diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-11-30 13:32:11 -0500 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-11-30 13:32:11 -0500 |
| commit | d039fed831cfc219821b58f1d819d79ad49dc652 (patch) | |
| tree | 02874006e87e02473a3ad89c0259e55fa235b3c4 /lib/std | |
| parent | 85e1e3b95f1f1699a842a5e889d8987692a829a4 (diff) | |
| download | zig-d039fed831cfc219821b58f1d819d79ad49dc652.tar.gz zig-d039fed831cfc219821b58f1d819d79ad49dc652.zip | |
introduce std.fs.Dir.openFile and std.fs.Dir.createFile
These functions have flags parameters which cover all the use cases. The
other functions are now deprecated.
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/fs.zig | 103 | ||||
| -rw-r--r-- | lib/std/fs/file.zig | 128 |
2 files changed, 144 insertions, 87 deletions
diff --git a/lib/std/fs.zig b/lib/std/fs.zig index f580cf2045..ec143056f1 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -698,29 +698,104 @@ pub const Dir = struct { self.* = undefined; } - /// Call `File.close` on the result when done. - pub fn openRead(self: Dir, sub_path: []const u8) File.OpenError!File { + /// Opens a file for reading or writing, without attempting to create a new file. + /// Call `File.close` to release the resource. + pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File { if (builtin.os == .windows) { const path_w = try os.windows.sliceToPrefixedFileW(sub_path); - return self.openReadW(&path_w); + return self.openFileW(&path_w, flags); } const path_c = try os.toPosixPath(sub_path); - return self.openReadC(&path_c); + return self.openFileC(&path_c, flags); } - /// Call `File.close` on the result when done. - pub fn openReadC(self: Dir, sub_path: [*:0]const u8) File.OpenError!File { + /// Same as `openFile` but the path parameter is null-terminated. + pub fn openFileC(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File.OpenError!File { if (builtin.os == .windows) { const path_w = try os.windows.cStrToPrefixedFileW(sub_path); - return self.openReadW(&path_w); + return self.openFileW(&path_w, flags); } const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; - const flags = O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC; - const fd = try os.openatC(self.fd, sub_path, flags, 0); - return File.openHandle(fd); + const os_flags = O_LARGEFILE | os.O_CLOEXEC | if (flags.write and flags.read) + @as(u32, os.O_RDWR) + else if (flags.write) + @as(u32, os.O_WRONLY) + else + @as(u32, os.O_RDONLY); + const fd = try os.openatC(self.fd, sub_path, os_flags, 0); + return File{ .handle = fd }; } - pub fn openReadW(self: Dir, sub_path_w: [*:0]const u16) File.OpenError!File { + /// Same as `openFile` but the path parameter is WTF-16 encoded. + pub fn openFileW(self: Dir, sub_path_w: [*:0]const u16, flags: File.OpenFlags) File.OpenError!File { + const w = os.windows; + const access_mask = w.SYNCHRONIZE | + (if (flags.read) @as(u32, w.GENERIC_READ) else 0) | + (if (flags.write) @as(u32, w.GENERIC_WRITE) else 0); + return self.openFileWindows(sub_path_w, access_mask, w.FILE_OPEN); + } + + /// Creates, opens, or overwrites a file with write access. + /// Call `File.close` on the result when done. + pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { + if (builtin.os == .windows) { + const path_w = try os.windows.sliceToPrefixedFileW(sub_path); + return self.createFileW(&path_w, flags); + } + const path_c = try os.toPosixPath(sub_path); + return self.createFileC(&path_c, flags); + } + + /// Same as `createFile` but the path parameter is null-terminated. + pub fn createFileC(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File { + if (builtin.os == .windows) { + const path_w = try os.windows.cStrToPrefixedFileW(sub_path_c); + return self.createFileW(&path_w, flags); + } + const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; + const os_flags = O_LARGEFILE | os.O_CREAT | os.O_CLOEXEC | + (if (flags.truncate) @as(u32, os.O_TRUNC) else 0) | + (if (flags.read) @as(u32, os.O_RDWR) else os.O_WRONLY) | + (if (flags.exclusive) @as(u32, os.O_EXCL) else 0); + const fd = try os.openatC(self.fd, sub_path_c, os_flags, flags.mode); + return File{ .handle = fd }; + } + + /// Same as `createFile` but the path parameter is WTF-16 encoded. + pub fn createFileW(self: Dir, sub_path_w: [*:0]const u16, flags: File.CreateFlags) File.OpenError!File { + const w = os.windows; + const access_mask = w.SYNCHRONIZE | w.GENERIC_WRITE | + (if (flags.read) @as(u32, w.GENERIC_READ) else 0); + const creation = if (flags.exclusive) + @as(u32, w.FILE_CREATE) + else if (flags.truncate) + @as(u32, w.FILE_OVERWRITE_IF) + else + @as(u32, w.FILE_OPEN_IF); + return self.openFileWindows(sub_path_w, access_mask, creation); + } + + /// Deprecated; call `openFile` directly. + pub fn openRead(self: Dir, sub_path: []const u8) File.OpenError!File { + return self.openFile(sub_path, .{}); + } + + /// Deprecated; call `openFileC` directly. + pub fn openReadC(self: Dir, sub_path: [*:0]const u8) File.OpenError!File { + return self.openFileC(sub_path, .{}); + } + + /// Deprecated; call `openFileW` directly. + pub fn openReadW(self: Dir, sub_path: [*:0]const u16) File.OpenError!File { + return self.openFileW(sub_path, .{}); + } + + pub fn openFileWindows( + self: Dir, + sub_path_w: [*:0]const u16, + access_mask: os.windows.ACCESS_MASK, + creation: os.windows.ULONG, + ) File.OpenError!File { const w = os.windows; var result = File{ .handle = undefined }; @@ -750,13 +825,13 @@ pub const Dir = struct { var io: w.IO_STATUS_BLOCK = undefined; const rc = w.ntdll.NtCreateFile( &result.handle, - w.GENERIC_READ | w.SYNCHRONIZE, + access_mask, &attr, &io, null, w.FILE_ATTRIBUTE_NORMAL, - w.FILE_SHARE_READ, - w.FILE_OPEN, + w.FILE_SHARE_WRITE | w.FILE_SHARE_READ | w.FILE_SHARE_DELETE, + creation, w.FILE_NON_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT, null, 0, diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 9cfdad3885..52e5f3e49e 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -25,105 +25,87 @@ pub const File = struct { pub const OpenError = windows.CreateFileError || os.OpenError; - /// Deprecated; call `std.fs.Dir.openRead` directly. + /// TODO https://github.com/ziglang/zig/issues/3802 + pub const OpenFlags = struct { + read: bool = true, + write: bool = false, + }; + + /// TODO https://github.com/ziglang/zig/issues/3802 + pub const CreateFlags = struct { + /// Whether the file will be created with read access. + read: bool = false, + + /// If the file already exists, and is a regular file, and the access + /// mode allows writing, it will be truncated to length 0. + truncate: bool = true, + + /// Ensures that this open call creates the file, otherwise causes + /// `error.FileAlreadyExists` to be returned. + exclusive: bool = false, + + /// For POSIX systems this is the file system mode the file will + /// be created with. + mode: Mode = default_mode, + }; + + /// Deprecated; call `std.fs.Dir.openFile` directly. pub fn openRead(path: []const u8) OpenError!File { - return std.fs.Dir.cwd().openRead(path); + return std.fs.Dir.cwd().openFile(path, .{}); } - /// Deprecated; call `std.fs.Dir.openReadC` directly. + /// Deprecated; call `std.fs.Dir.openFileC` directly. pub fn openReadC(path_c: [*:0]const u8) OpenError!File { - return std.fs.Dir.cwd().openReadC(path_c); + return std.fs.Dir.cwd().openFileC(path_c, .{}); } - /// Deprecated; call `std.fs.Dir.openReadW` directly. + /// Deprecated; call `std.fs.Dir.openFileW` directly. pub fn openReadW(path_w: [*]const u16) OpenError!File { - return std.fs.Dir.cwd().openReadW(path_w); + return std.fs.Dir.cwd().openFileW(path_w, .{}); } - /// Calls `openWriteMode` with `default_mode` for the mode. - /// TODO: deprecate this and move it to `std.fs.Dir`. + /// Deprecated; call `std.fs.Dir.createFile` directly. pub fn openWrite(path: []const u8) OpenError!File { - return openWriteMode(path, default_mode); + return std.fs.Dir.cwd().createFile(path, .{}); } - /// If the path does not exist it will be created. - /// If a file already exists in the destination it will be truncated. - /// Call close to clean up. - /// TODO: deprecate this and move it to `std.fs.Dir`. + /// Deprecated; call `std.fs.Dir.createFile` directly. pub fn openWriteMode(path: []const u8, file_mode: Mode) OpenError!File { - if (builtin.os == .windows) { - const path_w = try windows.sliceToPrefixedFileW(path); - return openWriteModeW(&path_w, file_mode); - } - const path_c = try os.toPosixPath(path); - return openWriteModeC(&path_c, file_mode); + return std.fs.Dir.cwd().createFile(path, .{ .mode = file_mode }); } - /// Same as `openWriteMode` except `path` is null-terminated. - /// TODO: deprecate this and move it to `std.fs.Dir`. - pub fn openWriteModeC(path: [*:0]const u8, file_mode: Mode) OpenError!File { - if (builtin.os == .windows) { - const path_w = try windows.cStrToPrefixedFileW(path); - return openWriteModeW(&path_w, file_mode); - } - const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; - const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC; - const fd = try os.openC(path, flags, file_mode); - return openHandle(fd); + /// Deprecated; call `std.fs.Dir.createFileC` directly. + pub fn openWriteModeC(path_c: [*:0]const u8, file_mode: Mode) OpenError!File { + return std.fs.Dir.cwd().createFileC(path_c, .{ .mode = file_mode }); } - /// Same as `openWriteMode` except `path` is null-terminated and UTF16LE encoded - /// TODO: deprecate this and move it to `std.fs.Dir`. + /// Deprecated; call `std.fs.Dir.createFileW` directly. pub fn openWriteModeW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File { - const handle = try windows.CreateFileW( - path_w, - windows.GENERIC_WRITE, - windows.FILE_SHARE_WRITE | windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE, - null, - windows.CREATE_ALWAYS, - windows.FILE_ATTRIBUTE_NORMAL, - null, - ); - return openHandle(handle); + return std.fs.Dir.cwd().createFileW(path_w, .{ .mode = file_mode }); } - /// If the path does not exist it will be created. - /// If a file already exists in the destination this returns OpenError.PathAlreadyExists - /// Call close to clean up. - /// TODO: deprecate this and move it to `std.fs.Dir`. + /// Deprecated; call `std.fs.Dir.createFile` directly. pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File { - if (builtin.os == .windows) { - const path_w = try windows.sliceToPrefixedFileW(path); - return openWriteNoClobberW(&path_w, file_mode); - } - const path_c = try os.toPosixPath(path); - return openWriteNoClobberC(&path_c, file_mode); + return std.fs.Dir.cwd().createFile(path, .{ + .mode = file_mode, + .exclusive = true, + }); } - /// TODO: deprecate this and move it to `std.fs.Dir`. - pub fn openWriteNoClobberC(path: [*:0]const u8, file_mode: Mode) OpenError!File { - if (builtin.os == .windows) { - const path_w = try windows.cStrToPrefixedFileW(path); - return openWriteNoClobberW(&path_w, file_mode); - } - const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; - const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_EXCL; - const fd = try os.openC(path, flags, file_mode); - return openHandle(fd); + /// Deprecated; call `std.fs.Dir.createFileC` directly. + pub fn openWriteNoClobberC(path_c: [*:0]const u8, file_mode: Mode) OpenError!File { + return std.fs.Dir.cwd().createFileC(path_c, .{ + .mode = file_mode, + .exclusive = true, + }); } - /// TODO: deprecate this and move it to `std.fs.Dir`. + /// Deprecated; call `std.fs.Dir.createFileW` directly. pub fn openWriteNoClobberW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File { - const handle = try windows.CreateFileW( - path_w, - windows.GENERIC_WRITE, - windows.FILE_SHARE_WRITE | windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE, - null, - windows.CREATE_NEW, - windows.FILE_ATTRIBUTE_NORMAL, - null, - ); - return openHandle(handle); + return std.fs.Dir.cwd().createFileW(path_w, .{ + .mode = file_mode, + .exclusive = true, + }); } pub fn openHandle(handle: os.fd_t) File { |
