authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-06-29 17:10:01+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-06-29 17:10:01+02:00
logbf8bf528c6c131f61de4af24c3599486a59c5868
tree5350bc08ee690d446c219a4df7076390dde7dbad
parent374e3e42e0de10d21406c077599cfc4a6a813497

Handle ENOTCAPABLE in WASI

This commit adds `error.NotCapable` enum value and makes sure that every applicable WASI syscall that can return `ENOTCAPABLE` errno remaps it to `error.NotCapable.

2 files changed, 132 insertions(+), 43 deletions(-)

lib/std/fs.zig+24-10
...@@ -264,7 +264,13 @@ pub const Dir = struct {...@@ -264,7 +264,13 @@ pub const Dir = struct {
264 pub const Kind = File.Kind;264 pub const Kind = File.Kind;
265 };265 };
266266
267 const IteratorError = error{AccessDenied} || os.UnexpectedError;267 const IteratorError = error{
268 AccessDenied,
269
270 /// WASI-only. This error occurs when the underlying `Dir` file descriptor does
271 /// not hold the required rights to call `fd_readdir` on it.
272 NotCapable,
273 } || os.UnexpectedError;
268274
269 pub const Iterator = switch (builtin.os.tag) {275 pub const Iterator = switch (builtin.os.tag) {
270 .macosx, .ios, .freebsd, .netbsd, .dragonfly => struct {276 .macosx, .ios, .freebsd, .netbsd, .dragonfly => struct {
...@@ -535,14 +541,15 @@ pub const Dir = struct {...@@ -535,14 +541,15 @@ pub const Dir = struct {
535 w.EFAULT => unreachable,541 w.EFAULT => unreachable,
536 w.ENOTDIR => unreachable,542 w.ENOTDIR => unreachable,
537 w.EINVAL => unreachable,543 w.EINVAL => unreachable,
544 w.ENOTCAPABLE => return error.NotCapable,
538 else => |err| return os.unexpectedErrno(err),545 else => |err| return os.unexpectedErrno(err),
539 }546 }
540 if (bufused == 0) return null;547 if (bufused == 0) return null;
541 self.index = 0;548 self.index = 0;
542 self.end_index = bufused;549 self.end_index = bufused;
543 }550 }
544 const entry = @ptrCast(*align(1) os.wasi.dirent_t, &self.buf[self.index]);551 const entry = @ptrCast(*align(1) w.dirent_t, &self.buf[self.index]);
545 const entry_size = @sizeOf(os.wasi.dirent_t);552 const entry_size = @sizeOf(w.dirent_t);
546 const name_index = self.index + entry_size;553 const name_index = self.index + entry_size;
547 const name = mem.span(self.buf[name_index .. name_index + entry.d_namlen]);554 const name = mem.span(self.buf[name_index .. name_index + entry.d_namlen]);
548555
...@@ -556,12 +563,12 @@ pub const Dir = struct {...@@ -556,12 +563,12 @@ pub const Dir = struct {
556 }563 }
557564
558 const entry_kind = switch (entry.d_type) {565 const entry_kind = switch (entry.d_type) {
559 wasi.FILETYPE_BLOCK_DEVICE => Entry.Kind.BlockDevice,566 w.FILETYPE_BLOCK_DEVICE => Entry.Kind.BlockDevice,
560 wasi.FILETYPE_CHARACTER_DEVICE => Entry.Kind.CharacterDevice,567 w.FILETYPE_CHARACTER_DEVICE => Entry.Kind.CharacterDevice,
561 wasi.FILETYPE_DIRECTORY => Entry.Kind.Directory,568 w.FILETYPE_DIRECTORY => Entry.Kind.Directory,
562 wasi.FILETYPE_SYMBOLIC_LINK => Entry.Kind.SymLink,569 w.FILETYPE_SYMBOLIC_LINK => Entry.Kind.SymLink,
563 wasi.FILETYPE_REGULAR_FILE => Entry.Kind.File,570 w.FILETYPE_REGULAR_FILE => Entry.Kind.File,
564 wasi.FILETYPE_SOCKET_STREAM, wasi.FILETYPE_SOCKET_DGRAM => Entry.Kind.UnixDomainSocket,571 w.FILETYPE_SOCKET_STREAM, wasi.FILETYPE_SOCKET_DGRAM => Entry.Kind.UnixDomainSocket,
565 else => Entry.Kind.Unknown,572 else => Entry.Kind.Unknown,
566 };573 };
567 return Entry{574 return Entry{
...@@ -621,6 +628,7 @@ pub const Dir = struct {...@@ -621,6 +628,7 @@ pub const Dir = struct {
621 InvalidUtf8,628 InvalidUtf8,
622 BadPathName,629 BadPathName,
623 DeviceBusy,630 DeviceBusy,
631 NotCapable,
624 } || os.UnexpectedError;632 } || os.UnexpectedError;
625633
626 pub fn close(self: *Dir) void {634 pub fn close(self: *Dir) void {
...@@ -1105,7 +1113,7 @@ pub const Dir = struct {...@@ -1105,7 +1113,7 @@ pub const Dir = struct {
1105 }1113 }
1106 }1114 }
11071115
1108 pub const DeleteFileError = os.UnlinkError;1116 pub const DeleteFileError = os.UnlinkatError;
11091117
1110 /// Delete a file name and possibly the file it refers to, based on an open directory handle.1118 /// Delete a file name and possibly the file it refers to, based on an open directory handle.
1111 /// Asserts that the path parameter has no null bytes.1119 /// Asserts that the path parameter has no null bytes.
...@@ -1147,6 +1155,7 @@ pub const Dir = struct {...@@ -1147,6 +1155,7 @@ pub const Dir = struct {
1147 ReadOnlyFileSystem,1155 ReadOnlyFileSystem,
1148 InvalidUtf8,1156 InvalidUtf8,
1149 BadPathName,1157 BadPathName,
1158 NotCapable,
1150 Unexpected,1159 Unexpected,
1151 };1160 };
11521161
...@@ -1249,6 +1258,7 @@ pub const Dir = struct {...@@ -1249,6 +1258,7 @@ pub const Dir = struct {
1249 /// On Windows, file paths cannot contain these characters:1258 /// On Windows, file paths cannot contain these characters:
1250 /// '/', '*', '?', '"', '<', '>', '|'1259 /// '/', '*', '?', '"', '<', '>', '|'
1251 BadPathName,1260 BadPathName,
1261 NotCapable,
1252 } || os.UnexpectedError;1262 } || os.UnexpectedError;
12531263
1254 /// Whether `full_path` describes a symlink, file, or directory, this function1264 /// Whether `full_path` describes a symlink, file, or directory, this function
...@@ -1276,6 +1286,7 @@ pub const Dir = struct {...@@ -1276,6 +1286,7 @@ pub const Dir = struct {
1276 error.FileBusy,1286 error.FileBusy,
1277 error.BadPathName,1287 error.BadPathName,
1278 error.Unexpected,1288 error.Unexpected,
1289 error.NotCapable,
1279 => |e| return e,1290 => |e| return e,
1280 }1291 }
1281 var dir = self.openDir(sub_path, .{ .iterate = true }) catch |err| switch (err) {1292 var dir = self.openDir(sub_path, .{ .iterate = true }) catch |err| switch (err) {
...@@ -1301,6 +1312,7 @@ pub const Dir = struct {...@@ -1301,6 +1312,7 @@ pub const Dir = struct {
1301 error.InvalidUtf8,1312 error.InvalidUtf8,
1302 error.BadPathName,1313 error.BadPathName,
1303 error.DeviceBusy,1314 error.DeviceBusy,
1315 error.NotCapable,
1304 => |e| return e,1316 => |e| return e,
1305 };1317 };
1306 var cleanup_dir_parent: ?Dir = null;1318 var cleanup_dir_parent: ?Dir = null;
...@@ -1342,6 +1354,7 @@ pub const Dir = struct {...@@ -1342,6 +1354,7 @@ pub const Dir = struct {
1342 error.FileBusy,1354 error.FileBusy,
1343 error.BadPathName,1355 error.BadPathName,
1344 error.Unexpected,1356 error.Unexpected,
1357 error.NotCapable,
1345 => |e| return e,1358 => |e| return e,
1346 }1359 }
13471360
...@@ -1368,6 +1381,7 @@ pub const Dir = struct {...@@ -1368,6 +1381,7 @@ pub const Dir = struct {
1368 error.InvalidUtf8,1381 error.InvalidUtf8,
1369 error.BadPathName,1382 error.BadPathName,
1370 error.DeviceBusy,1383 error.DeviceBusy,
1384 error.NotCapable,
1371 => |e| return e,1385 => |e| return e,
1372 };1386 };
1373 if (cleanup_dir_parent) |*d| d.close();1387 if (cleanup_dir_parent) |*d| d.close();
lib/std/os.zig+108-33
...@@ -300,6 +300,10 @@ pub const ReadError = error{...@@ -300,6 +300,10 @@ pub const ReadError = error{
300 /// This error occurs when no global event loop is configured,300 /// This error occurs when no global event loop is configured,
301 /// and reading from the file descriptor would block.301 /// and reading from the file descriptor would block.
302 WouldBlock,302 WouldBlock,
303
304 /// WASI-only. This error occurs when the file descriptor does
305 /// not hold the required rights to read from it.
306 NotCapable,
303} || UnexpectedError;307} || UnexpectedError;
304308
305/// Returns the number of bytes that were read, which can be less than309/// Returns the number of bytes that were read, which can be less than
...@@ -335,6 +339,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {...@@ -335,6 +339,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
335 wasi.ENOMEM => return error.SystemResources,339 wasi.ENOMEM => return error.SystemResources,
336 wasi.ECONNRESET => return error.ConnectionResetByPeer,340 wasi.ECONNRESET => return error.ConnectionResetByPeer,
337 wasi.ETIMEDOUT => return error.ConnectionTimedOut,341 wasi.ETIMEDOUT => return error.ConnectionTimedOut,
342 wasi.ENOTCAPABLE => return error.NotCapable,
338 else => |err| return unexpectedErrno(err),343 else => |err| return unexpectedErrno(err),
339 }344 }
340 }345 }
...@@ -402,6 +407,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize {...@@ -402,6 +407,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize {
402 wasi.EISDIR => return error.IsDir,407 wasi.EISDIR => return error.IsDir,
403 wasi.ENOBUFS => return error.SystemResources,408 wasi.ENOBUFS => return error.SystemResources,
404 wasi.ENOMEM => return error.SystemResources,409 wasi.ENOMEM => return error.SystemResources,
410 wasi.ENOTCAPABLE => return error.NotCapable,
405 else => |err| return unexpectedErrno(err),411 else => |err| return unexpectedErrno(err),
406 }412 }
407 }413 }
...@@ -466,6 +472,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {...@@ -466,6 +472,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
466 wasi.ENXIO => return error.Unseekable,472 wasi.ENXIO => return error.Unseekable,
467 wasi.ESPIPE => return error.Unseekable,473 wasi.ESPIPE => return error.Unseekable,
468 wasi.EOVERFLOW => return error.Unseekable,474 wasi.EOVERFLOW => return error.Unseekable,
475 wasi.ENOTCAPABLE => return error.NotCapable,
469 else => |err| return unexpectedErrno(err),476 else => |err| return unexpectedErrno(err),
470 }477 }
471 }478 }
...@@ -502,6 +509,10 @@ pub const TruncateError = error{...@@ -502,6 +509,10 @@ pub const TruncateError = error{
502 InputOutput,509 InputOutput,
503 CannotTruncate,510 CannotTruncate,
504 FileBusy,511 FileBusy,
512
513 /// WASI-only. This error occurs when the file descriptor does
514 /// not hold the required rights to call `ftruncate` on it.
515 NotCapable,
505} || UnexpectedError;516} || UnexpectedError;
506517
507pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {518pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
...@@ -536,6 +547,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {...@@ -536,6 +547,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
536 wasi.ETXTBSY => return error.FileBusy,547 wasi.ETXTBSY => return error.FileBusy,
537 wasi.EBADF => unreachable, // Handle not open for writing548 wasi.EBADF => unreachable, // Handle not open for writing
538 wasi.EINVAL => unreachable, // Handle not open for writing549 wasi.EINVAL => unreachable, // Handle not open for writing
550 wasi.ENOTCAPABLE => return error.NotCapable,
539 else => |err| return unexpectedErrno(err),551 else => |err| return unexpectedErrno(err),
540 }552 }
541 }553 }
...@@ -604,6 +616,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize {...@@ -604,6 +616,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize {
604 wasi.ENXIO => return error.Unseekable,616 wasi.ENXIO => return error.Unseekable,
605 wasi.ESPIPE => return error.Unseekable,617 wasi.ESPIPE => return error.Unseekable,
606 wasi.EOVERFLOW => return error.Unseekable,618 wasi.EOVERFLOW => return error.Unseekable,
619 wasi.ENOTCAPABLE => return error.NotCapable,
607 else => |err| return unexpectedErrno(err),620 else => |err| return unexpectedErrno(err),
608 }621 }
609 }622 }
...@@ -649,6 +662,10 @@ pub const WriteError = error{...@@ -649,6 +662,10 @@ pub const WriteError = error{
649 /// This error occurs when no global event loop is configured,662 /// This error occurs when no global event loop is configured,
650 /// and reading from the file descriptor would block.663 /// and reading from the file descriptor would block.
651 WouldBlock,664 WouldBlock,
665
666 /// WASI-only. This error occurs when the file descriptor does
667 /// not hold the required rights to write to it.
668 NotCapable,
652} || UnexpectedError;669} || UnexpectedError;
653670
654/// Write to a file descriptor.671/// Write to a file descriptor.
...@@ -697,6 +714,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {...@@ -697,6 +714,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
697 wasi.ENOSPC => return error.NoSpaceLeft,714 wasi.ENOSPC => return error.NoSpaceLeft,
698 wasi.EPERM => return error.AccessDenied,715 wasi.EPERM => return error.AccessDenied,
699 wasi.EPIPE => return error.BrokenPipe,716 wasi.EPIPE => return error.BrokenPipe,
717 wasi.ENOTCAPABLE => return error.NotCapable,
700 else => |err| return unexpectedErrno(err),718 else => |err| return unexpectedErrno(err),
701 }719 }
702 }720 }
...@@ -774,6 +792,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize {...@@ -774,6 +792,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize {
774 wasi.ENOSPC => return error.NoSpaceLeft,792 wasi.ENOSPC => return error.NoSpaceLeft,
775 wasi.EPERM => return error.AccessDenied,793 wasi.EPERM => return error.AccessDenied,
776 wasi.EPIPE => return error.BrokenPipe,794 wasi.EPIPE => return error.BrokenPipe,
795 wasi.ENOTCAPABLE => return error.NotCapable,
777 else => |err| return unexpectedErrno(err),796 else => |err| return unexpectedErrno(err),
778 }797 }
779 }798 }
...@@ -856,6 +875,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {...@@ -856,6 +875,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
856 wasi.ENXIO => return error.Unseekable,875 wasi.ENXIO => return error.Unseekable,
857 wasi.ESPIPE => return error.Unseekable,876 wasi.ESPIPE => return error.Unseekable,
858 wasi.EOVERFLOW => return error.Unseekable,877 wasi.EOVERFLOW => return error.Unseekable,
878 wasi.ENOTCAPABLE => return error.NotCapable,
859 else => |err| return unexpectedErrno(err),879 else => |err| return unexpectedErrno(err),
860 }880 }
861 }881 }
...@@ -949,6 +969,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz...@@ -949,6 +969,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz
949 wasi.ENXIO => return error.Unseekable,969 wasi.ENXIO => return error.Unseekable,
950 wasi.ESPIPE => return error.Unseekable,970 wasi.ESPIPE => return error.Unseekable,
951 wasi.EOVERFLOW => return error.Unseekable,971 wasi.EOVERFLOW => return error.Unseekable,
972 wasi.ENOTCAPABLE => return error.NotCapable,
952 else => |err| return unexpectedErrno(err),973 else => |err| return unexpectedErrno(err),
953 }974 }
954 }975 }
...@@ -1020,6 +1041,10 @@ pub const OpenError = error{...@@ -1020,6 +1041,10 @@ pub const OpenError = error{
10201041
1021 /// The underlying filesystem does not support file locks1042 /// The underlying filesystem does not support file locks
1022 FileLocksNotSupported,1043 FileLocksNotSupported,
1044
1045 /// WASI-only. This error occurs when the file descriptor does
1046 /// not hold the required rights to open a new resource relative to it.
1047 NotCapable,
1023} || UnexpectedError;1048} || UnexpectedError;
10241049
1025/// Open and possibly create a file. Keeps trying if it gets interrupted.1050/// Open and possibly create a file. Keeps trying if it gets interrupted.
...@@ -1113,6 +1138,7 @@ pub fn openatWasi(dir_fd: fd_t, file_path: []const u8, oflags: oflags_t, fdflags...@@ -1113,6 +1138,7 @@ pub fn openatWasi(dir_fd: fd_t, file_path: []const u8, oflags: oflags_t, fdflags
1113 wasi.EPERM => return error.AccessDenied,1138 wasi.EPERM => return error.AccessDenied,
1114 wasi.EEXIST => return error.PathAlreadyExists,1139 wasi.EEXIST => return error.PathAlreadyExists,
1115 wasi.EBUSY => return error.DeviceBusy,1140 wasi.EBUSY => return error.DeviceBusy,
1141 wasi.ENOTCAPABLE => return error.NotCapable,
1116 else => |err| return unexpectedErrno(err),1142 else => |err| return unexpectedErrno(err),
1117 }1143 }
1118 }1144 }
...@@ -1563,13 +1589,19 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin...@@ -1563,13 +1589,19 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin
1563 }1589 }
1564}1590}
15651591
1592pub const SymlinkatError = error{
1593 /// WASI-only. This error occurs when the file descriptor does
1594 /// not hold the required rights to create a new symbolic link relative to it.
1595 NotCapable,
1596} || SymlinkError;
1597
1566/// Similar to `symlink`, however, creates a symbolic link named `sym_link_path` which contains the string1598/// Similar to `symlink`, however, creates a symbolic link named `sym_link_path` which contains the string
1567/// `target_path` **relative** to `newdirfd` directory handle.1599/// `target_path` **relative** to `newdirfd` directory handle.
1568/// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent1600/// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent
1569/// one; the latter case is known as a dangling link.1601/// one; the latter case is known as a dangling link.
1570/// If `sym_link_path` exists, it will not be overwritten.1602/// If `sym_link_path` exists, it will not be overwritten.
1571/// See also `symlinkatWasi`, `symlinkatZ` and `symlinkatW`.1603/// See also `symlinkatWasi`, `symlinkatZ` and `symlinkatW`.
1572pub fn symlinkat(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const u8) SymLinkError!void {1604pub fn symlinkat(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const u8) SymLinkatError!void {
1573 if (builtin.os.tag == .wasi) {1605 if (builtin.os.tag == .wasi) {
1574 return symlinkatWasi(target_path, newdirfd, sym_link_path);1606 return symlinkatWasi(target_path, newdirfd, sym_link_path);
1575 }1607 }
...@@ -1587,7 +1619,7 @@ pub const symlinkatC = @compileError("deprecated: renamed to symlinkatZ");...@@ -1587,7 +1619,7 @@ pub const symlinkatC = @compileError("deprecated: renamed to symlinkatZ");
15871619
1588/// WASI-only. The same as `symlinkat` but targeting WASI.1620/// WASI-only. The same as `symlinkat` but targeting WASI.
1589/// See also `symlinkat`.1621/// See also `symlinkat`.
1590pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const u8) SymLinkError!void {1622pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const u8) SymLinkatError!void {
1591 switch (wasi.path_symlink(target_path.ptr, target_path.len, newdirfd, sym_link_path.ptr, sym_link_path.len)) {1623 switch (wasi.path_symlink(target_path.ptr, target_path.len, newdirfd, sym_link_path.ptr, sym_link_path.len)) {
1592 wasi.ESUCCESS => {},1624 wasi.ESUCCESS => {},
1593 wasi.EFAULT => unreachable,1625 wasi.EFAULT => unreachable,
...@@ -1604,19 +1636,20 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c...@@ -1604,19 +1636,20 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c
1604 wasi.ENOMEM => return error.SystemResources,1636 wasi.ENOMEM => return error.SystemResources,
1605 wasi.ENOSPC => return error.NoSpaceLeft,1637 wasi.ENOSPC => return error.NoSpaceLeft,
1606 wasi.EROFS => return error.ReadOnlyFileSystem,1638 wasi.EROFS => return error.ReadOnlyFileSystem,
1639 wasi.ENOTCAPABLE => return error.NotCapable,
1607 else => |err| return unexpectedErrno(err),1640 else => |err| return unexpectedErrno(err),
1608 }1641 }
1609}1642}
16101643
1611/// Windows-only. The same as `symlinkat` except the paths are null-terminated, WTF-16 encoded.1644/// Windows-only. The same as `symlinkat` except the paths are null-terminated, WTF-16 encoded.
1612/// See also `symlinkat`.1645/// See also `symlinkat`.
1613pub fn symlinkatW(target_path: [*:0]const u16, newdirfd: fd_t, sym_link_path: [*:0]const u16) SymlinkError!void {1646pub fn symlinkatW(target_path: [*:0]const u16, newdirfd: fd_t, sym_link_path: [*:0]const u16) SymlinkatError!void {
1614 @compileError("TODO implement on Windows");1647 @compileError("TODO implement on Windows");
1615}1648}
16161649
1617/// The same as `symlinkat` except the parameters are null-terminated pointers.1650/// The same as `symlinkat` except the parameters are null-terminated pointers.
1618/// See also `symlinkat`.1651/// See also `symlinkat`.
1619pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*:0]const u8) SymLinkError!void {1652pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*:0]const u8) SymLinkatError!void {
1620 if (builtin.os.tag == .windows) {1653 if (builtin.os.tag == .windows) {
1621 const target_path_w = try windows.cStrToPrefixedFileW(target_path);1654 const target_path_w = try windows.cStrToPrefixedFileW(target_path);
1622 const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);1655 const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);
...@@ -1706,6 +1739,10 @@ pub fn unlinkZ(file_path: [*:0]const u8) UnlinkError!void {...@@ -1706,6 +1739,10 @@ pub fn unlinkZ(file_path: [*:0]const u8) UnlinkError!void {
1706pub const UnlinkatError = UnlinkError || error{1739pub const UnlinkatError = UnlinkError || error{
1707 /// When passing `AT_REMOVEDIR`, this error occurs when the named directory is not empty.1740 /// When passing `AT_REMOVEDIR`, this error occurs when the named directory is not empty.
1708 DirNotEmpty,1741 DirNotEmpty,
1742
1743 /// WASI-only. This error occurs when the file descriptor does
1744 /// not hold the required rights to unlink a resource by path relative to it.
1745 NotCapable,
1709};1746};
17101747
1711/// Delete a file name and possibly the file it refers to, based on an open directory handle.1748/// Delete a file name and possibly the file it refers to, based on an open directory handle.
...@@ -1747,6 +1784,7 @@ pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatErro...@@ -1747,6 +1784,7 @@ pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatErro
1747 wasi.ENOMEM => return error.SystemResources,1784 wasi.ENOMEM => return error.SystemResources,
1748 wasi.EROFS => return error.ReadOnlyFileSystem,1785 wasi.EROFS => return error.ReadOnlyFileSystem,
1749 wasi.ENOTEMPTY => return error.DirNotEmpty,1786 wasi.ENOTEMPTY => return error.DirNotEmpty,
1787 wasi.ENOTCAPABLE => return error.NotCapable,
17501788
1751 wasi.EINVAL => unreachable, // invalid flags, or pathname has . as last component1789 wasi.EINVAL => unreachable, // invalid flags, or pathname has . as last component
1752 wasi.EBADF => unreachable, // always a race condition1790 wasi.EBADF => unreachable, // always a race condition
...@@ -1925,13 +1963,19 @@ pub fn renameW(old_path: [*:0]const u16, new_path: [*:0]const u16) RenameError!v...@@ -1925,13 +1963,19 @@ pub fn renameW(old_path: [*:0]const u16, new_path: [*:0]const u16) RenameError!v
1925 return windows.MoveFileExW(old_path, new_path, flags);1963 return windows.MoveFileExW(old_path, new_path, flags);
1926}1964}
19271965
1966pub const RenameatError = error{
1967 /// WASI-only. This error occurs when the file descriptor does
1968 /// not hold the required rights to rename a resource by path relative to it.
1969 NotCapable,
1970} || RenameError;
1971
1928/// Change the name or location of a file based on an open directory handle.1972/// Change the name or location of a file based on an open directory handle.
1929pub fn renameat(1973pub fn renameat(
1930 old_dir_fd: fd_t,1974 old_dir_fd: fd_t,
1931 old_path: []const u8,1975 old_path: []const u8,
1932 new_dir_fd: fd_t,1976 new_dir_fd: fd_t,
1933 new_path: []const u8,1977 new_path: []const u8,
1934) RenameError!void {1978) RenameatError!void {
1935 if (builtin.os.tag == .windows) {1979 if (builtin.os.tag == .windows) {
1936 const old_path_w = try windows.sliceToPrefixedFileW(old_path);1980 const old_path_w = try windows.sliceToPrefixedFileW(old_path);
1937 const new_path_w = try windows.sliceToPrefixedFileW(new_path);1981 const new_path_w = try windows.sliceToPrefixedFileW(new_path);
...@@ -1947,7 +1991,7 @@ pub fn renameat(...@@ -1947,7 +1991,7 @@ pub fn renameat(
19471991
1948/// WASI-only. Same as `renameat` expect targeting WASI.1992/// WASI-only. Same as `renameat` expect targeting WASI.
1949/// See also `renameat`.1993/// See also `renameat`.
1950pub fn renameatWasi(old_dir_fd: fd_t, old_path: []const u8, new_dir_fd: fd_t, new_path: []const u8) RenameError!void {1994pub fn renameatWasi(old_dir_fd: fd_t, old_path: []const u8, new_dir_fd: fd_t, new_path: []const u8) RenameatError!void {
1951 switch (wasi.path_rename(old_dir_fd, old_path.ptr, old_path.len, new_dir_fd, new_path.ptr, new_path.len)) {1995 switch (wasi.path_rename(old_dir_fd, old_path.ptr, old_path.len, new_dir_fd, new_path.ptr, new_path.len)) {
1952 wasi.ESUCCESS => return,1996 wasi.ESUCCESS => return,
1953 wasi.EACCES => return error.AccessDenied,1997 wasi.EACCES => return error.AccessDenied,
...@@ -1968,6 +2012,7 @@ pub fn renameatWasi(old_dir_fd: fd_t, old_path: []const u8, new_dir_fd: fd_t, ne...@@ -1968,6 +2012,7 @@ pub fn renameatWasi(old_dir_fd: fd_t, old_path: []const u8, new_dir_fd: fd_t, ne
1968 wasi.ENOTEMPTY => return error.PathAlreadyExists,2012 wasi.ENOTEMPTY => return error.PathAlreadyExists,
1969 wasi.EROFS => return error.ReadOnlyFileSystem,2013 wasi.EROFS => return error.ReadOnlyFileSystem,
1970 wasi.EXDEV => return error.RenameAcrossMountPoints,2014 wasi.EXDEV => return error.RenameAcrossMountPoints,
2015 wasi.ENOTCAPABLE => return error.NotCapable,
1971 else => |err| return unexpectedErrno(err),2016 else => |err| return unexpectedErrno(err),
1972 }2017 }
1973}2018}
...@@ -1978,7 +2023,7 @@ pub fn renameatZ(...@@ -1978,7 +2023,7 @@ pub fn renameatZ(
1978 old_path: [*:0]const u8,2023 old_path: [*:0]const u8,
1979 new_dir_fd: fd_t,2024 new_dir_fd: fd_t,
1980 new_path: [*:0]const u8,2025 new_path: [*:0]const u8,
1981) RenameError!void {2026) RenameatError!void {
1982 if (builtin.os.tag == .windows) {2027 if (builtin.os.tag == .windows) {
1983 const old_path_w = try windows.cStrToPrefixedFileW(old_path);2028 const old_path_w = try windows.cStrToPrefixedFileW(old_path);
1984 const new_path_w = try windows.cStrToPrefixedFileW(new_path);2029 const new_path_w = try windows.cStrToPrefixedFileW(new_path);
...@@ -2017,7 +2062,7 @@ pub fn renameatW(...@@ -2017,7 +2062,7 @@ pub fn renameatW(
2017 new_dir_fd: fd_t,2062 new_dir_fd: fd_t,
2018 new_path_w: []const u16,2063 new_path_w: []const u16,
2019 ReplaceIfExists: windows.BOOLEAN,2064 ReplaceIfExists: windows.BOOLEAN,
2020) RenameError!void {2065) RenameatError!void {
2021 const src_fd = windows.OpenFile(old_path_w, .{2066 const src_fd = windows.OpenFile(old_path_w, .{
2022 .dir = old_dir_fd,2067 .dir = old_dir_fd,
2023 .access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE,2068 .access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE,
...@@ -2066,24 +2111,13 @@ pub fn renameatW(...@@ -2066,24 +2111,13 @@ pub fn renameatW(
2066 }2111 }
2067}2112}
20682113
2069pub const MakeDirError = error{2114pub const MakeDirAtError = error{
2070 AccessDenied,2115 /// WASI-only. This error occurs when the file descriptor does
2071 DiskQuota,2116 /// not hold the required rights to create a new directory relative to it.
2072 PathAlreadyExists,2117 NotCapable,
2073 SymLinkLoop,2118} || MakeDirError;
2074 LinkQuotaExceeded,
2075 NameTooLong,
2076 FileNotFound,
2077 SystemResources,
2078 NoSpaceLeft,
2079 NotDir,
2080 ReadOnlyFileSystem,
2081 InvalidUtf8,
2082 BadPathName,
2083 NoDevice,
2084} || UnexpectedError;
20852119
2086pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!void {2120pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirAtError!void {
2087 if (builtin.os.tag == .windows) {2121 if (builtin.os.tag == .windows) {
2088 const sub_dir_path_w = try windows.sliceToPrefixedFileW(sub_dir_path);2122 const sub_dir_path_w = try windows.sliceToPrefixedFileW(sub_dir_path);
2089 return mkdiratW(dir_fd, sub_dir_path_w.span().ptr, mode);2123 return mkdiratW(dir_fd, sub_dir_path_w.span().ptr, mode);
...@@ -2097,7 +2131,7 @@ pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!v...@@ -2097,7 +2131,7 @@ pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!v
20972131
2098pub const mkdiratC = @compileError("deprecated: renamed to mkdiratZ");2132pub const mkdiratC = @compileError("deprecated: renamed to mkdiratZ");
20992133
2100pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!void {2134pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirAtError!void {
2101 switch (wasi.path_create_directory(dir_fd, sub_dir_path.ptr, sub_dir_path.len)) {2135 switch (wasi.path_create_directory(dir_fd, sub_dir_path.ptr, sub_dir_path.len)) {
2102 wasi.ESUCCESS => return,2136 wasi.ESUCCESS => return,
2103 wasi.EACCES => return error.AccessDenied,2137 wasi.EACCES => return error.AccessDenied,
...@@ -2114,11 +2148,12 @@ pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirErr...@@ -2114,11 +2148,12 @@ pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirErr
2114 wasi.ENOSPC => return error.NoSpaceLeft,2148 wasi.ENOSPC => return error.NoSpaceLeft,
2115 wasi.ENOTDIR => return error.NotDir,2149 wasi.ENOTDIR => return error.NotDir,
2116 wasi.EROFS => return error.ReadOnlyFileSystem,2150 wasi.EROFS => return error.ReadOnlyFileSystem,
2151 wasi.ENOTCAPABLE => return error.NotCapable,
2117 else => |err| return unexpectedErrno(err),2152 else => |err| return unexpectedErrno(err),
2118 }2153 }
2119}2154}
21202155
2121pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirError!void {2156pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirAtError!void {
2122 if (builtin.os.tag == .windows) {2157 if (builtin.os.tag == .windows) {
2123 const sub_dir_path_w = try windows.cStrToPrefixedFileW(sub_dir_path);2158 const sub_dir_path_w = try windows.cStrToPrefixedFileW(sub_dir_path);
2124 return mkdiratW(dir_fd, sub_dir_path_w.span().ptr, mode);2159 return mkdiratW(dir_fd, sub_dir_path_w.span().ptr, mode);
...@@ -2143,11 +2178,28 @@ pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirErr...@@ -2143,11 +2178,28 @@ pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirErr
2143 }2178 }
2144}2179}
21452180
2146pub fn mkdiratW(dir_fd: fd_t, sub_path_w: [*:0]const u16, mode: u32) MakeDirError!void {2181pub fn mkdiratW(dir_fd: fd_t, sub_path_w: [*:0]const u16, mode: u32) MakeDirAtError!void {
2147 const sub_dir_handle = try windows.CreateDirectoryW(dir_fd, sub_path_w, null);2182 const sub_dir_handle = try windows.CreateDirectoryW(dir_fd, sub_path_w, null);
2148 windows.CloseHandle(sub_dir_handle);2183 windows.CloseHandle(sub_dir_handle);
2149}2184}
21502185
2186pub const MakeDirError = error{
2187 AccessDenied,
2188 DiskQuota,
2189 PathAlreadyExists,
2190 SymLinkLoop,
2191 LinkQuotaExceeded,
2192 NameTooLong,
2193 FileNotFound,
2194 SystemResources,
2195 NoSpaceLeft,
2196 NotDir,
2197 ReadOnlyFileSystem,
2198 InvalidUtf8,
2199 BadPathName,
2200 NoDevice,
2201} || UnexpectedError;
2202
2151/// Create a directory.2203/// Create a directory.
2152/// `mode` is ignored on Windows.2204/// `mode` is ignored on Windows.
2153pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {2205pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
...@@ -2364,10 +2416,16 @@ pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8...@@ -2364,10 +2416,16 @@ pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8
2364 }2416 }
2365}2417}
23662418
2419pub const ReadLinkAtError = error{
2420 /// WASI-only. This error occurs when the file descriptor does
2421 /// not hold the required rights to read value of a symbolic link relative to it.
2422 NotCapable,
2423} || ReadLinkError;
2424
2367/// Similar to `readlink` except reads value of a symbolink link **relative** to `dirfd` directory handle.2425/// Similar to `readlink` except reads value of a symbolink link **relative** to `dirfd` directory handle.
2368/// The return value is a slice of `out_buffer` from index 0.2426/// The return value is a slice of `out_buffer` from index 0.
2369/// See also `readlinkatWasi`, `realinkatZ` and `realinkatW`.2427/// See also `readlinkatWasi`, `realinkatZ` and `realinkatW`.
2370pub fn readlinkat(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {2428pub fn readlinkat(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLinkAtError![]u8 {
2371 if (builtin.os.tag == .wasi) {2429 if (builtin.os.tag == .wasi) {
2372 return readlinkatWasi(dirfd, file_path, out_buffer);2430 return readlinkatWasi(dirfd, file_path, out_buffer);
2373 }2431 }
...@@ -2383,7 +2441,7 @@ pub const readlinkatC = @compileError("deprecated: renamed to readlinkatZ");...@@ -2383,7 +2441,7 @@ pub const readlinkatC = @compileError("deprecated: renamed to readlinkatZ");
23832441
2384/// WASI-only. Same as `readlinkat` but targets WASI.2442/// WASI-only. Same as `readlinkat` but targets WASI.
2385/// See also `readlinkat`.2443/// See also `readlinkat`.
2386pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {2444pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLinkAtError![]u8 {
2387 var bufused: usize = undefined;2445 var bufused: usize = undefined;
2388 switch (wasi.path_readlink(dirfd, file_path.ptr, file_path.len, out_buffer.ptr, out_buffer.len, &bufused)) {2446 switch (wasi.path_readlink(dirfd, file_path.ptr, file_path.len, out_buffer.ptr, out_buffer.len, &bufused)) {
2389 wasi.ESUCCESS => return out_buffer[0..bufused],2447 wasi.ESUCCESS => return out_buffer[0..bufused],
...@@ -2396,19 +2454,20 @@ pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) Read...@@ -2396,19 +2454,20 @@ pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) Read
2396 wasi.ENOENT => return error.FileNotFound,2454 wasi.ENOENT => return error.FileNotFound,
2397 wasi.ENOMEM => return error.SystemResources,2455 wasi.ENOMEM => return error.SystemResources,
2398 wasi.ENOTDIR => return error.NotDir,2456 wasi.ENOTDIR => return error.NotDir,
2457 wasi.ENOTCAPABLE => return error.NotCapable,
2399 else => |err| return unexpectedErrno(err),2458 else => |err| return unexpectedErrno(err),
2400 }2459 }
2401}2460}
24022461
2403/// Windows-only. Same as `readlinkat` except `file_path` is null-terminated, WTF16 encoded.2462/// Windows-only. Same as `readlinkat` except `file_path` is null-terminated, WTF16 encoded.
2404/// See also `readlinkat`.2463/// See also `readlinkat`.
2405pub fn readlinkatW(dirfd: fd_t, file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 {2464pub fn readlinkatW(dirfd: fd_t, file_path: [*:0]const u16, out_buffer: []u8) ReadLinkAtError![]u8 {
2406 @compileError("TODO implement on Windows");2465 @compileError("TODO implement on Windows");
2407}2466}
24082467
2409/// Same as `readlinkat` except `file_path` is null-terminated.2468/// Same as `readlinkat` except `file_path` is null-terminated.
2410/// See also `readlinkat`.2469/// See also `readlinkat`.
2411pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {2470pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkAtError![]u8 {
2412 if (builtin.os.tag == .windows) {2471 if (builtin.os.tag == .windows) {
2413 const file_path_w = try windows.cStrToPrefixedFileW(file_path);2472 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
2414 return readlinkatW(dirfd, file_path_w.span().ptr, out_buffer);2473 return readlinkatW(dirfd, file_path_w.span().ptr, out_buffer);
...@@ -3074,6 +3133,10 @@ pub fn waitpid(pid: i32, flags: u32) u32 {...@@ -3074,6 +3133,10 @@ pub fn waitpid(pid: i32, flags: u32) u32 {
3074pub const FStatError = error{3133pub const FStatError = error{
3075 SystemResources,3134 SystemResources,
3076 AccessDenied,3135 AccessDenied,
3136
3137 /// WASI-only. This error occurs when the file descriptor does
3138 /// not hold the required rights to get its filestat information.
3139 NotCapable,
3077} || UnexpectedError;3140} || UnexpectedError;
30783141
3079/// Return information about a file descriptor.3142/// Return information about a file descriptor.
...@@ -3086,6 +3149,7 @@ pub fn fstat(fd: fd_t) FStatError!Stat {...@@ -3086,6 +3149,7 @@ pub fn fstat(fd: fd_t) FStatError!Stat {
3086 wasi.EBADF => unreachable, // Always a race condition.3149 wasi.EBADF => unreachable, // Always a race condition.
3087 wasi.ENOMEM => return error.SystemResources,3150 wasi.ENOMEM => return error.SystemResources,
3088 wasi.EACCES => return error.AccessDenied,3151 wasi.EACCES => return error.AccessDenied,
3152 wasi.ENOTCAPABLE => return error.NotCapable,
3089 else => |err| return unexpectedErrno(err),3153 else => |err| return unexpectedErrno(err),
3090 }3154 }
3091 }3155 }
...@@ -3136,6 +3200,7 @@ pub fn fstatatWasi(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!S...@@ -3136,6 +3200,7 @@ pub fn fstatatWasi(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!S
3136 wasi.ENAMETOOLONG => return error.NameTooLong,3200 wasi.ENAMETOOLONG => return error.NameTooLong,
3137 wasi.ENOENT => return error.FileNotFound,3201 wasi.ENOENT => return error.FileNotFound,
3138 wasi.ENOTDIR => return error.FileNotFound,3202 wasi.ENOTDIR => return error.FileNotFound,
3203 wasi.ENOTCAPABLE => return error.NotCapable,
3139 else => |err| return unexpectedErrno(err),3204 else => |err| return unexpectedErrno(err),
3140 }3205 }
3141}3206}
...@@ -3641,7 +3706,13 @@ pub fn gettimeofday(tv: ?*timeval, tz: ?*timezone) void {...@@ -3641,7 +3706,13 @@ pub fn gettimeofday(tv: ?*timeval, tz: ?*timezone) void {
3641 }3706 }
3642}3707}
36433708
3644pub const SeekError = error{Unseekable} || UnexpectedError;3709pub const SeekError = error{
3710 Unseekable,
3711
3712 /// WASI-only. This error occurs when the file descriptor does
3713 /// not hold the required rights to seek on it.
3714 NotCapable,
3715} || UnexpectedError;
36453716
3646/// Repositions read/write file offset relative to the beginning.3717/// Repositions read/write file offset relative to the beginning.
3647pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {3718pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {
...@@ -3669,6 +3740,7 @@ pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {...@@ -3669,6 +3740,7 @@ pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {
3669 wasi.EOVERFLOW => return error.Unseekable,3740 wasi.EOVERFLOW => return error.Unseekable,
3670 wasi.ESPIPE => return error.Unseekable,3741 wasi.ESPIPE => return error.Unseekable,
3671 wasi.ENXIO => return error.Unseekable,3742 wasi.ENXIO => return error.Unseekable,
3743 wasi.ENOTCAPABLE => return error.NotCapable,
3672 else => |err| return unexpectedErrno(err),3744 else => |err| return unexpectedErrno(err),
3673 }3745 }
3674 }3746 }
...@@ -3710,6 +3782,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {...@@ -3710,6 +3782,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {
3710 wasi.EOVERFLOW => return error.Unseekable,3782 wasi.EOVERFLOW => return error.Unseekable,
3711 wasi.ESPIPE => return error.Unseekable,3783 wasi.ESPIPE => return error.Unseekable,
3712 wasi.ENXIO => return error.Unseekable,3784 wasi.ENXIO => return error.Unseekable,
3785 wasi.ENOTCAPABLE => return error.NotCapable,
3713 else => |err| return unexpectedErrno(err),3786 else => |err| return unexpectedErrno(err),
3714 }3787 }
3715 }3788 }
...@@ -3750,6 +3823,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {...@@ -3750,6 +3823,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {
3750 wasi.EOVERFLOW => return error.Unseekable,3823 wasi.EOVERFLOW => return error.Unseekable,
3751 wasi.ESPIPE => return error.Unseekable,3824 wasi.ESPIPE => return error.Unseekable,
3752 wasi.ENXIO => return error.Unseekable,3825 wasi.ENXIO => return error.Unseekable,
3826 wasi.ENOTCAPABLE => return error.NotCapable,
3753 else => |err| return unexpectedErrno(err),3827 else => |err| return unexpectedErrno(err),
3754 }3828 }
3755 }3829 }
...@@ -3790,6 +3864,7 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {...@@ -3790,6 +3864,7 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {
3790 wasi.EOVERFLOW => return error.Unseekable,3864 wasi.EOVERFLOW => return error.Unseekable,
3791 wasi.ESPIPE => return error.Unseekable,3865 wasi.ESPIPE => return error.Unseekable,
3792 wasi.ENXIO => return error.Unseekable,3866 wasi.ENXIO => return error.Unseekable,
3867 wasi.ENOTCAPABLE => return error.NotCapable,
3793 else => |err| return unexpectedErrno(err),3868 else => |err| return unexpectedErrno(err),
3794 }3869 }
3795 }3870 }