diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-12-11 22:11:16 -0800 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-12-23 22:15:09 -0800 |
| commit | 68621afd2e203d82b6f53bf4ede951827fa98db8 (patch) | |
| tree | 60899decd0062ce7786592e49ca77ab6f80d22fd /lib | |
| parent | 0e230993d51d0ecded40d5235ada4f2f64036b26 (diff) | |
| download | zig-68621afd2e203d82b6f53bf4ede951827fa98db8.tar.gz zig-68621afd2e203d82b6f53bf4ede951827fa98db8.zip | |
std.tar: update fs API calls to take io argument
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/compiler/aro/aro/Compilation.zig | 3 | ||||
| -rw-r--r-- | lib/std/Build/Cache/Path.zig | 4 | ||||
| -rw-r--r-- | lib/std/Io.zig | 2 | ||||
| -rw-r--r-- | lib/std/Io/Dir.zig | 12 | ||||
| -rw-r--r-- | lib/std/Io/File.zig | 3 | ||||
| -rw-r--r-- | lib/std/Io/Threaded.zig | 50 | ||||
| -rw-r--r-- | lib/std/fs/test.zig | 57 | ||||
| -rw-r--r-- | lib/std/tar.zig | 54 | ||||
| -rw-r--r-- | lib/std/tar/test.zig | 4 | ||||
| -rw-r--r-- | lib/std/zig/WindowsSdk.zig | 2 | ||||
| -rw-r--r-- | lib/std/zig/parser_test.zig | 2 |
11 files changed, 96 insertions, 97 deletions
diff --git a/lib/compiler/aro/aro/Compilation.zig b/lib/compiler/aro/aro/Compilation.zig index b3e4d5544d..a78f18dd74 100644 --- a/lib/compiler/aro/aro/Compilation.zig +++ b/lib/compiler/aro/aro/Compilation.zig @@ -2162,8 +2162,9 @@ pub fn locSlice(comp: *const Compilation, loc: Source.Location) []const u8 { } pub fn getSourceMTimeUncached(comp: *const Compilation, source_id: Source.Id) ?u64 { + const io = comp.io; const source = comp.getSource(source_id); - if (comp.cwd.statFile(source.path)) |stat| { + if (comp.cwd.statFile(io, source.path, .{})) |stat| { return std.math.cast(u64, stat.mtime.toSeconds()); } else |_| { return null; diff --git a/lib/std/Build/Cache/Path.zig b/lib/std/Build/Cache/Path.zig index 759eb143b8..54104afa41 100644 --- a/lib/std/Build/Cache/Path.zig +++ b/lib/std/Build/Cache/Path.zig @@ -94,14 +94,14 @@ pub fn makeOpenPath(p: Path, sub_path: []const u8, opts: Io.Dir.OpenOptions) !Io return p.root_dir.handle.makeOpenPath(joined_path, opts); } -pub fn statFile(p: Path, sub_path: []const u8) !Io.Dir.Stat { +pub fn statFile(p: Path, io: Io, sub_path: []const u8) !Io.Dir.Stat { var buf: [fs.max_path_bytes]u8 = undefined; const joined_path = if (p.sub_path.len == 0) sub_path else p: { break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ p.sub_path, sub_path, }) catch return error.NameTooLong; }; - return p.root_dir.handle.statFile(joined_path); + return p.root_dir.handle.statFile(io, joined_path, .{}); } pub fn atomicFile( diff --git a/lib/std/Io.zig b/lib/std/Io.zig index b76cbebe3a..83a2e940bf 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -671,7 +671,7 @@ pub const VTable = struct { dirMakeOpenPath: *const fn (?*anyopaque, Dir, []const u8, Dir.Permissions, Dir.OpenOptions) Dir.MakeOpenPathError!Dir, dirOpenDir: *const fn (?*anyopaque, Dir, []const u8, Dir.OpenOptions) Dir.OpenError!Dir, dirStat: *const fn (?*anyopaque, Dir) Dir.StatError!Dir.Stat, - dirStatPath: *const fn (?*anyopaque, Dir, []const u8, Dir.StatPathOptions) Dir.StatPathError!File.Stat, + dirStatFile: *const fn (?*anyopaque, Dir, []const u8, Dir.StatFileOptions) Dir.StatFileError!File.Stat, dirAccess: *const fn (?*anyopaque, Dir, []const u8, Dir.AccessOptions) Dir.AccessError!void, dirCreateFile: *const fn (?*anyopaque, Dir, []const u8, File.CreateFlags) File.OpenError!File, dirOpenFile: *const fn (?*anyopaque, Dir, []const u8, File.OpenFlags) File.OpenError!File, diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig index 085667edca..0bc3982a61 100644 --- a/lib/std/Io/Dir.zig +++ b/lib/std/Io/Dir.zig @@ -669,7 +669,7 @@ pub fn makeDirAbsolute(io: Io, absolute_path: []const u8, permissions: Permissio test makeDirAbsolute {} -pub const MakePathError = MakeError || StatPathError; +pub const MakePathError = MakeError || StatFileError; /// Creates parent directories with default permissions as necessary to ensure /// `sub_path` exists as a directory. @@ -708,7 +708,7 @@ pub fn makePathStatus(dir: Dir, io: Io, sub_path: []const u8, permissions: Permi return io.vtable.dirMakePath(io.userdata, dir, sub_path, permissions); } -pub const MakeOpenPathError = MakeError || OpenError || StatPathError; +pub const MakeOpenPathError = MakeError || OpenError || StatFileError; pub const MakeOpenPathOptions = struct { open_options: OpenOptions = .{}, @@ -734,9 +734,9 @@ pub fn stat(dir: Dir, io: Io) StatError!Stat { return io.vtable.dirStat(io.userdata, dir); } -pub const StatPathError = File.OpenError || File.StatError; +pub const StatFileError = File.OpenError || File.StatError; -pub const StatPathOptions = struct { +pub const StatFileOptions = struct { follow_symlinks: bool = true, }; @@ -752,8 +752,8 @@ pub const StatPathOptions = struct { /// * On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). /// * On WASI, `sub_path` should be encoded as valid UTF-8. /// * On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. -pub fn statPath(dir: Dir, io: Io, sub_path: []const u8, options: StatPathOptions) StatPathError!Stat { - return io.vtable.dirStatPath(io.userdata, dir, sub_path, options); +pub fn statFile(dir: Dir, io: Io, sub_path: []const u8, options: StatFileOptions) StatFileError!Stat { + return io.vtable.dirStatFile(io.userdata, dir, sub_path, options); } pub const RealPathError = error{ diff --git a/lib/std/Io/File.zig b/lib/std/Io/File.zig index ccf18a8f56..3c04909d46 100644 --- a/lib/std/Io/File.zig +++ b/lib/std/Io/File.zig @@ -372,6 +372,7 @@ pub const Permissions = std.options.FilePermissions orelse if (is_windows) enum( _, pub const default_dir: @This() = .default_file; + pub const executable_file: @This() = .default_file; pub const has_executable_bit = false; const windows = std.os.windows; @@ -401,6 +402,7 @@ pub const Permissions = std.options.FilePermissions orelse if (is_windows) enum( /// process-scoped "umask" setting to adjust this number for file creation. default_file = 0o666, default_dir = 0o755, + executable_file = 0o777, _, pub const has_executable_bit = true; @@ -428,6 +430,7 @@ pub const Permissions = std.options.FilePermissions orelse if (is_windows) enum( } else enum(u0) { default_file = 0, pub const default_dir: @This() = .default_file; + pub const executable_file: @This() = .default_file; pub const has_executable_bit = false; }; diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 2fb0f3ad1f..d4c4da3990 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -708,7 +708,7 @@ pub fn io(t: *Threaded) Io { .dirMakePath = dirMakePath, .dirMakeOpenPath = dirMakeOpenPath, .dirStat = dirStat, - .dirStatPath = dirStatPath, + .dirStatFile = dirStatFile, .dirAccess = dirAccess, .dirCreateFile = dirCreateFile, .dirOpenFile = dirOpenFile, @@ -840,7 +840,7 @@ pub fn ioBasic(t: *Threaded) Io { .dirMakePath = dirMakePath, .dirMakeOpenPath = dirMakeOpenPath, .dirStat = dirStat, - .dirStatPath = dirStatPath, + .dirStatFile = dirStatFile, .dirAccess = dirAccess, .dirCreateFile = dirCreateFile, .dirOpenFile = dirOpenFile, @@ -1623,7 +1623,7 @@ fn dirMakePath( // could cause an infinite loop check_dir: { // workaround for windows, see https://github.com/ziglang/zig/issues/16738 - const fstat = dirStatPath(t, dir, component.path, .{}) catch |stat_err| switch (stat_err) { + const fstat = dirStatFile(t, dir, component.path, .{}) catch |stat_err| switch (stat_err) { error.IsDir => break :check_dir, else => |e| return e, }; @@ -1752,7 +1752,7 @@ fn dirMakeOpenPathWindows( // could cause an infinite loop check_dir: { // workaround for windows, see https://github.com/ziglang/zig/issues/16738 - const fstat = dirStatPathWindows(t, dir, component.path, .{ + const fstat = dirStatFileWindows(t, dir, component.path, .{ .follow_symlinks = options.follow_symlinks, }) catch |stat_err| switch (stat_err) { error.IsDir => break :check_dir, @@ -1806,19 +1806,19 @@ fn dirStat(userdata: ?*anyopaque, dir: Dir) Dir.StatError!Dir.Stat { return fileStat(t, file); } -const dirStatPath = switch (native_os) { - .linux => dirStatPathLinux, - .windows => dirStatPathWindows, - .wasi => dirStatPathWasi, - else => dirStatPathPosix, +const dirStatFile = switch (native_os) { + .linux => dirStatFileLinux, + .windows => dirStatFileWindows, + .wasi => dirStatFileWasi, + else => dirStatFilePosix, }; -fn dirStatPathLinux( +fn dirStatFileLinux( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, - options: Dir.StatPathOptions, -) Dir.StatPathError!File.Stat { + options: Dir.StatFileOptions, +) Dir.StatFileError!File.Stat { const t: *Threaded = @ptrCast(@alignCast(userdata)); const current_thread = Thread.getCurrent(t); const linux = std.os.linux; @@ -1875,12 +1875,12 @@ fn dirStatPathLinux( } } -fn dirStatPathPosix( +fn dirStatFilePosix( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, - options: Dir.StatPathOptions, -) Dir.StatPathError!File.Stat { + options: Dir.StatFileOptions, +) Dir.StatFileError!File.Stat { const t: *Threaded = @ptrCast(@alignCast(userdata)); const current_thread = Thread.getCurrent(t); @@ -1889,10 +1889,10 @@ fn dirStatPathPosix( const flags: u32 = if (!options.follow_symlinks) posix.AT.SYMLINK_NOFOLLOW else 0; - return posixStatPath(current_thread, dir.handle, sub_path_posix, flags); + return posixStatFile(current_thread, dir.handle, sub_path_posix, flags); } -fn posixStatPath(current_thread: *Thread, dir_fd: posix.fd_t, sub_path: [:0]const u8, flags: u32) Dir.StatPathError!File.Stat { +fn posixStatFile(current_thread: *Thread, dir_fd: posix.fd_t, sub_path: [:0]const u8, flags: u32) Dir.StatFileError!File.Stat { try current_thread.beginSyscall(); while (true) { var stat = std.mem.zeroes(posix.Stat); @@ -1927,12 +1927,12 @@ fn posixStatPath(current_thread: *Thread, dir_fd: posix.fd_t, sub_path: [:0]cons } } -fn dirStatPathWindows( +fn dirStatFileWindows( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, - options: Dir.StatPathOptions, -) Dir.StatPathError!File.Stat { + options: Dir.StatFileOptions, +) Dir.StatFileError!File.Stat { const t: *Threaded = @ptrCast(@alignCast(userdata)); const file = try dirOpenFileWindows(t, dir, sub_path, .{ .follow_symlinks = options.follow_symlinks, @@ -1941,13 +1941,13 @@ fn dirStatPathWindows( return fileStatWindows(t, file); } -fn dirStatPathWasi( +fn dirStatFileWasi( userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, - options: Dir.StatPathOptions, -) Dir.StatPathError!File.Stat { - if (builtin.link_libc) return dirStatPathPosix(userdata, dir, sub_path, options); + options: Dir.StatFileOptions, +) Dir.StatFileError!File.Stat { + if (builtin.link_libc) return dirStatFilePosix(userdata, dir, sub_path, options); const t: *Threaded = @ptrCast(@alignCast(userdata)); const current_thread = Thread.getCurrent(t); const wasi = std.os.wasi; @@ -3629,7 +3629,7 @@ fn dirReadIllumos(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) D if (std.mem.eql(u8, name, ".") or std.mem.eql(u8, name, "..")) continue; // illumos dirent doesn't expose type, so we have to call stat to get it. - const stat = try posixStatPath(current_thread, dr.dir.handle, name, posix.AT.SYMLINK_NOFOLLOW); + const stat = try posixStatFile(current_thread, dr.dir.handle, name, posix.AT.SYMLINK_NOFOLLOW); buffer[buffer_index] = .{ .name = name, diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 3a4b551ae8..dd9b21d77b 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -160,8 +160,8 @@ fn testWithPathTypeIfSupported(comptime path_type: PathType, comptime path_sep: // For use in test setup. If the symlink creation fails on Windows with // AccessDenied, then make the test failure silent (it is not a Zig failure). -fn setupSymlink(dir: Dir, target: []const u8, link: []const u8, flags: SymLinkFlags) !void { - return dir.symLink(target, link, flags) catch |err| switch (err) { +fn setupSymlink(io: Io, dir: Dir, target: []const u8, link: []const u8, flags: SymLinkFlags) !void { + return dir.symLink(io, target, link, flags) catch |err| switch (err) { // Symlink requires admin privileges on windows, so this test can legitimately fail. error.AccessDenied => if (native_os == .windows) return error.SkipZigTest else return err, else => return err, @@ -193,15 +193,15 @@ test "Dir.readLink" { const canonical_dir_target_path = try ctx.toCanonicalPathSep(dir_target_path); // test 1: symlink to a file - try setupSymlink(ctx.dir, file_target_path, "symlink1", .{}); - try testReadLink(ctx.dir, canonical_file_target_path, "symlink1"); + try setupSymlink(io, ctx.dir, file_target_path, "symlink1", .{}); + try testReadLink(io, ctx.dir, canonical_file_target_path, "symlink1"); if (builtin.os.tag == .windows) { try testReadLinkW(testing.allocator, ctx.dir, canonical_file_target_path, "symlink1"); } // test 2: symlink to a directory (can be different on Windows) - try setupSymlink(ctx.dir, dir_target_path, "symlink2", .{ .is_directory = true }); - try testReadLink(ctx.dir, canonical_dir_target_path, "symlink2"); + try setupSymlink(io, ctx.dir, dir_target_path, "symlink2", .{ .is_directory = true }); + try testReadLink(io, ctx.dir, canonical_dir_target_path, "symlink2"); if (builtin.os.tag == .windows) { try testReadLinkW(testing.allocator, ctx.dir, canonical_dir_target_path, "symlink2"); } @@ -211,8 +211,8 @@ test "Dir.readLink" { const canonical_parent_file = try ctx.toCanonicalPathSep(parent_file); var subdir = try ctx.dir.makeOpenPath("subdir", .{}); defer subdir.close(io); - try setupSymlink(subdir, canonical_parent_file, "relative-link.txt", .{}); - try testReadLink(subdir, canonical_parent_file, "relative-link.txt"); + try setupSymlink(io, subdir, canonical_parent_file, "relative-link.txt", .{}); + try testReadLink(io, subdir, canonical_parent_file, "relative-link.txt"); if (builtin.os.tag == .windows) { try testReadLinkW(testing.allocator, subdir, canonical_parent_file, "relative-link.txt"); } @@ -246,9 +246,9 @@ test "Dir.readLink on non-symlinks" { }.impl); } -fn testReadLink(dir: Dir, target_path: []const u8, symlink_path: []const u8) !void { +fn testReadLink(io: Io, dir: Dir, target_path: []const u8, symlink_path: []const u8) !void { var buffer: [fs.max_path_bytes]u8 = undefined; - const actual = try dir.readLink(symlink_path, buffer[0..]); + const actual = try dir.readLink(io, symlink_path, &buffer); try testing.expectEqualStrings(target_path, actual); } @@ -284,7 +284,7 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { const dir_target_path = try ctx.transformPath("subdir"); try ctx.dir.makeDir(io, dir_target_path, .default_dir); - try setupSymlink(ctx.dir, dir_target_path, "symlink", .{ .is_directory = true }); + try setupSymlink(io, ctx.dir, dir_target_path, "symlink", .{ .is_directory = true }); var symlink: Dir = switch (builtin.target.os.tag) { .windows => windows_symlink: { @@ -809,11 +809,11 @@ test "Dir.statFile" { const io = ctx.io; const test_file_name = try ctx.transformPath("test_file"); - try testing.expectError(error.FileNotFound, ctx.dir.statFile(test_file_name)); + try testing.expectError(error.FileNotFound, ctx.dir.statFile(io, test_file_name, .{})); try ctx.dir.writeFile(io, .{ .sub_path = test_file_name, .data = "" }); - const stat = try ctx.dir.statFile(test_file_name); + const stat = try ctx.dir.statFile(io, test_file_name, .{}); try testing.expectEqual(File.Kind.file, stat.kind); } }.impl); @@ -822,12 +822,13 @@ test "Dir.statFile" { test "statFile on dangling symlink" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { + const io = ctx.io; const symlink_name = try ctx.transformPath("dangling-symlink"); const symlink_target = "." ++ fs.path.sep_str ++ "doesnotexist"; - try setupSymlink(ctx.dir, symlink_target, symlink_name, .{}); + try setupSymlink(io, ctx.dir, symlink_target, symlink_name, .{}); - try std.testing.expectError(error.FileNotFound, ctx.dir.statFile(symlink_name)); + try std.testing.expectError(error.FileNotFound, ctx.dir.statFile(io, symlink_name, .{})); } }.impl); } @@ -1206,7 +1207,7 @@ test "deleteTree does not follow symlinks" { var a = try tmp.dir.makeOpenPath("a", .{}); defer a.close(io); - try setupSymlink(a, "../b", "b", .{ .is_directory = true }); + try setupSymlink(io, a, "../b", "b", .{ .is_directory = true }); } try tmp.dir.deleteTree(io, "a"); @@ -1223,7 +1224,7 @@ test "deleteTree on a symlink" { // Symlink to a file try tmp.dir.writeFile(io, .{ .sub_path = "file", .data = "" }); - try setupSymlink(tmp.dir, "file", "filelink", .{}); + try setupSymlink(io, tmp.dir, "file", "filelink", .{}); try tmp.dir.deleteTree(io, "filelink"); try testing.expectError(error.FileNotFound, tmp.dir.access(io, "filelink", .{})); @@ -1231,7 +1232,7 @@ test "deleteTree on a symlink" { // Symlink to a directory try tmp.dir.makePath(io, "dir"); - try setupSymlink(tmp.dir, "dir", "dirlink", .{ .is_directory = true }); + try setupSymlink(io, tmp.dir, "dir", "dirlink", .{ .is_directory = true }); try tmp.dir.deleteTree(io, "dirlink"); try testing.expectError(error.FileNotFound, tmp.dir.access(io, "dirlink", .{})); @@ -1337,7 +1338,7 @@ test "makepath through existing valid symlink" { defer tmp.cleanup(); try tmp.dir.makeDir(io, "realfolder", .default_dir); - try setupSymlink(tmp.dir, "." ++ fs.path.sep_str ++ "realfolder", "working-symlink", .{}); + try setupSymlink(io, tmp.dir, "." ++ fs.path.sep_str ++ "realfolder", "working-symlink", .{}); try tmp.dir.makePath(io, "working-symlink" ++ fs.path.sep_str ++ "in-realfolder"); @@ -2178,12 +2179,12 @@ test "invalid UTF-8/WTF-8 paths" { try testing.expectError(expected_err, ctx.dir.rename(invalid_path, ctx.dir, invalid_path, io)); - try testing.expectError(expected_err, ctx.dir.symLink(invalid_path, invalid_path, .{})); + try testing.expectError(expected_err, ctx.dir.symLink(io, invalid_path, invalid_path, .{})); if (native_os == .wasi) { try testing.expectError(expected_err, ctx.dir.symLinkWasi(invalid_path, invalid_path, .{})); } - try testing.expectError(expected_err, ctx.dir.readLink(invalid_path, &[_]u8{})); + try testing.expectError(expected_err, ctx.dir.readLink(io, invalid_path, &[_]u8{})); if (native_os == .wasi) { try testing.expectError(expected_err, ctx.dir.readLinkWasi(invalid_path, &[_]u8{})); } @@ -2386,14 +2387,16 @@ test "File.Writer sendfile with buffered contents" { test "readlink on Windows" { if (native_os != .windows) return error.SkipZigTest; - try testReadlink("C:\\ProgramData", "C:\\Users\\All Users"); - try testReadlink("C:\\Users\\Default", "C:\\Users\\Default User"); - try testReadlink("C:\\Users", "C:\\Documents and Settings"); + const io = testing.io; + + try testReadLinkWindows(io, "C:\\ProgramData", "C:\\Users\\All Users"); + try testReadLinkWindows(io, "C:\\Users\\Default", "C:\\Users\\Default User"); + try testReadLinkWindows(io, "C:\\Users", "C:\\Documents and Settings"); } -fn testReadlink(target_path: []const u8, symlink_path: []const u8) !void { +fn testReadLinkWindows(io: Io, target_path: []const u8, symlink_path: []const u8) !void { var buffer: [fs.max_path_bytes]u8 = undefined; - const given = try Dir.readLinkAbsolute(symlink_path, buffer[0..]); + const given = try Dir.readLinkAbsolute(io, symlink_path, &buffer); try expect(mem.eql(u8, target_path, given)); } @@ -2424,6 +2427,6 @@ test "readlinkat" { // read the link var buffer: [fs.max_path_bytes]u8 = undefined; - const read_link = try tmp.dir.readLink("link", &buffer); + const read_link = try tmp.dir.readLink(io, "link", &buffer); try expect(mem.eql(u8, "file.txt", read_link)); } diff --git a/lib/std/tar.zig b/lib/std/tar.zig index 92dc8b88f9..d45aa99443 100644 --- a/lib/std/tar.zig +++ b/lib/std/tar.zig @@ -653,11 +653,11 @@ fn createDirAndFile(io: Io, dir: Io.Dir, file_name: []const u8, permissions: Io. // Creates a symbolic link at path `file_name` which points to `link_name`. fn createDirAndSymlink(io: Io, dir: Io.Dir, link_name: []const u8, file_name: []const u8) !void { - dir.symLink(link_name, file_name, .{}) catch |err| { + dir.symLink(io, link_name, file_name, .{}) catch |err| { if (err == error.FileNotFound) { if (std.fs.path.dirname(file_name)) |dir_name| { try dir.makePath(io, dir_name); - return try dir.symLink(link_name, file_name, .{}); + return try dir.symLink(io, link_name, file_name, .{}); } } return err; @@ -996,15 +996,15 @@ test pipeToFileSystem { return err; }; - try testing.expectError(error.FileNotFound, dir.statFile("empty")); - try testing.expect((try dir.statFile("a/file")).kind == .file); - try testing.expect((try dir.statFile("b/symlink")).kind == .file); // statFile follows symlink + try testing.expectError(error.FileNotFound, dir.statFile(io, "empty", .{})); + try testing.expect((try dir.statFile(io, "a/file", .{})).kind == .file); + try testing.expect((try dir.statFile(io, "b/symlink", .{})).kind == .file); // statFile follows symlink var buf: [32]u8 = undefined; try testing.expectEqualSlices( u8, "../a/file", - normalizePath(try dir.readLink("b/symlink", &buf)), + normalizePath(buf[0..try dir.readLink(io, "b/symlink", &buf)]), ); } @@ -1120,28 +1120,18 @@ fn normalizePath(bytes: []u8) []u8 { // File system mode based on tar header mode and mode_mode options. fn filePermissions(mode: u32, options: PipeOptions) Io.File.Permissions { - const default_mode = 0o666; - - if (!Io.File.Permissions.has_executable_bit or options.mode_mode == .ignore) - return .fromMode(default_mode); - - const S = std.posix.S; - - // The mode from the tar file is inspected for the owner executable bit. - if (mode & S.IXUSR == 0) - return .fromMode(default_mode); - - // This bit is copied to the group and other executable bits. - // Other bits of the mode are left as the default when creating files. - return .fromMode(default_mode | S.IXUSR | S.IXGRP | S.IXOTH); + return if (!Io.File.Permissions.has_executable_bit or options.mode_mode == .ignore or (mode & 0o100) == 0) + .default_file + else + .executable_file; } test filePermissions { if (!Io.File.Permissions.has_executable_bit) return error.SkipZigTest; - try testing.expectEqual(0o666, filePermissions(0o744, PipeOptions{ .mode_mode = .ignore })); - try testing.expectEqual(0o777, filePermissions(0o744, PipeOptions{})); - try testing.expectEqual(0o666, filePermissions(0o644, PipeOptions{})); - try testing.expectEqual(0o666, filePermissions(0o655, PipeOptions{})); + try testing.expectEqual(.default_file, filePermissions(0o744, .{ .mode_mode = .ignore })); + try testing.expectEqual(.executable_file, filePermissions(0o744, .{})); + try testing.expectEqual(.default_file, filePermissions(0o644, .{})); + try testing.expectEqual(.default_file, filePermissions(0o655, .{})); } test "executable bit" { @@ -1167,19 +1157,21 @@ test "executable bit" { return err; }; - const fs = try tmp.dir.statFile("a/file"); + const fs = try tmp.dir.statFile(io, "a/file", .{}); try testing.expect(fs.kind == .file); + const mode = fs.permissions.toMode(); + if (opt == .executable_bit_only) { // Executable bit is set for user, group and others - try testing.expect(fs.mode & S.IXUSR > 0); - try testing.expect(fs.mode & S.IXGRP > 0); - try testing.expect(fs.mode & S.IXOTH > 0); + try testing.expect(mode & S.IXUSR > 0); + try testing.expect(mode & S.IXGRP > 0); + try testing.expect(mode & S.IXOTH > 0); } if (opt == .ignore) { - try testing.expect(fs.mode & S.IXUSR == 0); - try testing.expect(fs.mode & S.IXGRP == 0); - try testing.expect(fs.mode & S.IXOTH == 0); + try testing.expect(mode & S.IXUSR == 0); + try testing.expect(mode & S.IXGRP == 0); + try testing.expect(mode & S.IXOTH == 0); } } } diff --git a/lib/std/tar/test.zig b/lib/std/tar/test.zig index b3fbd8f4b3..61aeb03519 100644 --- a/lib/std/tar/test.zig +++ b/lib/std/tar/test.zig @@ -504,6 +504,6 @@ test "case sensitivity" { }; // on case sensitive os both files are created - try testing.expect((try root.dir.statFile("alacritty/darkermatrix.yml")).kind == .file); - try testing.expect((try root.dir.statFile("alacritty/Darkermatrix.yml")).kind == .file); + try testing.expect((try root.dir.statFile(io, "alacritty/darkermatrix.yml", .{})).kind == .file); + try testing.expect((try root.dir.statFile(io, "alacritty/Darkermatrix.yml", .{})).kind == .file); } diff --git a/lib/std/zig/WindowsSdk.zig b/lib/std/zig/WindowsSdk.zig index 3f6d58b6ba..6da25822ca 100644 --- a/lib/std/zig/WindowsSdk.zig +++ b/lib/std/zig/WindowsSdk.zig @@ -1012,7 +1012,7 @@ const MsvcLibDir = struct { var dir = std.fs.openDirAbsolute(lib_dir_path, .{}) catch return false; defer dir.close(io); - const stat = dir.statFile("vcruntime.lib") catch return false; + const stat = dir.statFile(io, "vcruntime.lib", .{}) catch return false; if (stat.kind != .file) return false; diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 6064d3b540..9d9a6a48ce 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -4539,7 +4539,7 @@ test "zig fmt: Only indent multiline string literals in function calls" { test "zig fmt: Don't add extra newline after if" { try testCanonical( \\pub fn atomicSymLink(allocator: Allocator, existing_path: []const u8, new_path: []const u8) !void { - \\ if (cwd().symLink(existing_path, new_path, .{})) { + \\ if (foo().bar(existing_path, new_path, .{})) { \\ return; \\ } \\} |
