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 {
551551 error.InputOutput => return error.FileSystem,
552552 error.Unexpected => return error.Unexpected,
553553 error.WouldBlock => return error.Unexpected,
554 error.AccessDenied => return error.Unexpected,
554555 };
555556 if (len == 0) return error.UnexpectedEndOfFile;
556557 i += len;
lib/std/fs.zig+9-8
......@@ -535,14 +535,15 @@ pub const Dir = struct {
535535 w.EFAULT => unreachable,
536536 w.ENOTDIR => unreachable,
537537 w.EINVAL => unreachable,
538 w.ENOTCAPABLE => return error.AccessDenied,
538539 else => |err| return os.unexpectedErrno(err),
539540 }
540541 if (bufused == 0) return null;
541542 self.index = 0;
542543 self.end_index = bufused;
543544 }
544 const entry = @ptrCast(*align(1) os.wasi.dirent_t, &self.buf[self.index]);
545 const entry_size = @sizeOf(os.wasi.dirent_t);
545 const entry = @ptrCast(*align(1) w.dirent_t, &self.buf[self.index]);
546 const entry_size = @sizeOf(w.dirent_t);
546547 const name_index = self.index + entry_size;
547548 const name = mem.span(self.buf[name_index .. name_index + entry.d_namlen]);
548549
......@@ -556,12 +557,12 @@ pub const Dir = struct {
556557 }
557558
558559 const entry_kind = switch (entry.d_type) {
559 wasi.FILETYPE_BLOCK_DEVICE => Entry.Kind.BlockDevice,
560 wasi.FILETYPE_CHARACTER_DEVICE => Entry.Kind.CharacterDevice,
561 wasi.FILETYPE_DIRECTORY => Entry.Kind.Directory,
562 wasi.FILETYPE_SYMBOLIC_LINK => Entry.Kind.SymLink,
563 wasi.FILETYPE_REGULAR_FILE => Entry.Kind.File,
564 wasi.FILETYPE_SOCKET_STREAM, wasi.FILETYPE_SOCKET_DGRAM => Entry.Kind.UnixDomainSocket,
560 w.FILETYPE_BLOCK_DEVICE => Entry.Kind.BlockDevice,
561 w.FILETYPE_CHARACTER_DEVICE => Entry.Kind.CharacterDevice,
562 w.FILETYPE_DIRECTORY => Entry.Kind.Directory,
563 w.FILETYPE_SYMBOLIC_LINK => Entry.Kind.SymLink,
564 w.FILETYPE_REGULAR_FILE => Entry.Kind.File,
565 w.FILETYPE_SOCKET_STREAM, wasi.FILETYPE_SOCKET_DGRAM => Entry.Kind.UnixDomainSocket,
565566 else => Entry.Kind.Unknown,
566567 };
567568 return Entry{
lib/std/os.zig+76-23
......@@ -300,6 +300,10 @@ pub const ReadError = error{
300300 /// This error occurs when no global event loop is configured,
301301 /// and reading from the file descriptor would block.
302302 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,
303307} || UnexpectedError;
304308
305309/// 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 {
335339 wasi.ENOMEM => return error.SystemResources,
336340 wasi.ECONNRESET => return error.ConnectionResetByPeer,
337341 wasi.ETIMEDOUT => return error.ConnectionTimedOut,
342 wasi.ENOTCAPABLE => return error.AccessDenied,
338343 else => |err| return unexpectedErrno(err),
339344 }
340345 }
......@@ -402,6 +407,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize {
402407 wasi.EISDIR => return error.IsDir,
403408 wasi.ENOBUFS => return error.SystemResources,
404409 wasi.ENOMEM => return error.SystemResources,
410 wasi.ENOTCAPABLE => return error.AccessDenied,
405411 else => |err| return unexpectedErrno(err),
406412 }
407413 }
......@@ -466,6 +472,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
466472 wasi.ENXIO => return error.Unseekable,
467473 wasi.ESPIPE => return error.Unseekable,
468474 wasi.EOVERFLOW => return error.Unseekable,
475 wasi.ENOTCAPABLE => return error.AccessDenied,
469476 else => |err| return unexpectedErrno(err),
470477 }
471478 }
......@@ -500,8 +507,11 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
500507pub const TruncateError = error{
501508 FileTooBig,
502509 InputOutput,
503 CannotTruncate,
504510 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,
505515} || UnexpectedError;
506516
507517pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
......@@ -522,7 +532,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
522532 switch (rc) {
523533 .SUCCESS => return,
524534 .INVALID_HANDLE => unreachable, // Handle not open for writing
525 .ACCESS_DENIED => return error.CannotTruncate,
535 .ACCESS_DENIED => return error.AccessDenied,
526536 else => return windows.unexpectedStatus(rc),
527537 }
528538 }
......@@ -532,10 +542,11 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
532542 wasi.EINTR => unreachable,
533543 wasi.EFBIG => return error.FileTooBig,
534544 wasi.EIO => return error.InputOutput,
535 wasi.EPERM => return error.CannotTruncate,
545 wasi.EPERM => return error.AccessDenied,
536546 wasi.ETXTBSY => return error.FileBusy,
537547 wasi.EBADF => unreachable, // Handle not open for writing
538548 wasi.EINVAL => unreachable, // Handle not open for writing
549 wasi.ENOTCAPABLE => return error.AccessDenied,
539550 else => |err| return unexpectedErrno(err),
540551 }
541552 }
......@@ -554,7 +565,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
554565 EINTR => continue,
555566 EFBIG => return error.FileTooBig,
556567 EIO => return error.InputOutput,
557 EPERM => return error.CannotTruncate,
568 EPERM => return error.AccessDenied,
558569 ETXTBSY => return error.FileBusy,
559570 EBADF => unreachable, // Handle not open for writing
560571 EINVAL => unreachable, // Handle not open for writing
......@@ -604,6 +615,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize {
604615 wasi.ENXIO => return error.Unseekable,
605616 wasi.ESPIPE => return error.Unseekable,
606617 wasi.EOVERFLOW => return error.Unseekable,
618 wasi.ENOTCAPABLE => return error.AccessDenied,
607619 else => |err| return unexpectedErrno(err),
608620 }
609621 }
......@@ -641,6 +653,9 @@ pub const WriteError = error{
641653 FileTooBig,
642654 InputOutput,
643655 NoSpaceLeft,
656
657 /// In WASI, this error may occur when the file descriptor does
658 /// not hold the required rights to write to it.
644659 AccessDenied,
645660 BrokenPipe,
646661 SystemResources,
......@@ -697,6 +712,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
697712 wasi.ENOSPC => return error.NoSpaceLeft,
698713 wasi.EPERM => return error.AccessDenied,
699714 wasi.EPIPE => return error.BrokenPipe,
715 wasi.ENOTCAPABLE => return error.AccessDenied,
700716 else => |err| return unexpectedErrno(err),
701717 }
702718 }
......@@ -774,6 +790,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize {
774790 wasi.ENOSPC => return error.NoSpaceLeft,
775791 wasi.EPERM => return error.AccessDenied,
776792 wasi.EPIPE => return error.BrokenPipe,
793 wasi.ENOTCAPABLE => return error.AccessDenied,
777794 else => |err| return unexpectedErrno(err),
778795 }
779796 }
......@@ -856,6 +873,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
856873 wasi.ENXIO => return error.Unseekable,
857874 wasi.ESPIPE => return error.Unseekable,
858875 wasi.EOVERFLOW => return error.Unseekable,
876 wasi.ENOTCAPABLE => return error.AccessDenied,
859877 else => |err| return unexpectedErrno(err),
860878 }
861879 }
......@@ -949,6 +967,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz
949967 wasi.ENXIO => return error.Unseekable,
950968 wasi.ESPIPE => return error.Unseekable,
951969 wasi.EOVERFLOW => return error.Unseekable,
970 wasi.ENOTCAPABLE => return error.AccessDenied,
952971 else => |err| return unexpectedErrno(err),
953972 }
954973 }
......@@ -984,6 +1003,8 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz
9841003}
9851004
9861005pub 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.
9871008 AccessDenied,
9881009 SymLinkLoop,
9891010 ProcessFdQuotaExceeded,
......@@ -1113,6 +1134,7 @@ pub fn openatWasi(dir_fd: fd_t, file_path: []const u8, oflags: oflags_t, fdflags
11131134 wasi.EPERM => return error.AccessDenied,
11141135 wasi.EEXIST => return error.PathAlreadyExists,
11151136 wasi.EBUSY => return error.DeviceBusy,
1137 wasi.ENOTCAPABLE => return error.AccessDenied,
11161138 else => |err| return unexpectedErrno(err),
11171139 }
11181140 }
......@@ -1499,6 +1521,8 @@ pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {
14991521}
15001522
15011523pub 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.
15021526 AccessDenied,
15031527 DiskQuota,
15041528 PathAlreadyExists,
......@@ -1604,13 +1628,14 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c
16041628 wasi.ENOMEM => return error.SystemResources,
16051629 wasi.ENOSPC => return error.NoSpaceLeft,
16061630 wasi.EROFS => return error.ReadOnlyFileSystem,
1631 wasi.ENOTCAPABLE => return error.AccessDenied,
16071632 else => |err| return unexpectedErrno(err),
16081633 }
16091634}
16101635
16111636/// Windows-only. The same as `symlinkat` except the paths are null-terminated, WTF-16 encoded.
16121637/// 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 {
16141639 @compileError("TODO implement on Windows");
16151640}
16161641
......@@ -1644,6 +1669,9 @@ pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*:
16441669
16451670pub const UnlinkError = error{
16461671 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.
16471675 AccessDenied,
16481676 FileBusy,
16491677 FileSystem,
......@@ -1747,6 +1775,7 @@ pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatErro
17471775 wasi.ENOMEM => return error.SystemResources,
17481776 wasi.EROFS => return error.ReadOnlyFileSystem,
17491777 wasi.ENOTEMPTY => return error.DirNotEmpty,
1778 wasi.ENOTCAPABLE => return error.AccessDenied,
17501779
17511780 wasi.EINVAL => unreachable, // invalid flags, or pathname has . as last component
17521781 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
18491878}
18501879
18511880const 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.
18521883 AccessDenied,
18531884 FileBusy,
18541885 DiskQuota,
......@@ -1968,6 +1999,7 @@ pub fn renameatWasi(old_dir_fd: fd_t, old_path: []const u8, new_dir_fd: fd_t, ne
19681999 wasi.ENOTEMPTY => return error.PathAlreadyExists,
19692000 wasi.EROFS => return error.ReadOnlyFileSystem,
19702001 wasi.EXDEV => return error.RenameAcrossMountPoints,
2002 wasi.ENOTCAPABLE => return error.AccessDenied,
19712003 else => |err| return unexpectedErrno(err),
19722004 }
19732005}
......@@ -2066,23 +2098,6 @@ pub fn renameatW(
20662098 }
20672099}
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
20862101pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!void {
20872102 if (builtin.os.tag == .windows) {
20882103 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
21142129 wasi.ENOSPC => return error.NoSpaceLeft,
21152130 wasi.ENOTDIR => return error.NotDir,
21162131 wasi.EROFS => return error.ReadOnlyFileSystem,
2132 wasi.ENOTCAPABLE => return error.AccessDenied,
21172133 else => |err| return unexpectedErrno(err),
21182134 }
21192135}
......@@ -2148,6 +2164,25 @@ pub fn mkdiratW(dir_fd: fd_t, sub_path_w: [*:0]const u16, mode: u32) MakeDirErro
21482164 windows.CloseHandle(sub_dir_handle);
21492165}
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
21512186/// Create a directory.
21522187/// `mode` is ignored on Windows.
21532188pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
......@@ -2311,6 +2346,8 @@ pub fn fchdir(dirfd: fd_t) FchdirError!void {
23112346}
23122347
23132348pub 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.
23142351 AccessDenied,
23152352 FileSystem,
23162353 SymLinkLoop,
......@@ -2396,6 +2433,7 @@ pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) Read
23962433 wasi.ENOENT => return error.FileNotFound,
23972434 wasi.ENOMEM => return error.SystemResources,
23982435 wasi.ENOTDIR => return error.NotDir,
2436 wasi.ENOTCAPABLE => return error.AccessDenied,
23992437 else => |err| return unexpectedErrno(err),
24002438 }
24012439}
......@@ -3073,6 +3111,9 @@ pub fn waitpid(pid: i32, flags: u32) u32 {
30733111
30743112pub const FStatError = error{
30753113 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.
30763117 AccessDenied,
30773118} || UnexpectedError;
30783119
......@@ -3086,6 +3127,7 @@ pub fn fstat(fd: fd_t) FStatError!Stat {
30863127 wasi.EBADF => unreachable, // Always a race condition.
30873128 wasi.ENOMEM => return error.SystemResources,
30883129 wasi.EACCES => return error.AccessDenied,
3130 wasi.ENOTCAPABLE => return error.AccessDenied,
30893131 else => |err| return unexpectedErrno(err),
30903132 }
30913133 }
......@@ -3136,6 +3178,7 @@ pub fn fstatatWasi(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!S
31363178 wasi.ENAMETOOLONG => return error.NameTooLong,
31373179 wasi.ENOENT => return error.FileNotFound,
31383180 wasi.ENOTDIR => return error.FileNotFound,
3181 wasi.ENOTCAPABLE => return error.AccessDenied,
31393182 else => |err| return unexpectedErrno(err),
31403183 }
31413184}
......@@ -3641,7 +3684,13 @@ pub fn gettimeofday(tv: ?*timeval, tz: ?*timezone) void {
36413684 }
36423685}
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
36463695/// Repositions read/write file offset relative to the beginning.
36473696pub 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 {
36693718 wasi.EOVERFLOW => return error.Unseekable,
36703719 wasi.ESPIPE => return error.Unseekable,
36713720 wasi.ENXIO => return error.Unseekable,
3721 wasi.ENOTCAPABLE => return error.AccessDenied,
36723722 else => |err| return unexpectedErrno(err),
36733723 }
36743724 }
......@@ -3710,6 +3760,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {
37103760 wasi.EOVERFLOW => return error.Unseekable,
37113761 wasi.ESPIPE => return error.Unseekable,
37123762 wasi.ENXIO => return error.Unseekable,
3763 wasi.ENOTCAPABLE => return error.AccessDenied,
37133764 else => |err| return unexpectedErrno(err),
37143765 }
37153766 }
......@@ -3750,6 +3801,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {
37503801 wasi.EOVERFLOW => return error.Unseekable,
37513802 wasi.ESPIPE => return error.Unseekable,
37523803 wasi.ENXIO => return error.Unseekable,
3804 wasi.ENOTCAPABLE => return error.AccessDenied,
37533805 else => |err| return unexpectedErrno(err),
37543806 }
37553807 }
......@@ -3790,6 +3842,7 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {
37903842 wasi.EOVERFLOW => return error.Unseekable,
37913843 wasi.ESPIPE => return error.Unseekable,
37923844 wasi.ENXIO => return error.Unseekable,
3845 wasi.ENOTCAPABLE => return error.AccessDenied,
37933846 else => |err| return unexpectedErrno(err),
37943847 }
37953848 }
lib/std/zig/system.zig+1
......@@ -859,6 +859,7 @@ pub const NativeTargetInfo = struct {
859859 error.ConnectionTimedOut => return error.UnableToReadElfFile,
860860 error.Unexpected => return error.Unexpected,
861861 error.InputOutput => return error.FileSystem,
862 error.AccessDenied => return error.Unexpected,
862863 };
863864 if (len == 0) return error.UnexpectedEndOfFile;
864865 i += len;