authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-16 17:05:35-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:50-07:00
log3bf0ce65a514e6f86241364c4a11089e32b3ba57
tree17a43899fa0f1df18087a0af5d717e7f8b3034d1
parent7b1502f327f580254f5699754ec21521eac10cc7

fix miscellaneous compilation errors

- ILSEQ -> error.BadPathName - implement dirStatPath for WASI

11 files changed, 114 insertions(+), 224 deletions(-)

lib/compiler/aro/aro/Compilation.zig+2-1
......@@ -171,10 +171,11 @@ pub fn init(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics,
171171
172172/// Initialize Compilation with default environment,
173173/// pragma handlers and emulation mode set to target.
174pub fn initDefault(gpa: Allocator, arena: Allocator, diagnostics: *Diagnostics, cwd: std.fs.Dir) !Compilation {
174pub fn initDefault(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, cwd: std.fs.Dir) !Compilation {
175175 var comp: Compilation = .{
176176 .gpa = gpa,
177177 .arena = arena,
178 .io = io,
178179 .diagnostics = diagnostics,
179180 .environment = try Environment.loadAll(gpa),
180181 .cwd = cwd,
lib/std/Io/Threaded.zig+37-1
......@@ -174,7 +174,7 @@ pub fn io(t: *Threaded) Io {
174174 .dirStatPath = switch (builtin.os.tag) {
175175 .linux => dirStatPathLinux,
176176 .windows => @panic("TODO"),
177 .wasi => @panic("TODO"),
177 .wasi => dirStatPathWasi,
178178 else => dirStatPathPosix,
179179 },
180180 .fileStat = switch (builtin.os.tag) {
......@@ -984,6 +984,42 @@ fn dirStatPathPosix(
984984 }
985985}
986986
987fn dirStatPathWasi(
988 userdata: ?*anyopaque,
989 dir: Io.Dir,
990 sub_path: []const u8,
991 options: Io.Dir.StatPathOptions,
992) Io.Dir.StatPathError!Io.File.Stat {
993 if (builtin.link_libc) return dirStatPathPosix(userdata, dir, sub_path, options);
994 const t: *Threaded = @ptrCast(@alignCast(userdata));
995 const dir_fd = dir.handle;
996 const wasi = std.os.wasi;
997 const flags: wasi.lookupflags_t = .{
998 .SYMLINK_FOLLOW = @intFromBool(options.follow_symlinks),
999 };
1000 var stat: wasi.filestat_t = undefined;
1001 while (true) {
1002 try t.checkCancel();
1003 switch (wasi.path_filestat_get(dir_fd, flags, sub_path.ptr, sub_path.len, &stat)) {
1004 .SUCCESS => return statFromWasi(stat),
1005 .INTR => continue,
1006 .CANCELED => return error.Canceled,
1007
1008 .INVAL => |err| errnoBug(err),
1009 .BADF => |err| errnoBug(err), // Always a race condition.
1010 .NOMEM => return error.SystemResources,
1011 .ACCES => return error.AccessDenied,
1012 .FAULT => |err| errnoBug(err),
1013 .NAMETOOLONG => return error.NameTooLong,
1014 .NOENT => return error.FileNotFound,
1015 .NOTDIR => return error.FileNotFound,
1016 .NOTCAPABLE => return error.AccessDenied,
1017 .ILSEQ => return error.BadPathName,
1018 else => |err| return posix.unexpectedErrno(err),
1019 }
1020 }
1021}
1022
9871023fn fileStatPosix(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat {
9881024 const t: *Threaded = @ptrCast(@alignCast(userdata));
9891025
lib/std/fs/Dir.zig-4
......@@ -2500,10 +2500,6 @@ pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {
25002500 defer file.close();
25012501 return file.stat();
25022502 }
2503 if (native_os == .wasi and !builtin.link_libc) {
2504 const st = try std.os.fstatat_wasi(self.fd, sub_path, .{ .SYMLINK_FOLLOW = true });
2505 return Stat.fromWasi(st);
2506 }
25072503 var threaded: Io.Threaded = .init_single_threaded;
25082504 const io = threaded.io();
25092505 return Io.Dir.statPath(.{ .handle = self.fd }, io, sub_path, .{});
lib/std/fs/test.zig-22
......@@ -2031,37 +2031,28 @@ test "invalid UTF-8/WTF-8 paths" {
20312031 const invalid_path = try ctx.transformPath("\xFF");
20322032
20332033 try testing.expectError(expected_err, ctx.dir.openFile(invalid_path, .{}));
2034 try testing.expectError(expected_err, ctx.dir.openFileZ(invalid_path, .{}));
20352034
20362035 try testing.expectError(expected_err, ctx.dir.createFile(invalid_path, .{}));
2037 try testing.expectError(expected_err, ctx.dir.createFileZ(invalid_path, .{}));
20382036
20392037 try testing.expectError(expected_err, ctx.dir.makeDir(invalid_path));
2040 try testing.expectError(expected_err, ctx.dir.makeDirZ(invalid_path));
20412038
20422039 try testing.expectError(expected_err, ctx.dir.makePath(invalid_path));
20432040 try testing.expectError(expected_err, ctx.dir.makeOpenPath(invalid_path, .{}));
20442041
20452042 try testing.expectError(expected_err, ctx.dir.openDir(invalid_path, .{}));
2046 try testing.expectError(expected_err, ctx.dir.openDirZ(invalid_path, .{}));
20472043
20482044 try testing.expectError(expected_err, ctx.dir.deleteFile(invalid_path));
2049 try testing.expectError(expected_err, ctx.dir.deleteFileZ(invalid_path));
20502045
20512046 try testing.expectError(expected_err, ctx.dir.deleteDir(invalid_path));
2052 try testing.expectError(expected_err, ctx.dir.deleteDirZ(invalid_path));
20532047
20542048 try testing.expectError(expected_err, ctx.dir.rename(invalid_path, invalid_path));
2055 try testing.expectError(expected_err, ctx.dir.renameZ(invalid_path, invalid_path));
20562049
20572050 try testing.expectError(expected_err, ctx.dir.symLink(invalid_path, invalid_path, .{}));
2058 try testing.expectError(expected_err, ctx.dir.symLinkZ(invalid_path, invalid_path, .{}));
20592051 if (native_os == .wasi) {
20602052 try testing.expectError(expected_err, ctx.dir.symLinkWasi(invalid_path, invalid_path, .{}));
20612053 }
20622054
20632055 try testing.expectError(expected_err, ctx.dir.readLink(invalid_path, &[_]u8{}));
2064 try testing.expectError(expected_err, ctx.dir.readLinkZ(invalid_path, &[_]u8{}));
20652056 if (native_os == .wasi) {
20662057 try testing.expectError(expected_err, ctx.dir.readLinkWasi(invalid_path, &[_]u8{}));
20672058 }
......@@ -2075,7 +2066,6 @@ test "invalid UTF-8/WTF-8 paths" {
20752066 try testing.expectError(expected_err, ctx.dir.writeFile(.{ .sub_path = invalid_path, .data = "" }));
20762067
20772068 try testing.expectError(expected_err, ctx.dir.access(invalid_path, .{}));
2078 try testing.expectError(expected_err, ctx.dir.accessZ(invalid_path, .{}));
20792069
20802070 var dir = ctx.dir.adaptToNewApi();
20812071 try testing.expectError(expected_err, dir.updateFile(io, invalid_path, dir, invalid_path, .{}));
......@@ -2085,37 +2075,25 @@ test "invalid UTF-8/WTF-8 paths" {
20852075
20862076 if (native_os != .wasi) {
20872077 try testing.expectError(expected_err, ctx.dir.realpath(invalid_path, &[_]u8{}));
2088 try testing.expectError(expected_err, ctx.dir.realpathZ(invalid_path, &[_]u8{}));
20892078 try testing.expectError(expected_err, ctx.dir.realpathAlloc(testing.allocator, invalid_path));
20902079 }
20912080
20922081 try testing.expectError(expected_err, fs.rename(ctx.dir, invalid_path, ctx.dir, invalid_path));
2093 try testing.expectError(expected_err, fs.renameZ(ctx.dir, invalid_path, ctx.dir, invalid_path));
20942082
20952083 if (native_os != .wasi and ctx.path_type != .relative) {
20962084 try testing.expectError(expected_err, fs.copyFileAbsolute(invalid_path, invalid_path, .{}));
20972085 try testing.expectError(expected_err, fs.makeDirAbsolute(invalid_path));
2098 try testing.expectError(expected_err, fs.makeDirAbsoluteZ(invalid_path));
20992086 try testing.expectError(expected_err, fs.deleteDirAbsolute(invalid_path));
2100 try testing.expectError(expected_err, fs.deleteDirAbsoluteZ(invalid_path));
21012087 try testing.expectError(expected_err, fs.renameAbsolute(invalid_path, invalid_path));
2102 try testing.expectError(expected_err, fs.renameAbsoluteZ(invalid_path, invalid_path));
21032088 try testing.expectError(expected_err, fs.openDirAbsolute(invalid_path, .{}));
2104 try testing.expectError(expected_err, fs.openDirAbsoluteZ(invalid_path, .{}));
21052089 try testing.expectError(expected_err, fs.openFileAbsolute(invalid_path, .{}));
2106 try testing.expectError(expected_err, fs.openFileAbsoluteZ(invalid_path, .{}));
21072090 try testing.expectError(expected_err, fs.accessAbsolute(invalid_path, .{}));
2108 try testing.expectError(expected_err, fs.accessAbsoluteZ(invalid_path, .{}));
21092091 try testing.expectError(expected_err, fs.createFileAbsolute(invalid_path, .{}));
2110 try testing.expectError(expected_err, fs.createFileAbsoluteZ(invalid_path, .{}));
21112092 try testing.expectError(expected_err, fs.deleteFileAbsolute(invalid_path));
2112 try testing.expectError(expected_err, fs.deleteFileAbsoluteZ(invalid_path));
21132093 try testing.expectError(expected_err, fs.deleteTreeAbsolute(invalid_path));
21142094 var readlink_buf: [fs.max_path_bytes]u8 = undefined;
21152095 try testing.expectError(expected_err, fs.readLinkAbsolute(invalid_path, &readlink_buf));
2116 try testing.expectError(expected_err, fs.readLinkAbsoluteZ(invalid_path, &readlink_buf));
21172096 try testing.expectError(expected_err, fs.symLinkAbsolute(invalid_path, invalid_path, .{}));
2118 try testing.expectError(expected_err, fs.symLinkAbsoluteZ(invalid_path, invalid_path, .{}));
21192097 try testing.expectError(expected_err, fs.realpathAlloc(testing.allocator, invalid_path));
21202098 }
21212099 }
lib/std/os.zig-30
......@@ -201,36 +201,6 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix.
201201 }
202202}
203203
204pub const FstatatError = error{
205 SystemResources,
206 AccessDenied,
207 NameTooLong,
208 FileNotFound,
209 InvalidUtf8,
210 Unexpected,
211};
212
213/// WASI-only. Same as `fstatat` but targeting WASI.
214/// `pathname` should be encoded as valid UTF-8.
215/// See also `fstatat`.
216pub fn fstatat_wasi(dirfd: posix.fd_t, pathname: []const u8, flags: wasi.lookupflags_t) FstatatError!wasi.filestat_t {
217 var stat: wasi.filestat_t = undefined;
218 switch (wasi.path_filestat_get(dirfd, flags, pathname.ptr, pathname.len, &stat)) {
219 .SUCCESS => return stat,
220 .INVAL => unreachable,
221 .BADF => unreachable, // Always a race condition.
222 .NOMEM => return error.SystemResources,
223 .ACCES => return error.AccessDenied,
224 .FAULT => unreachable,
225 .NAMETOOLONG => return error.NameTooLong,
226 .NOENT => return error.FileNotFound,
227 .NOTDIR => return error.FileNotFound,
228 .NOTCAPABLE => return error.AccessDenied,
229 .ILSEQ => return error.InvalidUtf8,
230 else => |err| return posix.unexpectedErrno(err),
231 }
232}
233
234204pub fn fstat_wasi(fd: posix.fd_t) posix.FStatError!wasi.filestat_t {
235205 var stat: wasi.filestat_t = undefined;
236206 switch (wasi.fd_filestat_get(fd, &stat)) {
lib/std/os/windows.zig+4-4
......@@ -146,7 +146,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
146146 // call has failed. There is not really a sane way to handle
147147 // this other than retrying the creation after the OS finishes
148148 // the deletion.
149 std.Thread.sleep(std.time.ns_per_ms);
149 kernel32.Sleep(1);
150150 continue;
151151 },
152152 .VIRUS_INFECTED, .VIRUS_DELETED => return error.AntivirusInterference,
......@@ -604,7 +604,7 @@ pub const ReadFileError = error{
604604 BrokenPipe,
605605 /// The specified network name is no longer available.
606606 ConnectionResetByPeer,
607 OperationAborted,
607 Canceled,
608608 /// Unable to read file due to lock.
609609 LockViolation,
610610 /// Known to be possible when:
......@@ -654,7 +654,7 @@ pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64) ReadFileError!usiz
654654
655655pub const WriteFileError = error{
656656 SystemResources,
657 OperationAborted,
657 Canceled,
658658 BrokenPipe,
659659 NotOpenForWriting,
660660 /// The process cannot access the file because another process has locked
......@@ -694,7 +694,7 @@ pub fn WriteFile(
694694 switch (GetLastError()) {
695695 .INVALID_USER_BUFFER => return error.SystemResources,
696696 .NOT_ENOUGH_MEMORY => return error.SystemResources,
697 .OPERATION_ABORTED => return error.OperationAborted,
697 .OPERATION_ABORTED => return error.Canceled,
698698 .NOT_ENOUGH_QUOTA => return error.SystemResources,
699699 .IO_PENDING => unreachable,
700700 .NO_DATA => return error.BrokenPipe,
lib/std/posix.zig+31-99
......@@ -821,9 +821,6 @@ pub const ReadError = std.Io.File.ReadStreamingError;
821821/// The corresponding POSIX limit is `maxInt(isize)`.
822822pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
823823 if (buf.len == 0) return 0;
824 if (native_os == .windows) {
825 return windows.ReadFile(fd, buf, null);
826 }
827824 if (native_os == .wasi and !builtin.link_libc) {
828825 const iovs = [1]iovec{iovec{
829826 .base = buf.ptr,
......@@ -1181,7 +1178,7 @@ pub const WriteError = error{
11811178 PermissionDenied,
11821179 BrokenPipe,
11831180 SystemResources,
1184 OperationAborted,
1181 Canceled,
11851182 NotOpenForWriting,
11861183
11871184 /// The process cannot access the file because another process has locked
......@@ -1597,10 +1594,7 @@ pub fn openZ(file_path: [*:0]const u8, flags: O, perm: mode_t) OpenError!fd_t {
15971594 .PERM => return error.PermissionDenied,
15981595 .EXIST => return error.PathAlreadyExists,
15991596 .BUSY => return error.DeviceBusy,
1600 .ILSEQ => |err| if (native_os == .wasi)
1601 return error.InvalidUtf8
1602 else
1603 return unexpectedErrno(err),
1597 .ILSEQ => return error.BadPathName,
16041598 else => |err| return unexpectedErrno(err),
16051599 }
16061600 }
......@@ -1678,7 +1672,7 @@ pub fn openatWasi(
16781672 .EXIST => return error.PathAlreadyExists,
16791673 .BUSY => return error.DeviceBusy,
16801674 .NOTCAPABLE => return error.AccessDenied,
1681 .ILSEQ => return error.InvalidUtf8,
1675 .ILSEQ => return error.BadPathName,
16821676 else => |err| return unexpectedErrno(err),
16831677 }
16841678 }
......@@ -1773,10 +1767,7 @@ pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: O, mode: mode_t) O
17731767 .AGAIN => return error.WouldBlock,
17741768 .TXTBSY => return error.FileBusy,
17751769 .NXIO => return error.NoDevice,
1776 .ILSEQ => |err| if (native_os == .wasi)
1777 return error.InvalidUtf8
1778 else
1779 return unexpectedErrno(err),
1770 .ILSEQ => return error.BadPathName,
17801771 else => |err| return unexpectedErrno(err),
17811772 }
17821773 }
......@@ -2084,10 +2075,7 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin
20842075 .NOMEM => return error.SystemResources,
20852076 .NOSPC => return error.NoSpaceLeft,
20862077 .ROFS => return error.ReadOnlyFileSystem,
2087 .ILSEQ => |err| if (native_os == .wasi)
2088 return error.InvalidUtf8
2089 else
2090 return unexpectedErrno(err),
2078 .ILSEQ => return error.BadPathName,
20912079 else => |err| return unexpectedErrno(err),
20922080 }
20932081}
......@@ -2133,7 +2121,7 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c
21332121 .NOSPC => return error.NoSpaceLeft,
21342122 .ROFS => return error.ReadOnlyFileSystem,
21352123 .NOTCAPABLE => return error.AccessDenied,
2136 .ILSEQ => return error.InvalidUtf8,
2124 .ILSEQ => return error.BadPathName,
21372125 else => |err| return unexpectedErrno(err),
21382126 }
21392127}
......@@ -2162,10 +2150,7 @@ pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*:
21622150 .NOMEM => return error.SystemResources,
21632151 .NOSPC => return error.NoSpaceLeft,
21642152 .ROFS => return error.ReadOnlyFileSystem,
2165 .ILSEQ => |err| if (native_os == .wasi)
2166 return error.InvalidUtf8
2167 else
2168 return unexpectedErrno(err),
2153 .ILSEQ => return error.BadPathName,
21692154 else => |err| return unexpectedErrno(err),
21702155 }
21712156}
......@@ -2184,9 +2169,7 @@ pub const LinkError = UnexpectedError || error{
21842169 NoSpaceLeft,
21852170 ReadOnlyFileSystem,
21862171 NotSameFileSystem,
2187
2188 /// WASI-only; file paths must be valid UTF-8.
2189 InvalidUtf8,
2172 BadPathName,
21902173};
21912174
21922175/// On WASI, both paths should be encoded as valid UTF-8.
......@@ -2212,10 +2195,7 @@ pub fn linkZ(oldpath: [*:0]const u8, newpath: [*:0]const u8) LinkError!void {
22122195 .ROFS => return error.ReadOnlyFileSystem,
22132196 .XDEV => return error.NotSameFileSystem,
22142197 .INVAL => unreachable,
2215 .ILSEQ => |err| if (native_os == .wasi)
2216 return error.InvalidUtf8
2217 else
2218 return unexpectedErrno(err),
2198 .ILSEQ => return error.BadPathName,
22192199 else => |err| return unexpectedErrno(err),
22202200 }
22212201}
......@@ -2266,10 +2246,7 @@ pub fn linkatZ(
22662246 .ROFS => return error.ReadOnlyFileSystem,
22672247 .XDEV => return error.NotSameFileSystem,
22682248 .INVAL => unreachable,
2269 .ILSEQ => |err| if (native_os == .wasi)
2270 return error.InvalidUtf8
2271 else
2272 return unexpectedErrno(err),
2249 .ILSEQ => return error.BadPathName,
22732250 else => |err| return unexpectedErrno(err),
22742251 }
22752252}
......@@ -2315,7 +2292,7 @@ pub fn linkat(
23152292 .ROFS => return error.ReadOnlyFileSystem,
23162293 .XDEV => return error.NotSameFileSystem,
23172294 .INVAL => unreachable,
2318 .ILSEQ => return error.InvalidUtf8,
2295 .ILSEQ => return error.BadPathName,
23192296 else => |err| return unexpectedErrno(err),
23202297 }
23212298 }
......@@ -2398,10 +2375,7 @@ pub fn unlinkZ(file_path: [*:0]const u8) UnlinkError!void {
23982375 .NOTDIR => return error.NotDir,
23992376 .NOMEM => return error.SystemResources,
24002377 .ROFS => return error.ReadOnlyFileSystem,
2401 .ILSEQ => |err| if (native_os == .wasi)
2402 return error.InvalidUtf8
2403 else
2404 return unexpectedErrno(err),
2378 .ILSEQ => return error.BadPathName,
24052379 else => |err| return unexpectedErrno(err),
24062380 }
24072381}
......@@ -2460,7 +2434,7 @@ pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatErro
24602434 .ROFS => return error.ReadOnlyFileSystem,
24612435 .NOTEMPTY => return error.DirNotEmpty,
24622436 .NOTCAPABLE => return error.AccessDenied,
2463 .ILSEQ => return error.InvalidUtf8,
2437 .ILSEQ => return error.BadPathName,
24642438
24652439 .INVAL => unreachable, // invalid flags, or pathname has . as last component
24662440 .BADF => unreachable, // always a race condition
......@@ -2493,10 +2467,7 @@ pub fn unlinkatZ(dirfd: fd_t, file_path_c: [*:0]const u8, flags: u32) UnlinkatEr
24932467 .ROFS => return error.ReadOnlyFileSystem,
24942468 .EXIST => return error.DirNotEmpty,
24952469 .NOTEMPTY => return error.DirNotEmpty,
2496 .ILSEQ => |err| if (native_os == .wasi)
2497 return error.InvalidUtf8
2498 else
2499 return unexpectedErrno(err),
2470 .ILSEQ => return error.BadPathName,
25002471
25012472 .INVAL => unreachable, // invalid flags, or pathname has . as last component
25022473 .BADF => unreachable, // always a race condition
......@@ -2598,10 +2569,7 @@ pub fn renameZ(old_path: [*:0]const u8, new_path: [*:0]const u8) RenameError!voi
25982569 .NOTEMPTY => return error.PathAlreadyExists,
25992570 .ROFS => return error.ReadOnlyFileSystem,
26002571 .XDEV => return error.RenameAcrossMountPoints,
2601 .ILSEQ => |err| if (native_os == .wasi)
2602 return error.InvalidUtf8
2603 else
2604 return unexpectedErrno(err),
2572 .ILSEQ => return error.BadPathName,
26052573 else => |err| return unexpectedErrno(err),
26062574 }
26072575}
......@@ -2662,7 +2630,7 @@ fn renameatWasi(old: RelativePathWasi, new: RelativePathWasi) RenameError!void {
26622630 .ROFS => return error.ReadOnlyFileSystem,
26632631 .XDEV => return error.RenameAcrossMountPoints,
26642632 .NOTCAPABLE => return error.AccessDenied,
2665 .ILSEQ => return error.InvalidUtf8,
2633 .ILSEQ => return error.BadPathName,
26662634 else => |err| return unexpectedErrno(err),
26672635 }
26682636}
......@@ -2713,10 +2681,7 @@ pub fn renameatZ(
27132681 .NOTEMPTY => return error.PathAlreadyExists,
27142682 .ROFS => return error.ReadOnlyFileSystem,
27152683 .XDEV => return error.RenameAcrossMountPoints,
2716 .ILSEQ => |err| if (native_os == .wasi)
2717 return error.InvalidUtf8
2718 else
2719 return unexpectedErrno(err),
2684 .ILSEQ => return error.BadPathName,
27202685 else => |err| return unexpectedErrno(err),
27212686 }
27222687}
......@@ -2870,7 +2835,7 @@ pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: mode_t) MakeDir
28702835 .NOTDIR => return error.NotDir,
28712836 .ROFS => return error.ReadOnlyFileSystem,
28722837 .NOTCAPABLE => return error.AccessDenied,
2873 .ILSEQ => return error.InvalidUtf8,
2838 .ILSEQ => return error.BadPathName,
28742839 else => |err| return unexpectedErrno(err),
28752840 }
28762841}
......@@ -2901,10 +2866,7 @@ pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: mode_t) MakeDir
29012866 .ROFS => return error.ReadOnlyFileSystem,
29022867 // dragonfly: when dir_fd is unlinked from filesystem
29032868 .NOTCONN => return error.FileNotFound,
2904 .ILSEQ => |err| if (native_os == .wasi)
2905 return error.InvalidUtf8
2906 else
2907 return unexpectedErrno(err),
2869 .ILSEQ => return error.BadPathName,
29082870 else => |err| return unexpectedErrno(err),
29092871 }
29102872}
......@@ -2973,10 +2935,7 @@ pub fn mkdirZ(dir_path: [*:0]const u8, mode: mode_t) MakeDirError!void {
29732935 .NOSPC => return error.NoSpaceLeft,
29742936 .NOTDIR => return error.NotDir,
29752937 .ROFS => return error.ReadOnlyFileSystem,
2976 .ILSEQ => |err| if (native_os == .wasi)
2977 return error.InvalidUtf8
2978 else
2979 return unexpectedErrno(err),
2938 .ILSEQ => return error.BadPathName,
29802939 else => |err| return unexpectedErrno(err),
29812940 }
29822941}
......@@ -3067,10 +3026,7 @@ pub fn rmdirZ(dir_path: [*:0]const u8) DeleteDirError!void {
30673026 .EXIST => return error.DirNotEmpty,
30683027 .NOTEMPTY => return error.DirNotEmpty,
30693028 .ROFS => return error.ReadOnlyFileSystem,
3070 .ILSEQ => |err| if (native_os == .wasi)
3071 return error.InvalidUtf8
3072 else
3073 return unexpectedErrno(err),
3029 .ILSEQ => return error.BadPathName,
30743030 else => |err| return unexpectedErrno(err),
30753031 }
30763032}
......@@ -3145,10 +3101,7 @@ pub fn chdirZ(dir_path: [*:0]const u8) ChangeCurDirError!void {
31453101 .NOENT => return error.FileNotFound,
31463102 .NOMEM => return error.SystemResources,
31473103 .NOTDIR => return error.NotDir,
3148 .ILSEQ => |err| if (native_os == .wasi)
3149 return error.InvalidUtf8
3150 else
3151 return unexpectedErrno(err),
3104 .ILSEQ => return error.BadPathName,
31523105 else => |err| return unexpectedErrno(err),
31533106 }
31543107}
......@@ -3254,10 +3207,7 @@ pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8
32543207 .NOENT => return error.FileNotFound,
32553208 .NOMEM => return error.SystemResources,
32563209 .NOTDIR => return error.NotDir,
3257 .ILSEQ => |err| if (native_os == .wasi)
3258 return error.InvalidUtf8
3259 else
3260 return unexpectedErrno(err),
3210 .ILSEQ => return error.BadPathName,
32613211 else => |err| return unexpectedErrno(err),
32623212 }
32633213}
......@@ -3299,7 +3249,7 @@ pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) Read
32993249 .NOMEM => return error.SystemResources,
33003250 .NOTDIR => return error.NotDir,
33013251 .NOTCAPABLE => return error.AccessDenied,
3302 .ILSEQ => return error.InvalidUtf8,
3252 .ILSEQ => return error.BadPathName,
33033253 else => |err| return unexpectedErrno(err),
33043254 }
33053255}
......@@ -3332,10 +3282,7 @@ pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) Read
33323282 .NOENT => return error.FileNotFound,
33333283 .NOMEM => return error.SystemResources,
33343284 .NOTDIR => return error.NotDir,
3335 .ILSEQ => |err| if (native_os == .wasi)
3336 return error.InvalidUtf8
3337 else
3338 return unexpectedErrno(err),
3285 .ILSEQ => return error.BadPathName,
33393286 else => |err| return unexpectedErrno(err),
33403287 }
33413288}
......@@ -4421,13 +4368,10 @@ pub const FStatAtError = FStatError || error{
44214368/// which is relative to `dirfd` handle.
44224369/// On WASI, `pathname` should be encoded as valid UTF-8.
44234370/// On other platforms, `pathname` is an opaque sequence of bytes with no particular encoding.
4424/// See also `fstatatZ` and `std.os.fstatat_wasi`.
4371/// See also `fstatatZ`.
44254372pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat {
44264373 if (native_os == .wasi and !builtin.link_libc) {
4427 const filestat = try std.os.fstatat_wasi(dirfd, pathname, .{
4428 .SYMLINK_FOLLOW = (flags & AT.SYMLINK_NOFOLLOW) == 0,
4429 });
4430 return Stat.fromFilestat(filestat);
4374 @compileError("use std.Io instead");
44314375 } else if (native_os == .windows) {
44324376 @compileError("fstatat is not yet implemented on Windows");
44334377 } else {
......@@ -4440,10 +4384,7 @@ pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat
44404384/// See also `fstatat`.
44414385pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!Stat {
44424386 if (native_os == .wasi and !builtin.link_libc) {
4443 const filestat = try std.os.fstatat_wasi(dirfd, mem.sliceTo(pathname, 0), .{
4444 .SYMLINK_FOLLOW = (flags & AT.SYMLINK_NOFOLLOW) == 0,
4445 });
4446 return Stat.fromFilestat(filestat);
4387 @compileError("use std.Io instead");
44474388 }
44484389
44494390 const fstatat_sym = if (lfs64_abi) system.fstatat64 else system.fstatat;
......@@ -4460,10 +4401,7 @@ pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!S
44604401 .LOOP => return error.SymLinkLoop,
44614402 .NOENT => return error.FileNotFound,
44624403 .NOTDIR => return error.FileNotFound,
4463 .ILSEQ => |err| if (native_os == .wasi)
4464 return error.InvalidUtf8
4465 else
4466 return unexpectedErrno(err),
4404 .ILSEQ => return error.BadPathName,
44674405 else => |err| return unexpectedErrno(err),
44684406 }
44694407}
......@@ -4991,10 +4929,7 @@ pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void {
49914929 .FAULT => unreachable,
49924930 .IO => return error.InputOutput,
49934931 .NOMEM => return error.SystemResources,
4994 .ILSEQ => |err| if (native_os == .wasi)
4995 return error.InvalidUtf8
4996 else
4997 return unexpectedErrno(err),
4932 .ILSEQ => return error.BadPathName,
49984933 else => |err| return unexpectedErrno(err),
49994934 }
50004935}
......@@ -5072,10 +5007,7 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces
50725007 .FAULT => unreachable,
50735008 .IO => return error.InputOutput,
50745009 .NOMEM => return error.SystemResources,
5075 .ILSEQ => |err| if (native_os == .wasi)
5076 return error.InvalidUtf8
5077 else
5078 return unexpectedErrno(err),
5010 .ILSEQ => return error.BadPathName,
50795011 else => |err| return unexpectedErrno(err),
50805012 }
50815013}
lib/std/posix/test.zig-43
......@@ -226,49 +226,6 @@ test "linkat with different directories" {
226226 }
227227}
228228
229test "fstatat" {
230 if ((builtin.cpu.arch == .riscv32 or builtin.cpu.arch.isLoongArch()) and builtin.os.tag == .linux and !builtin.link_libc) return error.SkipZigTest; // No `fstatat()`.
231 // enable when `fstat` and `fstatat` are implemented on Windows
232 if (native_os == .windows) return error.SkipZigTest;
233
234 var tmp = tmpDir(.{});
235 defer tmp.cleanup();
236
237 // create dummy file
238 const contents = "nonsense";
239 try tmp.dir.writeFile(.{ .sub_path = "file.txt", .data = contents });
240
241 // fetch file's info on the opened fd directly
242 const file = try tmp.dir.openFile("file.txt", .{});
243 const stat = try posix.fstat(file.handle);
244 defer file.close();
245
246 // now repeat but using `fstatat` instead
247 const statat = try posix.fstatat(tmp.dir.fd, "file.txt", posix.AT.SYMLINK_NOFOLLOW);
248
249 try expectEqual(stat.dev, statat.dev);
250 try expectEqual(stat.ino, statat.ino);
251 try expectEqual(stat.nlink, statat.nlink);
252 try expectEqual(stat.mode, statat.mode);
253 try expectEqual(stat.uid, statat.uid);
254 try expectEqual(stat.gid, statat.gid);
255 try expectEqual(stat.rdev, statat.rdev);
256 try expectEqual(stat.size, statat.size);
257 try expectEqual(stat.blksize, statat.blksize);
258
259 // The stat.blocks/statat.blocks count is managed by the filesystem and may
260 // change if the file is stored in a journal or "inline".
261 // try expectEqual(stat.blocks, statat.blocks);
262
263 // s390x-linux does not have nanosecond precision for fstat(), but it does for
264 // fstatat(). As a result, comparing the timestamps isn't worth the effort
265 if (!(builtin.cpu.arch == .s390x and builtin.os.tag == .linux)) {
266 try expectEqual(stat.atime(), statat.atime());
267 try expectEqual(stat.mtime(), statat.mtime());
268 try expectEqual(stat.ctime(), statat.ctime());
269 }
270}
271
272229test "readlinkat" {
273230 var tmp = tmpDir(.{});
274231 defer tmp.cleanup();
test/src/convert-stack-trace.zig+7-1
......@@ -32,6 +32,12 @@ pub fn main() !void {
3232 const args = try std.process.argsAlloc(arena);
3333 if (args.len != 2) std.process.fatal("usage: convert-stack-trace path/to/test/output", .{});
3434
35 const gpa = arena;
36
37 var threaded: std.Io.Threaded = .init(gpa);
38 defer threaded.deinit();
39 const io = threaded.io();
40
3541 var read_buf: [1024]u8 = undefined;
3642 var write_buf: [1024]u8 = undefined;
3743
......@@ -40,7 +46,7 @@ pub fn main() !void {
4046
4147 const out_file: std.fs.File = .stdout();
4248
43 var in_fr = in_file.reader(&read_buf);
49 var in_fr = in_file.reader(io, &read_buf);
4450 var out_fw = out_file.writer(&write_buf);
4551
4652 const w = &out_fw.interface;
tools/docgen.zig+7-1
......@@ -36,6 +36,12 @@ pub fn main() !void {
3636 var args_it = try process.argsWithAllocator(arena);
3737 if (!args_it.skip()) @panic("expected self arg");
3838
39 const gpa = arena;
40
41 var threaded: std.Io.Threaded = .init(gpa);
42 defer threaded.deinit();
43 const io = threaded.io();
44
3945 var opt_code_dir: ?[]const u8 = null;
4046 var opt_input: ?[]const u8 = null;
4147 var opt_output: ?[]const u8 = null;
......@@ -77,7 +83,7 @@ pub fn main() !void {
7783 var code_dir = try fs.cwd().openDir(code_dir_path, .{});
7884 defer code_dir.close();
7985
80 var in_file_reader = in_file.reader(&.{});
86 var in_file_reader = in_file.reader(io, &.{});
8187 const input_file_bytes = try in_file_reader.interface.allocRemaining(arena, .limited(max_doc_file_size));
8288
8389 var tokenizer = Tokenizer.init(input_path, input_file_bytes);
tools/doctest.zig+26-18
......@@ -1,5 +1,8 @@
11const builtin = @import("builtin");
2
23const std = @import("std");
4const Io = std.Io;
5const Writer = std.Io.Writer;
36const fatal = std.process.fatal;
47const mem = std.mem;
58const fs = std.fs;
......@@ -7,7 +10,6 @@ const process = std.process;
710const Allocator = std.mem.Allocator;
811const testing = std.testing;
912const getExternalExecutor = std.zig.system.getExternalExecutor;
10const Writer = std.Io.Writer;
1113
1214const max_doc_file_size = 10 * 1024 * 1024;
1315
......@@ -36,6 +38,12 @@ pub fn main() !void {
3638 var args_it = try process.argsWithAllocator(arena);
3739 if (!args_it.skip()) fatal("missing argv[0]", .{});
3840
41 const gpa = arena;
42
43 var threaded: std.Io.Threaded = .init(gpa);
44 defer threaded.deinit();
45 const io = threaded.io();
46
3947 var opt_input: ?[]const u8 = null;
4048 var opt_output: ?[]const u8 = null;
4149 var opt_zig: ?[]const u8 = null;
......@@ -93,6 +101,7 @@ pub fn main() !void {
93101 try printSourceBlock(arena, out, source, fs.path.basename(input_path));
94102 try printOutput(
95103 arena,
104 io,
96105 out,
97106 code,
98107 tmp_dir_path,
......@@ -109,6 +118,7 @@ pub fn main() !void {
109118
110119fn printOutput(
111120 arena: Allocator,
121 io: Io,
112122 out: *Writer,
113123 code: Code,
114124 /// Relative to this process' cwd.
......@@ -123,11 +133,11 @@ fn printOutput(
123133 var env_map = try process.getEnvMap(arena);
124134 try env_map.put("CLICOLOR_FORCE", "1");
125135
126 const host = try std.zig.system.resolveTargetQuery(.{});
136 const host = try std.zig.system.resolveTargetQuery(io, .{});
127137 const obj_ext = builtin.object_format.fileExt(builtin.cpu.arch);
128138 const print = std.debug.print;
129139
130 var shell_buffer: std.Io.Writer.Allocating = .init(arena);
140 var shell_buffer: Writer.Allocating = .init(arena);
131141 defer shell_buffer.deinit();
132142 const shell_out = &shell_buffer.writer;
133143
......@@ -238,7 +248,7 @@ fn printOutput(
238248 const target_query = try std.Target.Query.parse(.{
239249 .arch_os_abi = code.target_str orelse "native",
240250 });
241 const target = try std.zig.system.resolveTargetQuery(target_query);
251 const target = try std.zig.system.resolveTargetQuery(io, target_query);
242252
243253 const path_to_exe = try std.fmt.allocPrint(arena, "./{s}{s}", .{
244254 code_name, target.exeFileExt(),
......@@ -316,9 +326,7 @@ fn printOutput(
316326 const target_query = try std.Target.Query.parse(.{
317327 .arch_os_abi = triple,
318328 });
319 const target = try std.zig.system.resolveTargetQuery(
320 target_query,
321 );
329 const target = try std.zig.system.resolveTargetQuery(io, target_query);
322330 switch (getExternalExecutor(&host, &target, .{
323331 .link_libc = code.link_libc,
324332 })) {
......@@ -1397,7 +1405,7 @@ test "printShell" {
13971405 \\</samp></pre></figure>
13981406 ;
13991407
1400 var buffer: std.Io.Writer.Allocating = .init(test_allocator);
1408 var buffer: Writer.Allocating = .init(test_allocator);
14011409 defer buffer.deinit();
14021410
14031411 try printShell(&buffer.writer, shell_out, false);
......@@ -1414,7 +1422,7 @@ test "printShell" {
14141422 \\</samp></pre></figure>
14151423 ;
14161424
1417 var buffer: std.Io.Writer.Allocating = .init(test_allocator);
1425 var buffer: Writer.Allocating = .init(test_allocator);
14181426 defer buffer.deinit();
14191427
14201428 try printShell(&buffer.writer, shell_out, false);
......@@ -1428,7 +1436,7 @@ test "printShell" {
14281436 \\</samp></pre></figure>
14291437 ;
14301438
1431 var buffer: std.Io.Writer.Allocating = .init(test_allocator);
1439 var buffer: Writer.Allocating = .init(test_allocator);
14321440 defer buffer.deinit();
14331441
14341442 try printShell(&buffer.writer, shell_out, false);
......@@ -1447,7 +1455,7 @@ test "printShell" {
14471455 \\</samp></pre></figure>
14481456 ;
14491457
1450 var buffer: std.Io.Writer.Allocating = .init(test_allocator);
1458 var buffer: Writer.Allocating = .init(test_allocator);
14511459 defer buffer.deinit();
14521460
14531461 try printShell(&buffer.writer, shell_out, false);
......@@ -1468,7 +1476,7 @@ test "printShell" {
14681476 \\</samp></pre></figure>
14691477 ;
14701478
1471 var buffer: std.Io.Writer.Allocating = .init(test_allocator);
1479 var buffer: Writer.Allocating = .init(test_allocator);
14721480 defer buffer.deinit();
14731481
14741482 try printShell(&buffer.writer, shell_out, false);
......@@ -1487,7 +1495,7 @@ test "printShell" {
14871495 \\</samp></pre></figure>
14881496 ;
14891497
1490 var buffer: std.Io.Writer.Allocating = .init(test_allocator);
1498 var buffer: Writer.Allocating = .init(test_allocator);
14911499 defer buffer.deinit();
14921500
14931501 try printShell(&buffer.writer, shell_out, false);
......@@ -1510,7 +1518,7 @@ test "printShell" {
15101518 \\</samp></pre></figure>
15111519 ;
15121520
1513 var buffer: std.Io.Writer.Allocating = .init(test_allocator);
1521 var buffer: Writer.Allocating = .init(test_allocator);
15141522 defer buffer.deinit();
15151523
15161524 try printShell(&buffer.writer, shell_out, false);
......@@ -1532,7 +1540,7 @@ test "printShell" {
15321540 \\</samp></pre></figure>
15331541 ;
15341542
1535 var buffer: std.Io.Writer.Allocating = .init(test_allocator);
1543 var buffer: Writer.Allocating = .init(test_allocator);
15361544 defer buffer.deinit();
15371545
15381546 try printShell(&buffer.writer, shell_out, false);
......@@ -1549,7 +1557,7 @@ test "printShell" {
15491557 \\</samp></pre></figure>
15501558 ;
15511559
1552 var buffer: std.Io.Writer.Allocating = .init(test_allocator);
1560 var buffer: Writer.Allocating = .init(test_allocator);
15531561 defer buffer.deinit();
15541562
15551563 try printShell(&buffer.writer, shell_out, false);
......@@ -1568,7 +1576,7 @@ test "printShell" {
15681576 \\</samp></pre></figure>
15691577 ;
15701578
1571 var buffer: std.Io.Writer.Allocating = .init(test_allocator);
1579 var buffer: Writer.Allocating = .init(test_allocator);
15721580 defer buffer.deinit();
15731581
15741582 try printShell(&buffer.writer, shell_out, false);
......@@ -1583,7 +1591,7 @@ test "printShell" {
15831591 \\</samp></pre></figure>
15841592 ;
15851593
1586 var buffer: std.Io.Writer.Allocating = .init(test_allocator);
1594 var buffer: Writer.Allocating = .init(test_allocator);
15871595 defer buffer.deinit();
15881596
15891597 try printShell(&buffer.writer, shell_out, false);