diff --git a/doc/docgen.zig b/doc/docgen.zig index aed546680b..341863fb4a 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -45,7 +45,7 @@ pub fn main() !void { } } - var in_file = try fs.cwd().openFile(in_file_name, .{ .read = true }); + var in_file = try fs.cwd().openFile(in_file_name, .{ .mode = .read_only }); defer in_file.close(); var out_file = try fs.cwd().createFile(out_file_name, .{}); @@ -1866,7 +1866,7 @@ test "shell parsed" { // intentional space after "--build-option1 \" const shell_out = \\$ zig build test.zig \ - \\ --build-option1 \ + \\ --build-option1 \ \\ --build-option2 \\$ ./test ; diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 83c2992a45..182f7ccb6b 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -79,7 +79,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { var buf: [32]u8 = undefined; const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()}); - const file = try std.fs.cwd().openFile(path, .{ .write = true }); + const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only }); defer file.close(); try file.writer().writeAll(name); diff --git a/lib/std/fs.zig b/lib/std/fs.zig index a09f9f2ed2..fbf1b2ccc2 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -938,10 +938,10 @@ pub const Dir = struct { const w = os.wasi; var fdflags: w.fdflags_t = 0x0; var base: w.rights_t = 0x0; - if (flags.read) { + if (flags.isRead()) { base |= w.RIGHT.FD_READ | w.RIGHT.FD_TELL | w.RIGHT.FD_SEEK | w.RIGHT.FD_FILESTAT_GET; } - if (flags.write) { + if (flags.isWrite()) { fdflags |= w.FDFLAG.APPEND; base |= w.RIGHT.FD_WRITE | w.RIGHT.FD_TELL | @@ -988,12 +988,11 @@ pub const Dir = struct { if (!flags.allow_ctty) { os_flags |= os.O.NOCTTY; } - os_flags |= 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); + os_flags |= switch (flags.mode) { + .read_only => @as(u32, os.O.RDONLY), + .write_only => @as(u32, os.O.WRONLY), + .read_write => @as(u32, os.O.RDWR), + }; const fd = if (flags.intended_io_mode != .blocking) try std.event.Loop.instance.?.openatZ(self.fd, sub_path, os_flags, 0) else @@ -1045,8 +1044,8 @@ pub const Dir = struct { .handle = try w.OpenFile(sub_path_w, .{ .dir = self.fd, .access_mask = w.SYNCHRONIZE | - (if (flags.read) @as(u32, w.GENERIC_READ) else 0) | - (if (flags.write) @as(u32, w.GENERIC_WRITE) else 0), + (if (flags.isRead()) @as(u32, w.GENERIC_READ) else 0) | + (if (flags.isWrite()) @as(u32, w.GENERIC_WRITE) else 0), .creation = w.FILE_OPEN, .io_mode = flags.intended_io_mode, }), @@ -2042,12 +2041,11 @@ pub const Dir = struct { const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path); return self.accessW(sub_path_w.span().ptr, flags); } - const os_mode = if (flags.write and flags.read) - @as(u32, os.R_OK | os.W_OK) - else if (flags.write) - @as(u32, os.W_OK) - else - @as(u32, os.F_OK); + const os_mode = switch (flags.mode) { + .read_only => @as(u32, os.F_OK), + .write_only => @as(u32, os.W_OK), + .read_write => @as(u32, os.R_OK | os.W_OK), + }; const result = if (need_async_thread and flags.intended_io_mode != .blocking) std.event.Loop.instance.?.faccessatZ(self.fd, sub_path, os_mode, 0) else diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 6fa46579fd..ff71c82d2b 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -69,12 +69,17 @@ pub const File = struct { Unexpected, } || os.OpenError || os.FlockError; + pub const OpenMode = enum { + read_only, + write_only, + read_write, + }; + pub const Lock = enum { None, Shared, Exclusive }; /// TODO https://github.com/ziglang/zig/issues/3802 pub const OpenFlags = struct { - read: bool = true, - write: bool = false, + mode: OpenMode = .read_only, /// Open the file with an advisory lock to coordinate with other processes /// accessing it at the same time. An exclusive lock will prevent other @@ -118,6 +123,14 @@ pub const File = struct { /// Set this to allow the opened file to automatically become the /// controlling TTY for the current process. allow_ctty: bool = false, + + pub fn isRead(self: OpenFlags) bool { + return self.mode != .write_only; + } + + pub fn isWrite(self: OpenFlags) bool { + return self.mode != .read_only; + } }; /// TODO https://github.com/ziglang/zig/issues/3802 diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 1ab6608327..1cb5dc3a04 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -319,9 +319,9 @@ test "file operations on directories" { try testing.expectError(error.IsDir, tmp_dir.dir.readFileAlloc(testing.allocator, test_dir_name, std.math.maxInt(usize))); }, } - // Note: The `.write = true` is necessary to ensure the error occurs on all platforms. + // Note: The `.mode = .read_write` is necessary to ensure the error occurs on all platforms. // TODO: Add a read-only test as well, see https://github.com/ziglang/zig/issues/5732 - try testing.expectError(error.IsDir, tmp_dir.dir.openFile(test_dir_name, .{ .write = true })); + try testing.expectError(error.IsDir, tmp_dir.dir.openFile(test_dir_name, .{ .mode = .read_write })); switch (builtin.os.tag) { .wasi, .freebsd, .netbsd, .openbsd, .dragonfly => {}, diff --git a/lib/std/fs/watch.zig b/lib/std/fs/watch.zig index e2ec8b8061..469244fcd6 100644 --- a/lib/std/fs/watch.zig +++ b/lib/std/fs/watch.zig @@ -678,7 +678,7 @@ fn testWriteWatchWriteDelete(allocator: Allocator) !void { }; // overwrite line 2 - const file = try std.fs.cwd().openFile(file_path, .{ .read = true, .write = true }); + const file = try std.fs.cwd().openFile(file_path, .{ .mode = .read_write }); { defer file.close(); const write_contents = "lorem ipsum"; diff --git a/src/Cache.zig b/src/Cache.zig index a5995f64ea..993114905e 100644 --- a/src/Cache.zig +++ b/src/Cache.zig @@ -308,8 +308,7 @@ pub const Manifest = struct { // comparing the hashes on the files used for the cached item while (true) { if (self.cache.manifest_dir.openFile(&manifest_file_path, .{ - .read = true, - .write = true, + .mode = .read_write, .lock = .Exclusive, .lock_nonblocking = self.want_shared_lock, })) |manifest_file| { @@ -410,7 +409,7 @@ pub const Manifest = struct { cache_hash_file.path = try self.cache.gpa.dupe(u8, file_path); } - const this_file = fs.cwd().openFile(cache_hash_file.path.?, .{ .read = true }) catch |err| switch (err) { + const this_file = fs.cwd().openFile(cache_hash_file.path.?, .{ .mode = .read_only }) catch |err| switch (err) { error.FileNotFound => { try self.upgradeToExclusiveLock(); return false; diff --git a/src/test.zig b/src/test.zig index af0dbec24b..e02ea04f1c 100644 --- a/src/test.zig +++ b/src/test.zig @@ -958,14 +958,14 @@ pub const TestContext = struct { switch (update.case) { .Header => |expected_output| { - var file = try tmp.dir.openFile("test_case.h", .{ .read = true }); + var file = try tmp.dir.openFile("test_case.h", .{ .mode = .read_only }); defer file.close(); const out = try file.reader().readAllAlloc(arena, 5 * 1024 * 1024); try std.testing.expectEqualStrings(expected_output, out); }, .CompareObjectFile => |expected_output| { - var file = try tmp.dir.openFile(bin_name, .{ .read = true }); + var file = try tmp.dir.openFile(bin_name, .{ .mode = .read_only }); defer file.close(); const out = try file.reader().readAllAlloc(arena, 5 * 1024 * 1024);