authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-01 23:12:26+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-07-01 23:12:26+00:00
logd2a4e5e226f2041e4a21e9353e1323b84017b3b1
tree39cfc5c3a868e8820f103c2e7d6f1919b4591843
parent30ae7f7573b7dcc3cd85f9e4cbab4e5608fdb3dd
parent8306826d53bf6dd0c5ea5ea27963374b31aa6dd1
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #5749 from kubkon/wasi-notcapable

[libstd]: handle ENOTCAPABLE in WASI

4 files changed, 87 insertions(+), 31 deletions(-)

lib/std/elf.zig+1
...@@ -551,6 +551,7 @@ fn preadNoEof(file: std.fs.File, buf: []u8, offset: u64) !void {...@@ -551,6 +551,7 @@ fn preadNoEof(file: std.fs.File, buf: []u8, offset: u64) !void {
551 error.InputOutput => return error.FileSystem,551 error.InputOutput => return error.FileSystem,
552 error.Unexpected => return error.Unexpected,552 error.Unexpected => return error.Unexpected,
553 error.WouldBlock => return error.Unexpected,553 error.WouldBlock => return error.Unexpected,
554 error.AccessDenied => return error.Unexpected,
554 };555 };
555 if (len == 0) return error.UnexpectedEndOfFile;556 if (len == 0) return error.UnexpectedEndOfFile;
556 i += len;557 i += len;
lib/std/fs.zig+9-8
...@@ -535,14 +535,15 @@ pub const Dir = struct {...@@ -535,14 +535,15 @@ pub const Dir = struct {
535 w.EFAULT => unreachable,535 w.EFAULT => unreachable,
536 w.ENOTDIR => unreachable,536 w.ENOTDIR => unreachable,
537 w.EINVAL => unreachable,537 w.EINVAL => unreachable,
538 w.ENOTCAPABLE => return error.AccessDenied,
538 else => |err| return os.unexpectedErrno(err),539 else => |err| return os.unexpectedErrno(err),
539 }540 }
540 if (bufused == 0) return null;541 if (bufused == 0) return null;
541 self.index = 0;542 self.index = 0;
542 self.end_index = bufused;543 self.end_index = bufused;
543 }544 }
544 const entry = @ptrCast(*align(1) os.wasi.dirent_t, &self.buf[self.index]);545 const entry = @ptrCast(*align(1) w.dirent_t, &self.buf[self.index]);
545 const entry_size = @sizeOf(os.wasi.dirent_t);546 const entry_size = @sizeOf(w.dirent_t);
546 const name_index = self.index + entry_size;547 const name_index = self.index + entry_size;
547 const name = mem.span(self.buf[name_index .. name_index + entry.d_namlen]);548 const name = mem.span(self.buf[name_index .. name_index + entry.d_namlen]);
548549
...@@ -556,12 +557,12 @@ pub const Dir = struct {...@@ -556,12 +557,12 @@ pub const Dir = struct {
556 }557 }
557558
558 const entry_kind = switch (entry.d_type) {559 const entry_kind = switch (entry.d_type) {
559 wasi.FILETYPE_BLOCK_DEVICE => Entry.Kind.BlockDevice,560 w.FILETYPE_BLOCK_DEVICE => Entry.Kind.BlockDevice,
560 wasi.FILETYPE_CHARACTER_DEVICE => Entry.Kind.CharacterDevice,561 w.FILETYPE_CHARACTER_DEVICE => Entry.Kind.CharacterDevice,
561 wasi.FILETYPE_DIRECTORY => Entry.Kind.Directory,562 w.FILETYPE_DIRECTORY => Entry.Kind.Directory,
562 wasi.FILETYPE_SYMBOLIC_LINK => Entry.Kind.SymLink,563 w.FILETYPE_SYMBOLIC_LINK => Entry.Kind.SymLink,
563 wasi.FILETYPE_REGULAR_FILE => Entry.Kind.File,564 w.FILETYPE_REGULAR_FILE => Entry.Kind.File,
564 wasi.FILETYPE_SOCKET_STREAM, wasi.FILETYPE_SOCKET_DGRAM => Entry.Kind.UnixDomainSocket,565 w.FILETYPE_SOCKET_STREAM, wasi.FILETYPE_SOCKET_DGRAM => Entry.Kind.UnixDomainSocket,
565 else => Entry.Kind.Unknown,566 else => Entry.Kind.Unknown,
566 };567 };
567 return Entry{568 return Entry{
lib/std/os.zig+76-23
...@@ -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 /// In WASI, this error occurs when the file descriptor does
305 /// not hold the required rights to read from it.
306 AccessDenied,
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.AccessDenied,
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.AccessDenied,
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.AccessDenied,
469 else => |err| return unexpectedErrno(err),476 else => |err| return unexpectedErrno(err),
470 }477 }
471 }478 }
...@@ -500,8 +507,11 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {...@@ -500,8 +507,11 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
500pub const TruncateError = error{507pub const TruncateError = error{
501 FileTooBig,508 FileTooBig,
502 InputOutput,509 InputOutput,
503 CannotTruncate,
504 FileBusy,510 FileBusy,
511
512 /// In WASI, this error occurs when the file descriptor does
513 /// not hold the required rights to call `ftruncate` on it.
514 AccessDenied,
505} || UnexpectedError;515} || UnexpectedError;
506516
507pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {517pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
...@@ -522,7 +532,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {...@@ -522,7 +532,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
522 switch (rc) {532 switch (rc) {
523 .SUCCESS => return,533 .SUCCESS => return,
524 .INVALID_HANDLE => unreachable, // Handle not open for writing534 .INVALID_HANDLE => unreachable, // Handle not open for writing
525 .ACCESS_DENIED => return error.CannotTruncate,535 .ACCESS_DENIED => return error.AccessDenied,
526 else => return windows.unexpectedStatus(rc),536 else => return windows.unexpectedStatus(rc),
527 }537 }
528 }538 }
...@@ -532,10 +542,11 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {...@@ -532,10 +542,11 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
532 wasi.EINTR => unreachable,542 wasi.EINTR => unreachable,
533 wasi.EFBIG => return error.FileTooBig,543 wasi.EFBIG => return error.FileTooBig,
534 wasi.EIO => return error.InputOutput,544 wasi.EIO => return error.InputOutput,
535 wasi.EPERM => return error.CannotTruncate,545 wasi.EPERM => return error.AccessDenied,
536 wasi.ETXTBSY => return error.FileBusy,546 wasi.ETXTBSY => return error.FileBusy,
537 wasi.EBADF => unreachable, // Handle not open for writing547 wasi.EBADF => unreachable, // Handle not open for writing
538 wasi.EINVAL => unreachable, // Handle not open for writing548 wasi.EINVAL => unreachable, // Handle not open for writing
549 wasi.ENOTCAPABLE => return error.AccessDenied,
539 else => |err| return unexpectedErrno(err),550 else => |err| return unexpectedErrno(err),
540 }551 }
541 }552 }
...@@ -554,7 +565,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {...@@ -554,7 +565,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
554 EINTR => continue,565 EINTR => continue,
555 EFBIG => return error.FileTooBig,566 EFBIG => return error.FileTooBig,
556 EIO => return error.InputOutput,567 EIO => return error.InputOutput,
557 EPERM => return error.CannotTruncate,568 EPERM => return error.AccessDenied,
558 ETXTBSY => return error.FileBusy,569 ETXTBSY => return error.FileBusy,
559 EBADF => unreachable, // Handle not open for writing570 EBADF => unreachable, // Handle not open for writing
560 EINVAL => unreachable, // Handle not open for writing571 EINVAL => unreachable, // Handle not open for writing
...@@ -604,6 +615,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize {...@@ -604,6 +615,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize {
604 wasi.ENXIO => return error.Unseekable,615 wasi.ENXIO => return error.Unseekable,
605 wasi.ESPIPE => return error.Unseekable,616 wasi.ESPIPE => return error.Unseekable,
606 wasi.EOVERFLOW => return error.Unseekable,617 wasi.EOVERFLOW => return error.Unseekable,
618 wasi.ENOTCAPABLE => return error.AccessDenied,
607 else => |err| return unexpectedErrno(err),619 else => |err| return unexpectedErrno(err),
608 }620 }
609 }621 }
...@@ -641,6 +653,9 @@ pub const WriteError = error{...@@ -641,6 +653,9 @@ pub const WriteError = error{
641 FileTooBig,653 FileTooBig,
642 InputOutput,654 InputOutput,
643 NoSpaceLeft,655 NoSpaceLeft,
656
657 /// In WASI, this error may occur when the file descriptor does
658 /// not hold the required rights to write to it.
644 AccessDenied,659 AccessDenied,
645 BrokenPipe,660 BrokenPipe,
646 SystemResources,661 SystemResources,
...@@ -697,6 +712,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {...@@ -697,6 +712,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
697 wasi.ENOSPC => return error.NoSpaceLeft,712 wasi.ENOSPC => return error.NoSpaceLeft,
698 wasi.EPERM => return error.AccessDenied,713 wasi.EPERM => return error.AccessDenied,
699 wasi.EPIPE => return error.BrokenPipe,714 wasi.EPIPE => return error.BrokenPipe,
715 wasi.ENOTCAPABLE => return error.AccessDenied,
700 else => |err| return unexpectedErrno(err),716 else => |err| return unexpectedErrno(err),
701 }717 }
702 }718 }
...@@ -774,6 +790,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize {...@@ -774,6 +790,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize {
774 wasi.ENOSPC => return error.NoSpaceLeft,790 wasi.ENOSPC => return error.NoSpaceLeft,
775 wasi.EPERM => return error.AccessDenied,791 wasi.EPERM => return error.AccessDenied,
776 wasi.EPIPE => return error.BrokenPipe,792 wasi.EPIPE => return error.BrokenPipe,
793 wasi.ENOTCAPABLE => return error.AccessDenied,
777 else => |err| return unexpectedErrno(err),794 else => |err| return unexpectedErrno(err),
778 }795 }
779 }796 }
...@@ -856,6 +873,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {...@@ -856,6 +873,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
856 wasi.ENXIO => return error.Unseekable,873 wasi.ENXIO => return error.Unseekable,
857 wasi.ESPIPE => return error.Unseekable,874 wasi.ESPIPE => return error.Unseekable,
858 wasi.EOVERFLOW => return error.Unseekable,875 wasi.EOVERFLOW => return error.Unseekable,
876 wasi.ENOTCAPABLE => return error.AccessDenied,
859 else => |err| return unexpectedErrno(err),877 else => |err| return unexpectedErrno(err),
860 }878 }
861 }879 }
...@@ -949,6 +967,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz...@@ -949,6 +967,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz
949 wasi.ENXIO => return error.Unseekable,967 wasi.ENXIO => return error.Unseekable,
950 wasi.ESPIPE => return error.Unseekable,968 wasi.ESPIPE => return error.Unseekable,
951 wasi.EOVERFLOW => return error.Unseekable,969 wasi.EOVERFLOW => return error.Unseekable,
970 wasi.ENOTCAPABLE => return error.AccessDenied,
952 else => |err| return unexpectedErrno(err),971 else => |err| return unexpectedErrno(err),
953 }972 }
954 }973 }
...@@ -984,6 +1003,8 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz...@@ -984,6 +1003,8 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz
984}1003}
9851004
986pub const OpenError = error{1005pub const OpenError = error{
1006 /// In WASI, this error may occur when the file descriptor does
1007 /// not hold the required rights to open a new resource relative to it.
987 AccessDenied,1008 AccessDenied,
988 SymLinkLoop,1009 SymLinkLoop,
989 ProcessFdQuotaExceeded,1010 ProcessFdQuotaExceeded,
...@@ -1113,6 +1134,7 @@ pub fn openatWasi(dir_fd: fd_t, file_path: []const u8, oflags: oflags_t, fdflags...@@ -1113,6 +1134,7 @@ pub fn openatWasi(dir_fd: fd_t, file_path: []const u8, oflags: oflags_t, fdflags
1113 wasi.EPERM => return error.AccessDenied,1134 wasi.EPERM => return error.AccessDenied,
1114 wasi.EEXIST => return error.PathAlreadyExists,1135 wasi.EEXIST => return error.PathAlreadyExists,
1115 wasi.EBUSY => return error.DeviceBusy,1136 wasi.EBUSY => return error.DeviceBusy,
1137 wasi.ENOTCAPABLE => return error.AccessDenied,
1116 else => |err| return unexpectedErrno(err),1138 else => |err| return unexpectedErrno(err),
1117 }1139 }
1118 }1140 }
...@@ -1499,6 +1521,8 @@ pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {...@@ -1499,6 +1521,8 @@ pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {
1499}1521}
15001522
1501pub const SymLinkError = error{1523pub const SymLinkError = error{
1524 /// In WASI, this error may occur when the file descriptor does
1525 /// not hold the required rights to create a new symbolic link relative to it.
1502 AccessDenied,1526 AccessDenied,
1503 DiskQuota,1527 DiskQuota,
1504 PathAlreadyExists,1528 PathAlreadyExists,
...@@ -1604,13 +1628,14 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c...@@ -1604,13 +1628,14 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c
1604 wasi.ENOMEM => return error.SystemResources,1628 wasi.ENOMEM => return error.SystemResources,
1605 wasi.ENOSPC => return error.NoSpaceLeft,1629 wasi.ENOSPC => return error.NoSpaceLeft,
1606 wasi.EROFS => return error.ReadOnlyFileSystem,1630 wasi.EROFS => return error.ReadOnlyFileSystem,
1631 wasi.ENOTCAPABLE => return error.AccessDenied,
1607 else => |err| return unexpectedErrno(err),1632 else => |err| return unexpectedErrno(err),
1608 }1633 }
1609}1634}
16101635
1611/// Windows-only. The same as `symlinkat` except the paths are null-terminated, WTF-16 encoded.1636/// Windows-only. The same as `symlinkat` except the paths are null-terminated, WTF-16 encoded.
1612/// See also `symlinkat`.1637/// See also `symlinkat`.
1613pub fn symlinkatW(target_path: [*:0]const u16, newdirfd: fd_t, sym_link_path: [*:0]const u16) SymlinkError!void {1638pub fn symlinkatW(target_path: [*:0]const u16, newdirfd: fd_t, sym_link_path: [*:0]const u16) SymLinkError!void {
1614 @compileError("TODO implement on Windows");1639 @compileError("TODO implement on Windows");
1615}1640}
16161641
...@@ -1644,6 +1669,9 @@ pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*:...@@ -1644,6 +1669,9 @@ pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*:
16441669
1645pub const UnlinkError = error{1670pub const UnlinkError = error{
1646 FileNotFound,1671 FileNotFound,
1672
1673 /// In WASI, this error may occur when the file descriptor does
1674 /// not hold the required rights to unlink a resource by path relative to it.
1647 AccessDenied,1675 AccessDenied,
1648 FileBusy,1676 FileBusy,
1649 FileSystem,1677 FileSystem,
...@@ -1747,6 +1775,7 @@ pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatErro...@@ -1747,6 +1775,7 @@ pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatErro
1747 wasi.ENOMEM => return error.SystemResources,1775 wasi.ENOMEM => return error.SystemResources,
1748 wasi.EROFS => return error.ReadOnlyFileSystem,1776 wasi.EROFS => return error.ReadOnlyFileSystem,
1749 wasi.ENOTEMPTY => return error.DirNotEmpty,1777 wasi.ENOTEMPTY => return error.DirNotEmpty,
1778 wasi.ENOTCAPABLE => return error.AccessDenied,
17501779
1751 wasi.EINVAL => unreachable, // invalid flags, or pathname has . as last component1780 wasi.EINVAL => unreachable, // invalid flags, or pathname has . as last component
1752 wasi.EBADF => unreachable, // always a race condition1781 wasi.EBADF => unreachable, // always a race condition
...@@ -1849,6 +1878,8 @@ pub fn unlinkatW(dirfd: fd_t, sub_path_w: [*:0]const u16, flags: u32) UnlinkatEr...@@ -1849,6 +1878,8 @@ pub fn unlinkatW(dirfd: fd_t, sub_path_w: [*:0]const u16, flags: u32) UnlinkatEr
1849}1878}
18501879
1851const RenameError = error{1880const RenameError = error{
1881 /// In WASI, this error may occur when the file descriptor does
1882 /// not hold the required rights to rename a resource by path relative to it.
1852 AccessDenied,1883 AccessDenied,
1853 FileBusy,1884 FileBusy,
1854 DiskQuota,1885 DiskQuota,
...@@ -1968,6 +1999,7 @@ pub fn renameatWasi(old_dir_fd: fd_t, old_path: []const u8, new_dir_fd: fd_t, ne...@@ -1968,6 +1999,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,1999 wasi.ENOTEMPTY => return error.PathAlreadyExists,
1969 wasi.EROFS => return error.ReadOnlyFileSystem,2000 wasi.EROFS => return error.ReadOnlyFileSystem,
1970 wasi.EXDEV => return error.RenameAcrossMountPoints,2001 wasi.EXDEV => return error.RenameAcrossMountPoints,
2002 wasi.ENOTCAPABLE => return error.AccessDenied,
1971 else => |err| return unexpectedErrno(err),2003 else => |err| return unexpectedErrno(err),
1972 }2004 }
1973}2005}
...@@ -2066,23 +2098,6 @@ pub fn renameatW(...@@ -2066,23 +2098,6 @@ pub fn renameatW(
2066 }2098 }
2067}2099}
20682100
2069pub const MakeDirError = error{
2070 AccessDenied,
2071 DiskQuota,
2072 PathAlreadyExists,
2073 SymLinkLoop,
2074 LinkQuotaExceeded,
2075 NameTooLong,
2076 FileNotFound,
2077 SystemResources,
2078 NoSpaceLeft,
2079 NotDir,
2080 ReadOnlyFileSystem,
2081 InvalidUtf8,
2082 BadPathName,
2083 NoDevice,
2084} || UnexpectedError;
2085
2086pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!void {2101pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!void {
2087 if (builtin.os.tag == .windows) {2102 if (builtin.os.tag == .windows) {
2088 const sub_dir_path_w = try windows.sliceToPrefixedFileW(sub_dir_path);2103 const sub_dir_path_w = try windows.sliceToPrefixedFileW(sub_dir_path);
...@@ -2114,6 +2129,7 @@ pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirErr...@@ -2114,6 +2129,7 @@ pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirErr
2114 wasi.ENOSPC => return error.NoSpaceLeft,2129 wasi.ENOSPC => return error.NoSpaceLeft,
2115 wasi.ENOTDIR => return error.NotDir,2130 wasi.ENOTDIR => return error.NotDir,
2116 wasi.EROFS => return error.ReadOnlyFileSystem,2131 wasi.EROFS => return error.ReadOnlyFileSystem,
2132 wasi.ENOTCAPABLE => return error.AccessDenied,
2117 else => |err| return unexpectedErrno(err),2133 else => |err| return unexpectedErrno(err),
2118 }2134 }
2119}2135}
...@@ -2148,6 +2164,25 @@ pub fn mkdiratW(dir_fd: fd_t, sub_path_w: [*:0]const u16, mode: u32) MakeDirErro...@@ -2148,6 +2164,25 @@ pub fn mkdiratW(dir_fd: fd_t, sub_path_w: [*:0]const u16, mode: u32) MakeDirErro
2148 windows.CloseHandle(sub_dir_handle);2164 windows.CloseHandle(sub_dir_handle);
2149}2165}
21502166
2167pub const MakeDirError = error{
2168 /// In WASI, this error may occur when the file descriptor does
2169 /// not hold the required rights to create a new directory relative to it.
2170 AccessDenied,
2171 DiskQuota,
2172 PathAlreadyExists,
2173 SymLinkLoop,
2174 LinkQuotaExceeded,
2175 NameTooLong,
2176 FileNotFound,
2177 SystemResources,
2178 NoSpaceLeft,
2179 NotDir,
2180 ReadOnlyFileSystem,
2181 InvalidUtf8,
2182 BadPathName,
2183 NoDevice,
2184} || UnexpectedError;
2185
2151/// Create a directory.2186/// Create a directory.
2152/// `mode` is ignored on Windows.2187/// `mode` is ignored on Windows.
2153pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {2188pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
...@@ -2311,6 +2346,8 @@ pub fn fchdir(dirfd: fd_t) FchdirError!void {...@@ -2311,6 +2346,8 @@ pub fn fchdir(dirfd: fd_t) FchdirError!void {
2311}2346}
23122347
2313pub const ReadLinkError = error{2348pub const ReadLinkError = error{
2349 /// In WASI, this error may occur when the file descriptor does
2350 /// not hold the required rights to read value of a symbolic link relative to it.
2314 AccessDenied,2351 AccessDenied,
2315 FileSystem,2352 FileSystem,
2316 SymLinkLoop,2353 SymLinkLoop,
...@@ -2396,6 +2433,7 @@ pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) Read...@@ -2396,6 +2433,7 @@ pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) Read
2396 wasi.ENOENT => return error.FileNotFound,2433 wasi.ENOENT => return error.FileNotFound,
2397 wasi.ENOMEM => return error.SystemResources,2434 wasi.ENOMEM => return error.SystemResources,
2398 wasi.ENOTDIR => return error.NotDir,2435 wasi.ENOTDIR => return error.NotDir,
2436 wasi.ENOTCAPABLE => return error.AccessDenied,
2399 else => |err| return unexpectedErrno(err),2437 else => |err| return unexpectedErrno(err),
2400 }2438 }
2401}2439}
...@@ -3073,6 +3111,9 @@ pub fn waitpid(pid: i32, flags: u32) u32 {...@@ -3073,6 +3111,9 @@ pub fn waitpid(pid: i32, flags: u32) u32 {
30733111
3074pub const FStatError = error{3112pub const FStatError = error{
3075 SystemResources,3113 SystemResources,
3114
3115 /// In WASI, this error may occur when the file descriptor does
3116 /// not hold the required rights to get its filestat information.
3076 AccessDenied,3117 AccessDenied,
3077} || UnexpectedError;3118} || UnexpectedError;
30783119
...@@ -3086,6 +3127,7 @@ pub fn fstat(fd: fd_t) FStatError!Stat {...@@ -3086,6 +3127,7 @@ pub fn fstat(fd: fd_t) FStatError!Stat {
3086 wasi.EBADF => unreachable, // Always a race condition.3127 wasi.EBADF => unreachable, // Always a race condition.
3087 wasi.ENOMEM => return error.SystemResources,3128 wasi.ENOMEM => return error.SystemResources,
3088 wasi.EACCES => return error.AccessDenied,3129 wasi.EACCES => return error.AccessDenied,
3130 wasi.ENOTCAPABLE => return error.AccessDenied,
3089 else => |err| return unexpectedErrno(err),3131 else => |err| return unexpectedErrno(err),
3090 }3132 }
3091 }3133 }
...@@ -3136,6 +3178,7 @@ pub fn fstatatWasi(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!S...@@ -3136,6 +3178,7 @@ pub fn fstatatWasi(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!S
3136 wasi.ENAMETOOLONG => return error.NameTooLong,3178 wasi.ENAMETOOLONG => return error.NameTooLong,
3137 wasi.ENOENT => return error.FileNotFound,3179 wasi.ENOENT => return error.FileNotFound,
3138 wasi.ENOTDIR => return error.FileNotFound,3180 wasi.ENOTDIR => return error.FileNotFound,
3181 wasi.ENOTCAPABLE => return error.AccessDenied,
3139 else => |err| return unexpectedErrno(err),3182 else => |err| return unexpectedErrno(err),
3140 }3183 }
3141}3184}
...@@ -3641,7 +3684,13 @@ pub fn gettimeofday(tv: ?*timeval, tz: ?*timezone) void {...@@ -3641,7 +3684,13 @@ pub fn gettimeofday(tv: ?*timeval, tz: ?*timezone) void {
3641 }3684 }
3642}3685}
36433686
3644pub const SeekError = error{Unseekable} || UnexpectedError;3687pub const SeekError = error{
3688 Unseekable,
3689
3690 /// In WASI, this error may occur when the file descriptor does
3691 /// not hold the required rights to seek on it.
3692 AccessDenied,
3693} || UnexpectedError;
36453694
3646/// Repositions read/write file offset relative to the beginning.3695/// Repositions read/write file offset relative to the beginning.
3647pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {3696pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {
...@@ -3669,6 +3718,7 @@ pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {...@@ -3669,6 +3718,7 @@ pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {
3669 wasi.EOVERFLOW => return error.Unseekable,3718 wasi.EOVERFLOW => return error.Unseekable,
3670 wasi.ESPIPE => return error.Unseekable,3719 wasi.ESPIPE => return error.Unseekable,
3671 wasi.ENXIO => return error.Unseekable,3720 wasi.ENXIO => return error.Unseekable,
3721 wasi.ENOTCAPABLE => return error.AccessDenied,
3672 else => |err| return unexpectedErrno(err),3722 else => |err| return unexpectedErrno(err),
3673 }3723 }
3674 }3724 }
...@@ -3710,6 +3760,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {...@@ -3710,6 +3760,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {
3710 wasi.EOVERFLOW => return error.Unseekable,3760 wasi.EOVERFLOW => return error.Unseekable,
3711 wasi.ESPIPE => return error.Unseekable,3761 wasi.ESPIPE => return error.Unseekable,
3712 wasi.ENXIO => return error.Unseekable,3762 wasi.ENXIO => return error.Unseekable,
3763 wasi.ENOTCAPABLE => return error.AccessDenied,
3713 else => |err| return unexpectedErrno(err),3764 else => |err| return unexpectedErrno(err),
3714 }3765 }
3715 }3766 }
...@@ -3750,6 +3801,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {...@@ -3750,6 +3801,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {
3750 wasi.EOVERFLOW => return error.Unseekable,3801 wasi.EOVERFLOW => return error.Unseekable,
3751 wasi.ESPIPE => return error.Unseekable,3802 wasi.ESPIPE => return error.Unseekable,
3752 wasi.ENXIO => return error.Unseekable,3803 wasi.ENXIO => return error.Unseekable,
3804 wasi.ENOTCAPABLE => return error.AccessDenied,
3753 else => |err| return unexpectedErrno(err),3805 else => |err| return unexpectedErrno(err),
3754 }3806 }
3755 }3807 }
...@@ -3790,6 +3842,7 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {...@@ -3790,6 +3842,7 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {
3790 wasi.EOVERFLOW => return error.Unseekable,3842 wasi.EOVERFLOW => return error.Unseekable,
3791 wasi.ESPIPE => return error.Unseekable,3843 wasi.ESPIPE => return error.Unseekable,
3792 wasi.ENXIO => return error.Unseekable,3844 wasi.ENXIO => return error.Unseekable,
3845 wasi.ENOTCAPABLE => return error.AccessDenied,
3793 else => |err| return unexpectedErrno(err),3846 else => |err| return unexpectedErrno(err),
3794 }3847 }
3795 }3848 }
lib/std/zig/system.zig+1
...@@ -859,6 +859,7 @@ pub const NativeTargetInfo = struct {...@@ -859,6 +859,7 @@ pub const NativeTargetInfo = struct {
859 error.ConnectionTimedOut => return error.UnableToReadElfFile,859 error.ConnectionTimedOut => return error.UnableToReadElfFile,
860 error.Unexpected => return error.Unexpected,860 error.Unexpected => return error.Unexpected,
861 error.InputOutput => return error.FileSystem,861 error.InputOutput => return error.FileSystem,
862 error.AccessDenied => return error.Unexpected,
862 };863 };
863 if (len == 0) return error.UnexpectedEndOfFile;864 if (len == 0) return error.UnexpectedEndOfFile;
864 i += len;865 i += len;