diff --git a/lib/compiler/aro/aro/Compilation.zig b/lib/compiler/aro/aro/Compilation.zig index 46f783097b..e0b9a508cf 100644 --- a/lib/compiler/aro/aro/Compilation.zig +++ b/lib/compiler/aro/aro/Compilation.zig @@ -171,10 +171,11 @@ pub fn init(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, /// Initialize Compilation with default environment, /// pragma handlers and emulation mode set to target. -pub fn initDefault(gpa: Allocator, arena: Allocator, diagnostics: *Diagnostics, cwd: std.fs.Dir) !Compilation { +pub fn initDefault(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, cwd: std.fs.Dir) !Compilation { var comp: Compilation = .{ .gpa = gpa, .arena = arena, + .io = io, .diagnostics = diagnostics, .environment = try Environment.loadAll(gpa), .cwd = cwd, diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index d88a8465d7..57578628fc 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -174,7 +174,7 @@ pub fn io(t: *Threaded) Io { .dirStatPath = switch (builtin.os.tag) { .linux => dirStatPathLinux, .windows => @panic("TODO"), - .wasi => @panic("TODO"), + .wasi => dirStatPathWasi, else => dirStatPathPosix, }, .fileStat = switch (builtin.os.tag) { @@ -984,6 +984,42 @@ fn dirStatPathPosix( } } +fn dirStatPathWasi( + userdata: ?*anyopaque, + dir: Io.Dir, + sub_path: []const u8, + options: Io.Dir.StatPathOptions, +) Io.Dir.StatPathError!Io.File.Stat { + if (builtin.link_libc) return dirStatPathPosix(userdata, dir, sub_path, options); + const t: *Threaded = @ptrCast(@alignCast(userdata)); + const dir_fd = dir.handle; + const wasi = std.os.wasi; + const flags: wasi.lookupflags_t = .{ + .SYMLINK_FOLLOW = @intFromBool(options.follow_symlinks), + }; + var stat: wasi.filestat_t = undefined; + while (true) { + try t.checkCancel(); + switch (wasi.path_filestat_get(dir_fd, flags, sub_path.ptr, sub_path.len, &stat)) { + .SUCCESS => return statFromWasi(stat), + .INTR => continue, + .CANCELED => return error.Canceled, + + .INVAL => |err| errnoBug(err), + .BADF => |err| errnoBug(err), // Always a race condition. + .NOMEM => return error.SystemResources, + .ACCES => return error.AccessDenied, + .FAULT => |err| errnoBug(err), + .NAMETOOLONG => return error.NameTooLong, + .NOENT => return error.FileNotFound, + .NOTDIR => return error.FileNotFound, + .NOTCAPABLE => return error.AccessDenied, + .ILSEQ => return error.BadPathName, + else => |err| return posix.unexpectedErrno(err), + } + } +} + fn fileStatPosix(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { const t: *Threaded = @ptrCast(@alignCast(userdata)); diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig index c8236b9f7a..3565d2fc2c 100644 --- a/lib/std/fs/Dir.zig +++ b/lib/std/fs/Dir.zig @@ -2500,10 +2500,6 @@ pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat { defer file.close(); return file.stat(); } - if (native_os == .wasi and !builtin.link_libc) { - const st = try std.os.fstatat_wasi(self.fd, sub_path, .{ .SYMLINK_FOLLOW = true }); - return Stat.fromWasi(st); - } var threaded: Io.Threaded = .init_single_threaded; const io = threaded.io(); return Io.Dir.statPath(.{ .handle = self.fd }, io, sub_path, .{}); diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 6bb0d871b6..052afc3a02 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -2031,37 +2031,28 @@ test "invalid UTF-8/WTF-8 paths" { const invalid_path = try ctx.transformPath("\xFF"); try testing.expectError(expected_err, ctx.dir.openFile(invalid_path, .{})); - try testing.expectError(expected_err, ctx.dir.openFileZ(invalid_path, .{})); try testing.expectError(expected_err, ctx.dir.createFile(invalid_path, .{})); - try testing.expectError(expected_err, ctx.dir.createFileZ(invalid_path, .{})); try testing.expectError(expected_err, ctx.dir.makeDir(invalid_path)); - try testing.expectError(expected_err, ctx.dir.makeDirZ(invalid_path)); try testing.expectError(expected_err, ctx.dir.makePath(invalid_path)); try testing.expectError(expected_err, ctx.dir.makeOpenPath(invalid_path, .{})); try testing.expectError(expected_err, ctx.dir.openDir(invalid_path, .{})); - try testing.expectError(expected_err, ctx.dir.openDirZ(invalid_path, .{})); try testing.expectError(expected_err, ctx.dir.deleteFile(invalid_path)); - try testing.expectError(expected_err, ctx.dir.deleteFileZ(invalid_path)); try testing.expectError(expected_err, ctx.dir.deleteDir(invalid_path)); - try testing.expectError(expected_err, ctx.dir.deleteDirZ(invalid_path)); try testing.expectError(expected_err, ctx.dir.rename(invalid_path, invalid_path)); - try testing.expectError(expected_err, ctx.dir.renameZ(invalid_path, invalid_path)); try testing.expectError(expected_err, ctx.dir.symLink(invalid_path, invalid_path, .{})); - try testing.expectError(expected_err, ctx.dir.symLinkZ(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.readLinkZ(invalid_path, &[_]u8{})); if (native_os == .wasi) { try testing.expectError(expected_err, ctx.dir.readLinkWasi(invalid_path, &[_]u8{})); } @@ -2075,7 +2066,6 @@ test "invalid UTF-8/WTF-8 paths" { try testing.expectError(expected_err, ctx.dir.writeFile(.{ .sub_path = invalid_path, .data = "" })); try testing.expectError(expected_err, ctx.dir.access(invalid_path, .{})); - try testing.expectError(expected_err, ctx.dir.accessZ(invalid_path, .{})); var dir = ctx.dir.adaptToNewApi(); try testing.expectError(expected_err, dir.updateFile(io, invalid_path, dir, invalid_path, .{})); @@ -2085,37 +2075,25 @@ test "invalid UTF-8/WTF-8 paths" { if (native_os != .wasi) { try testing.expectError(expected_err, ctx.dir.realpath(invalid_path, &[_]u8{})); - try testing.expectError(expected_err, ctx.dir.realpathZ(invalid_path, &[_]u8{})); try testing.expectError(expected_err, ctx.dir.realpathAlloc(testing.allocator, invalid_path)); } try testing.expectError(expected_err, fs.rename(ctx.dir, invalid_path, ctx.dir, invalid_path)); - try testing.expectError(expected_err, fs.renameZ(ctx.dir, invalid_path, ctx.dir, invalid_path)); if (native_os != .wasi and ctx.path_type != .relative) { try testing.expectError(expected_err, fs.copyFileAbsolute(invalid_path, invalid_path, .{})); try testing.expectError(expected_err, fs.makeDirAbsolute(invalid_path)); - try testing.expectError(expected_err, fs.makeDirAbsoluteZ(invalid_path)); try testing.expectError(expected_err, fs.deleteDirAbsolute(invalid_path)); - try testing.expectError(expected_err, fs.deleteDirAbsoluteZ(invalid_path)); try testing.expectError(expected_err, fs.renameAbsolute(invalid_path, invalid_path)); - try testing.expectError(expected_err, fs.renameAbsoluteZ(invalid_path, invalid_path)); try testing.expectError(expected_err, fs.openDirAbsolute(invalid_path, .{})); - try testing.expectError(expected_err, fs.openDirAbsoluteZ(invalid_path, .{})); try testing.expectError(expected_err, fs.openFileAbsolute(invalid_path, .{})); - try testing.expectError(expected_err, fs.openFileAbsoluteZ(invalid_path, .{})); try testing.expectError(expected_err, fs.accessAbsolute(invalid_path, .{})); - try testing.expectError(expected_err, fs.accessAbsoluteZ(invalid_path, .{})); try testing.expectError(expected_err, fs.createFileAbsolute(invalid_path, .{})); - try testing.expectError(expected_err, fs.createFileAbsoluteZ(invalid_path, .{})); try testing.expectError(expected_err, fs.deleteFileAbsolute(invalid_path)); - try testing.expectError(expected_err, fs.deleteFileAbsoluteZ(invalid_path)); try testing.expectError(expected_err, fs.deleteTreeAbsolute(invalid_path)); var readlink_buf: [fs.max_path_bytes]u8 = undefined; try testing.expectError(expected_err, fs.readLinkAbsolute(invalid_path, &readlink_buf)); - try testing.expectError(expected_err, fs.readLinkAbsoluteZ(invalid_path, &readlink_buf)); try testing.expectError(expected_err, fs.symLinkAbsolute(invalid_path, invalid_path, .{})); - try testing.expectError(expected_err, fs.symLinkAbsoluteZ(invalid_path, invalid_path, .{})); try testing.expectError(expected_err, fs.realpathAlloc(testing.allocator, invalid_path)); } } diff --git a/lib/std/os.zig b/lib/std/os.zig index b7122ca03b..7fe64290b1 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -201,36 +201,6 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix. } } -pub const FstatatError = error{ - SystemResources, - AccessDenied, - NameTooLong, - FileNotFound, - InvalidUtf8, - Unexpected, -}; - -/// WASI-only. Same as `fstatat` but targeting WASI. -/// `pathname` should be encoded as valid UTF-8. -/// See also `fstatat`. -pub fn fstatat_wasi(dirfd: posix.fd_t, pathname: []const u8, flags: wasi.lookupflags_t) FstatatError!wasi.filestat_t { - var stat: wasi.filestat_t = undefined; - switch (wasi.path_filestat_get(dirfd, flags, pathname.ptr, pathname.len, &stat)) { - .SUCCESS => return stat, - .INVAL => unreachable, - .BADF => unreachable, // Always a race condition. - .NOMEM => return error.SystemResources, - .ACCES => return error.AccessDenied, - .FAULT => unreachable, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.FileNotFound, - .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.InvalidUtf8, - else => |err| return posix.unexpectedErrno(err), - } -} - pub fn fstat_wasi(fd: posix.fd_t) posix.FStatError!wasi.filestat_t { var stat: wasi.filestat_t = undefined; switch (wasi.fd_filestat_get(fd, &stat)) { diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index cbf49638a3..f36effe380 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -146,7 +146,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN // call has failed. There is not really a sane way to handle // this other than retrying the creation after the OS finishes // the deletion. - std.Thread.sleep(std.time.ns_per_ms); + kernel32.Sleep(1); continue; }, .VIRUS_INFECTED, .VIRUS_DELETED => return error.AntivirusInterference, @@ -604,7 +604,7 @@ pub const ReadFileError = error{ BrokenPipe, /// The specified network name is no longer available. ConnectionResetByPeer, - OperationAborted, + Canceled, /// Unable to read file due to lock. LockViolation, /// Known to be possible when: @@ -654,7 +654,7 @@ pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64) ReadFileError!usiz pub const WriteFileError = error{ SystemResources, - OperationAborted, + Canceled, BrokenPipe, NotOpenForWriting, /// The process cannot access the file because another process has locked @@ -694,7 +694,7 @@ pub fn WriteFile( switch (GetLastError()) { .INVALID_USER_BUFFER => return error.SystemResources, .NOT_ENOUGH_MEMORY => return error.SystemResources, - .OPERATION_ABORTED => return error.OperationAborted, + .OPERATION_ABORTED => return error.Canceled, .NOT_ENOUGH_QUOTA => return error.SystemResources, .IO_PENDING => unreachable, .NO_DATA => return error.BrokenPipe, diff --git a/lib/std/posix.zig b/lib/std/posix.zig index b27468617c..651f6eb117 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -821,9 +821,6 @@ pub const ReadError = std.Io.File.ReadStreamingError; /// The corresponding POSIX limit is `maxInt(isize)`. pub fn read(fd: fd_t, buf: []u8) ReadError!usize { if (buf.len == 0) return 0; - if (native_os == .windows) { - return windows.ReadFile(fd, buf, null); - } if (native_os == .wasi and !builtin.link_libc) { const iovs = [1]iovec{iovec{ .base = buf.ptr, @@ -1181,7 +1178,7 @@ pub const WriteError = error{ PermissionDenied, BrokenPipe, SystemResources, - OperationAborted, + Canceled, NotOpenForWriting, /// 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 { .PERM => return error.PermissionDenied, .EXIST => return error.PathAlreadyExists, .BUSY => return error.DeviceBusy, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -1678,7 +1672,7 @@ pub fn openatWasi( .EXIST => return error.PathAlreadyExists, .BUSY => return error.DeviceBusy, .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.InvalidUtf8, + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -1773,10 +1767,7 @@ pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: O, mode: mode_t) O .AGAIN => return error.WouldBlock, .TXTBSY => return error.FileBusy, .NXIO => return error.NoDevice, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2084,10 +2075,7 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin .NOMEM => return error.SystemResources, .NOSPC => return error.NoSpaceLeft, .ROFS => return error.ReadOnlyFileSystem, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2133,7 +2121,7 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c .NOSPC => return error.NoSpaceLeft, .ROFS => return error.ReadOnlyFileSystem, .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.InvalidUtf8, + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2162,10 +2150,7 @@ pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*: .NOMEM => return error.SystemResources, .NOSPC => return error.NoSpaceLeft, .ROFS => return error.ReadOnlyFileSystem, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2184,9 +2169,7 @@ pub const LinkError = UnexpectedError || error{ NoSpaceLeft, ReadOnlyFileSystem, NotSameFileSystem, - - /// WASI-only; file paths must be valid UTF-8. - InvalidUtf8, + BadPathName, }; /// 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 { .ROFS => return error.ReadOnlyFileSystem, .XDEV => return error.NotSameFileSystem, .INVAL => unreachable, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2266,10 +2246,7 @@ pub fn linkatZ( .ROFS => return error.ReadOnlyFileSystem, .XDEV => return error.NotSameFileSystem, .INVAL => unreachable, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2315,7 +2292,7 @@ pub fn linkat( .ROFS => return error.ReadOnlyFileSystem, .XDEV => return error.NotSameFileSystem, .INVAL => unreachable, - .ILSEQ => return error.InvalidUtf8, + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2398,10 +2375,7 @@ pub fn unlinkZ(file_path: [*:0]const u8) UnlinkError!void { .NOTDIR => return error.NotDir, .NOMEM => return error.SystemResources, .ROFS => return error.ReadOnlyFileSystem, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2460,7 +2434,7 @@ pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatErro .ROFS => return error.ReadOnlyFileSystem, .NOTEMPTY => return error.DirNotEmpty, .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.InvalidUtf8, + .ILSEQ => return error.BadPathName, .INVAL => unreachable, // invalid flags, or pathname has . as last component .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 .ROFS => return error.ReadOnlyFileSystem, .EXIST => return error.DirNotEmpty, .NOTEMPTY => return error.DirNotEmpty, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, .INVAL => unreachable, // invalid flags, or pathname has . as last component .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 .NOTEMPTY => return error.PathAlreadyExists, .ROFS => return error.ReadOnlyFileSystem, .XDEV => return error.RenameAcrossMountPoints, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2662,7 +2630,7 @@ fn renameatWasi(old: RelativePathWasi, new: RelativePathWasi) RenameError!void { .ROFS => return error.ReadOnlyFileSystem, .XDEV => return error.RenameAcrossMountPoints, .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.InvalidUtf8, + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2713,10 +2681,7 @@ pub fn renameatZ( .NOTEMPTY => return error.PathAlreadyExists, .ROFS => return error.ReadOnlyFileSystem, .XDEV => return error.RenameAcrossMountPoints, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2870,7 +2835,7 @@ pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: mode_t) MakeDir .NOTDIR => return error.NotDir, .ROFS => return error.ReadOnlyFileSystem, .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.InvalidUtf8, + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2901,10 +2866,7 @@ pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: mode_t) MakeDir .ROFS => return error.ReadOnlyFileSystem, // dragonfly: when dir_fd is unlinked from filesystem .NOTCONN => return error.FileNotFound, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -2973,10 +2935,7 @@ pub fn mkdirZ(dir_path: [*:0]const u8, mode: mode_t) MakeDirError!void { .NOSPC => return error.NoSpaceLeft, .NOTDIR => return error.NotDir, .ROFS => return error.ReadOnlyFileSystem, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -3067,10 +3026,7 @@ pub fn rmdirZ(dir_path: [*:0]const u8) DeleteDirError!void { .EXIST => return error.DirNotEmpty, .NOTEMPTY => return error.DirNotEmpty, .ROFS => return error.ReadOnlyFileSystem, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -3145,10 +3101,7 @@ pub fn chdirZ(dir_path: [*:0]const u8) ChangeCurDirError!void { .NOENT => return error.FileNotFound, .NOMEM => return error.SystemResources, .NOTDIR => return error.NotDir, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -3254,10 +3207,7 @@ pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 .NOENT => return error.FileNotFound, .NOMEM => return error.SystemResources, .NOTDIR => return error.NotDir, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -3299,7 +3249,7 @@ pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) Read .NOMEM => return error.SystemResources, .NOTDIR => return error.NotDir, .NOTCAPABLE => return error.AccessDenied, - .ILSEQ => return error.InvalidUtf8, + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -3332,10 +3282,7 @@ pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) Read .NOENT => return error.FileNotFound, .NOMEM => return error.SystemResources, .NOTDIR => return error.NotDir, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -4421,13 +4368,10 @@ pub const FStatAtError = FStatError || error{ /// which is relative to `dirfd` handle. /// On WASI, `pathname` should be encoded as valid UTF-8. /// On other platforms, `pathname` is an opaque sequence of bytes with no particular encoding. -/// See also `fstatatZ` and `std.os.fstatat_wasi`. +/// See also `fstatatZ`. pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat { if (native_os == .wasi and !builtin.link_libc) { - const filestat = try std.os.fstatat_wasi(dirfd, pathname, .{ - .SYMLINK_FOLLOW = (flags & AT.SYMLINK_NOFOLLOW) == 0, - }); - return Stat.fromFilestat(filestat); + @compileError("use std.Io instead"); } else if (native_os == .windows) { @compileError("fstatat is not yet implemented on Windows"); } else { @@ -4440,10 +4384,7 @@ pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat /// See also `fstatat`. pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!Stat { if (native_os == .wasi and !builtin.link_libc) { - const filestat = try std.os.fstatat_wasi(dirfd, mem.sliceTo(pathname, 0), .{ - .SYMLINK_FOLLOW = (flags & AT.SYMLINK_NOFOLLOW) == 0, - }); - return Stat.fromFilestat(filestat); + @compileError("use std.Io instead"); } 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 .LOOP => return error.SymLinkLoop, .NOENT => return error.FileNotFound, .NOTDIR => return error.FileNotFound, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -4991,10 +4929,7 @@ pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void { .FAULT => unreachable, .IO => return error.InputOutput, .NOMEM => return error.SystemResources, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } @@ -5072,10 +5007,7 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces .FAULT => unreachable, .IO => return error.InputOutput, .NOMEM => return error.SystemResources, - .ILSEQ => |err| if (native_os == .wasi) - return error.InvalidUtf8 - else - return unexpectedErrno(err), + .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } } diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig index b5ce476441..230440a2f1 100644 --- a/lib/std/posix/test.zig +++ b/lib/std/posix/test.zig @@ -226,49 +226,6 @@ test "linkat with different directories" { } } -test "fstatat" { - if ((builtin.cpu.arch == .riscv32 or builtin.cpu.arch.isLoongArch()) and builtin.os.tag == .linux and !builtin.link_libc) return error.SkipZigTest; // No `fstatat()`. - // enable when `fstat` and `fstatat` are implemented on Windows - if (native_os == .windows) return error.SkipZigTest; - - var tmp = tmpDir(.{}); - defer tmp.cleanup(); - - // create dummy file - const contents = "nonsense"; - try tmp.dir.writeFile(.{ .sub_path = "file.txt", .data = contents }); - - // fetch file's info on the opened fd directly - const file = try tmp.dir.openFile("file.txt", .{}); - const stat = try posix.fstat(file.handle); - defer file.close(); - - // now repeat but using `fstatat` instead - const statat = try posix.fstatat(tmp.dir.fd, "file.txt", posix.AT.SYMLINK_NOFOLLOW); - - try expectEqual(stat.dev, statat.dev); - try expectEqual(stat.ino, statat.ino); - try expectEqual(stat.nlink, statat.nlink); - try expectEqual(stat.mode, statat.mode); - try expectEqual(stat.uid, statat.uid); - try expectEqual(stat.gid, statat.gid); - try expectEqual(stat.rdev, statat.rdev); - try expectEqual(stat.size, statat.size); - try expectEqual(stat.blksize, statat.blksize); - - // The stat.blocks/statat.blocks count is managed by the filesystem and may - // change if the file is stored in a journal or "inline". - // try expectEqual(stat.blocks, statat.blocks); - - // s390x-linux does not have nanosecond precision for fstat(), but it does for - // fstatat(). As a result, comparing the timestamps isn't worth the effort - if (!(builtin.cpu.arch == .s390x and builtin.os.tag == .linux)) { - try expectEqual(stat.atime(), statat.atime()); - try expectEqual(stat.mtime(), statat.mtime()); - try expectEqual(stat.ctime(), statat.ctime()); - } -} - test "readlinkat" { var tmp = tmpDir(.{}); defer tmp.cleanup(); diff --git a/test/src/convert-stack-trace.zig b/test/src/convert-stack-trace.zig index c7cd01a460..91be53a8e5 100644 --- a/test/src/convert-stack-trace.zig +++ b/test/src/convert-stack-trace.zig @@ -32,6 +32,12 @@ pub fn main() !void { const args = try std.process.argsAlloc(arena); if (args.len != 2) std.process.fatal("usage: convert-stack-trace path/to/test/output", .{}); + const gpa = arena; + + var threaded: std.Io.Threaded = .init(gpa); + defer threaded.deinit(); + const io = threaded.io(); + var read_buf: [1024]u8 = undefined; var write_buf: [1024]u8 = undefined; @@ -40,7 +46,7 @@ pub fn main() !void { const out_file: std.fs.File = .stdout(); - var in_fr = in_file.reader(&read_buf); + var in_fr = in_file.reader(io, &read_buf); var out_fw = out_file.writer(&write_buf); const w = &out_fw.interface; diff --git a/tools/docgen.zig b/tools/docgen.zig index 18311b0d54..d23892e06c 100644 --- a/tools/docgen.zig +++ b/tools/docgen.zig @@ -36,6 +36,12 @@ pub fn main() !void { var args_it = try process.argsWithAllocator(arena); if (!args_it.skip()) @panic("expected self arg"); + const gpa = arena; + + var threaded: std.Io.Threaded = .init(gpa); + defer threaded.deinit(); + const io = threaded.io(); + var opt_code_dir: ?[]const u8 = null; var opt_input: ?[]const u8 = null; var opt_output: ?[]const u8 = null; @@ -77,7 +83,7 @@ pub fn main() !void { var code_dir = try fs.cwd().openDir(code_dir_path, .{}); defer code_dir.close(); - var in_file_reader = in_file.reader(&.{}); + var in_file_reader = in_file.reader(io, &.{}); const input_file_bytes = try in_file_reader.interface.allocRemaining(arena, .limited(max_doc_file_size)); var tokenizer = Tokenizer.init(input_path, input_file_bytes); diff --git a/tools/doctest.zig b/tools/doctest.zig index ccdbc6b065..de8d3a80ee 100644 --- a/tools/doctest.zig +++ b/tools/doctest.zig @@ -1,5 +1,8 @@ const builtin = @import("builtin"); + const std = @import("std"); +const Io = std.Io; +const Writer = std.Io.Writer; const fatal = std.process.fatal; const mem = std.mem; const fs = std.fs; @@ -7,7 +10,6 @@ const process = std.process; const Allocator = std.mem.Allocator; const testing = std.testing; const getExternalExecutor = std.zig.system.getExternalExecutor; -const Writer = std.Io.Writer; const max_doc_file_size = 10 * 1024 * 1024; @@ -36,6 +38,12 @@ pub fn main() !void { var args_it = try process.argsWithAllocator(arena); if (!args_it.skip()) fatal("missing argv[0]", .{}); + const gpa = arena; + + var threaded: std.Io.Threaded = .init(gpa); + defer threaded.deinit(); + const io = threaded.io(); + var opt_input: ?[]const u8 = null; var opt_output: ?[]const u8 = null; var opt_zig: ?[]const u8 = null; @@ -93,6 +101,7 @@ pub fn main() !void { try printSourceBlock(arena, out, source, fs.path.basename(input_path)); try printOutput( arena, + io, out, code, tmp_dir_path, @@ -109,6 +118,7 @@ pub fn main() !void { fn printOutput( arena: Allocator, + io: Io, out: *Writer, code: Code, /// Relative to this process' cwd. @@ -123,11 +133,11 @@ fn printOutput( var env_map = try process.getEnvMap(arena); try env_map.put("CLICOLOR_FORCE", "1"); - const host = try std.zig.system.resolveTargetQuery(.{}); + const host = try std.zig.system.resolveTargetQuery(io, .{}); const obj_ext = builtin.object_format.fileExt(builtin.cpu.arch); const print = std.debug.print; - var shell_buffer: std.Io.Writer.Allocating = .init(arena); + var shell_buffer: Writer.Allocating = .init(arena); defer shell_buffer.deinit(); const shell_out = &shell_buffer.writer; @@ -238,7 +248,7 @@ fn printOutput( const target_query = try std.Target.Query.parse(.{ .arch_os_abi = code.target_str orelse "native", }); - const target = try std.zig.system.resolveTargetQuery(target_query); + const target = try std.zig.system.resolveTargetQuery(io, target_query); const path_to_exe = try std.fmt.allocPrint(arena, "./{s}{s}", .{ code_name, target.exeFileExt(), @@ -316,9 +326,7 @@ fn printOutput( const target_query = try std.Target.Query.parse(.{ .arch_os_abi = triple, }); - const target = try std.zig.system.resolveTargetQuery( - target_query, - ); + const target = try std.zig.system.resolveTargetQuery(io, target_query); switch (getExternalExecutor(&host, &target, .{ .link_libc = code.link_libc, })) { @@ -1397,7 +1405,7 @@ test "printShell" { \\ ; - var buffer: std.Io.Writer.Allocating = .init(test_allocator); + var buffer: Writer.Allocating = .init(test_allocator); defer buffer.deinit(); try printShell(&buffer.writer, shell_out, false); @@ -1414,7 +1422,7 @@ test "printShell" { \\ ; - var buffer: std.Io.Writer.Allocating = .init(test_allocator); + var buffer: Writer.Allocating = .init(test_allocator); defer buffer.deinit(); try printShell(&buffer.writer, shell_out, false); @@ -1428,7 +1436,7 @@ test "printShell" { \\ ; - var buffer: std.Io.Writer.Allocating = .init(test_allocator); + var buffer: Writer.Allocating = .init(test_allocator); defer buffer.deinit(); try printShell(&buffer.writer, shell_out, false); @@ -1447,7 +1455,7 @@ test "printShell" { \\ ; - var buffer: std.Io.Writer.Allocating = .init(test_allocator); + var buffer: Writer.Allocating = .init(test_allocator); defer buffer.deinit(); try printShell(&buffer.writer, shell_out, false); @@ -1468,7 +1476,7 @@ test "printShell" { \\ ; - var buffer: std.Io.Writer.Allocating = .init(test_allocator); + var buffer: Writer.Allocating = .init(test_allocator); defer buffer.deinit(); try printShell(&buffer.writer, shell_out, false); @@ -1487,7 +1495,7 @@ test "printShell" { \\ ; - var buffer: std.Io.Writer.Allocating = .init(test_allocator); + var buffer: Writer.Allocating = .init(test_allocator); defer buffer.deinit(); try printShell(&buffer.writer, shell_out, false); @@ -1510,7 +1518,7 @@ test "printShell" { \\ ; - var buffer: std.Io.Writer.Allocating = .init(test_allocator); + var buffer: Writer.Allocating = .init(test_allocator); defer buffer.deinit(); try printShell(&buffer.writer, shell_out, false); @@ -1532,7 +1540,7 @@ test "printShell" { \\ ; - var buffer: std.Io.Writer.Allocating = .init(test_allocator); + var buffer: Writer.Allocating = .init(test_allocator); defer buffer.deinit(); try printShell(&buffer.writer, shell_out, false); @@ -1549,7 +1557,7 @@ test "printShell" { \\ ; - var buffer: std.Io.Writer.Allocating = .init(test_allocator); + var buffer: Writer.Allocating = .init(test_allocator); defer buffer.deinit(); try printShell(&buffer.writer, shell_out, false); @@ -1568,7 +1576,7 @@ test "printShell" { \\ ; - var buffer: std.Io.Writer.Allocating = .init(test_allocator); + var buffer: Writer.Allocating = .init(test_allocator); defer buffer.deinit(); try printShell(&buffer.writer, shell_out, false); @@ -1583,7 +1591,7 @@ test "printShell" { \\ ; - var buffer: std.Io.Writer.Allocating = .init(test_allocator); + var buffer: Writer.Allocating = .init(test_allocator); defer buffer.deinit(); try printShell(&buffer.writer, shell_out, false);