| author | |
| committer | |
| log | 8e1cd69717e8d87f53e930bd87edb7ca701b3f0c |
| tree | 06ca1215459b2a72d98a54f61b5a5884c992f464 |
| parent | d7ca220121ade4031f09e6a7279fd08b617ee2c0 |
It seems that `std.os.openZ` is too POSIX-specific, so I think it
should not be a point of entry for WASI `open` call. I figure
WASI should be treated as a separate "os" that's _not_ POSIX
especially given the incoming changes in the ephemeral snapshot.2 files changed, 79 insertions(+), 25 deletions(-)
lib/std/fs.zig+49-1| ... | ... | @@ -37,7 +37,7 @@ pub const Watch = @import("fs/watch.zig").Watch; |
| 37 | 37 | /// fit into a UTF-8 encoded array of this length. |
| 38 | 38 | /// The byte count includes room for a null sentinel byte. |
| 39 | 39 | pub const MAX_PATH_BYTES = switch (builtin.os.tag) { |
| 40 | .linux, .macosx, .ios, .freebsd, .netbsd, .dragonfly => os.PATH_MAX, | |
| 40 | .linux, .macosx, .ios, .freebsd, .netbsd, .dragonfly, .wasi => os.PATH_MAX, | |
| 41 | 41 | // Each UTF-16LE character may be expanded to 3 UTF-8 bytes. |
| 42 | 42 | // If it would require 4 UTF-8 bytes, then there would be a surrogate |
| 43 | 43 | // pair in the UTF-16LE, and we (over)account 3 bytes for it that way. |
| ... | ... | @@ -584,10 +584,33 @@ pub const Dir = struct { |
| 584 | 584 | const path_w = try os.windows.sliceToPrefixedFileW(sub_path); |
| 585 | 585 | return self.openFileW(path_w.span(), flags); |
| 586 | 586 | } |
| 587 | if (builtin.os.tag == .wasi) { | |
| 588 | return self.openFileWasi(sub_path, flags); | |
| 589 | } | |
| 587 | 590 | const path_c = try os.toPosixPath(sub_path); |
| 588 | 591 | return self.openFileZ(&path_c, flags); |
| 589 | 592 | } |
| 590 | 593 | |
| 594 | pub fn openFileWasi(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File { | |
| 595 | var fdflags: wasi.fdflag_t = 0x0; | |
| 596 | var rights: wasi.rights_t = 0x0; | |
| 597 | if (flags.read) { | |
| 598 | rights |= wasi.FD_READ | wasi.FD_TELL | wasi.FD_FILESTAT_GET; | |
| 599 | } | |
| 600 | if (flags.write) { | |
| 601 | fdflags |= wasi.FDFLAG_APPEND; | |
| 602 | rights |= wasi.FD_WRITE | wasi.FD_DATASYNC | wasi.FD_SEEK | wasi.FD_FDSTAT_SET_FLAGS | wasi.FD_SYNC | wasi.FD_ALLOCATE | wasi.FD_ADVISE | wasi.FD_FILESTAT_SET_TIMES | wasi.FD_FILESTAT_SET_SIZE; | |
| 603 | } | |
| 604 | ||
| 605 | const fd = try os.openatWasi(self.fd, sub_path, 0x0, fdflags, rights); | |
| 606 | ||
| 607 | return File{ | |
| 608 | .handle = fd, | |
| 609 | .io_mode = .blocking, | |
| 610 | .async_block_allowed = File.async_block_allowed_no, | |
| 611 | }; | |
| 612 | } | |
| 613 | ||
| 591 | 614 | pub const openFileC = @compileError("deprecated: renamed to openFileZ"); |
| 592 | 615 | |
| 593 | 616 | /// Same as `openFile` but the path parameter is null-terminated. |
| ... | ... | @@ -671,12 +694,37 @@ pub const Dir = struct { |
| 671 | 694 | const path_w = try os.windows.sliceToPrefixedFileW(sub_path); |
| 672 | 695 | return self.createFileW(path_w.span(), flags); |
| 673 | 696 | } |
| 697 | if (builtin.os.tag == .wasi) { | |
| 698 | return self.createFileWasi(sub_path, flags); | |
| 699 | } | |
| 674 | 700 | const path_c = try os.toPosixPath(sub_path); |
| 675 | 701 | return self.createFileZ(&path_c, flags); |
| 676 | 702 | } |
| 677 | 703 | |
| 678 | 704 | pub const createFileC = @compileError("deprecated: renamed to createFileZ"); |
| 679 | 705 | |
| 706 | pub fn createFileWasi(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { | |
| 707 | var oflags: wasi.oflags_t = 0x0; | |
| 708 | var rights: wasi.rights_t = wasi.FD_WRITE | wasi.FD_DATASYNC | wasi.FD_SEEK | wasi.FD_FDSTAT_SET_FLAGS | wasi.FD_SYNC | wasi.FD_ALLOCATE | wasi.FD_ADVISE | wasi.FD_FILESTAT_SET_TIMES | wasi.FD_FILESTAT_SET_SIZE; | |
| 709 | if (flags.read) { | |
| 710 | rights |= wasi.FD_READ | wasi.FD_TELL | wasi.FD_FILESTAT_GET; | |
| 711 | } | |
| 712 | if (flags.truncate) { | |
| 713 | oflags |= wasi.O_TRUNC; | |
| 714 | } | |
| 715 | if (flags.exclusive) { | |
| 716 | oflags |= wasi.O_EXCL; | |
| 717 | } | |
| 718 | ||
| 719 | const fd = try os.openatWasi(self.fd, sub_path, oflags, 0x0, rights); | |
| 720 | ||
| 721 | return File{ | |
| 722 | .handle = fd, | |
| 723 | .io_mode = .blocking, | |
| 724 | .async_block_allowed = File.async_block_allowed_no, | |
| 725 | }; | |
| 726 | } | |
| 727 | ||
| 680 | 728 | /// Same as `createFile` but the path parameter is null-terminated. |
| 681 | 729 | pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File { |
| 682 | 730 | if (builtin.os.tag == .windows) { |
lib/std/os.zig+30-24| ... | ... | @@ -869,6 +869,26 @@ pub fn open(file_path: []const u8, flags: u32, perm: mode_t) OpenError!fd_t { |
| 869 | 869 | return openZ(&file_path_c, flags, perm); |
| 870 | 870 | } |
| 871 | 871 | |
| 872 | pub fn openWasi(file_path: []const u8, oflags: wasi.oflags_t, fdflags: wasi.fdflags_t, rights: wasi.rights_t) OpenError!fd_t { | |
| 873 | var dirfd: fd_t = undefined; | |
| 874 | var prefix: usize = undefined; | |
| 875 | ||
| 876 | switch (wasi.resolve_preopen(file_path, &dirfd, &prefix)) { | |
| 877 | 0 => {}, | |
| 878 | else => |err| return unexpectedErrno(err), | |
| 879 | } | |
| 880 | ||
| 881 | const rel_path = file_path[prefix + 1 ..]; | |
| 882 | var fd: fd_t = undefined; | |
| 883 | switch (wasi.path_open(dirfd, 0x0, rel_path.ptr, rel_path.len, oflags, rights, 0x0, fdflags, &fd)) { | |
| 884 | 0 => {}, | |
| 885 | // TODO map errors | |
| 886 | else => |err| return unexpectedErrno(err), | |
| 887 | } | |
| 888 | ||
| 889 | return fd; | |
| 890 | } | |
| 891 | ||
| 872 | 892 | pub const openC = @compileError("deprecated: renamed to openZ"); |
| 873 | 893 | |
| 874 | 894 | /// Open and possibly create a file. Keeps trying if it gets interrupted. |
| ... | ... | @@ -879,30 +899,6 @@ pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: mode_t) OpenError!fd_t |
| 879 | 899 | return openW(file_path_w.span(), flags, perm); |
| 880 | 900 | } |
| 881 | 901 | while (true) { |
| 882 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | |
| 883 | var dirfd: fd_t = undefined; | |
| 884 | var prefix: usize = undefined; | |
| 885 | const path = mem.span(file_path); | |
| 886 | ||
| 887 | switch (wasi.resolve_preopen(path, &dirfd, &prefix)) { | |
| 888 | 0 => {}, | |
| 889 | else => |err| return unexpectedErrno(err), | |
| 890 | } | |
| 891 | ||
| 892 | const rel_path = path[prefix + 1 ..]; | |
| 893 | // TODO map flags to wasi.oflag_t | |
| 894 | // TODO call wasi.fd_fdstat_get to verify rights | |
| 895 | // TODO adjust all flags to path_open | |
| 896 | var fd: fd_t = undefined; | |
| 897 | ||
| 898 | switch (wasi.path_open(dirfd, 0x0, rel_path.ptr, rel_path.len, wasi.O_CREAT, 0x0, 0x0, 0x0, &fd)) { | |
| 899 | 0 => {}, | |
| 900 | else => |err| return unexpectedErrno(err), | |
| 901 | } | |
| 902 | ||
| 903 | return fd; | |
| 904 | } | |
| 905 | ||
| 906 | 902 | const rc = system.open(file_path, flags, perm); |
| 907 | 903 | switch (errno(rc)) { |
| 908 | 904 | 0 => return @intCast(fd_t, rc), |
| ... | ... | @@ -947,6 +943,16 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) Ope |
| 947 | 943 | return openatZ(dir_fd, &file_path_c, flags, mode); |
| 948 | 944 | } |
| 949 | 945 | |
| 946 | pub fn openatWasi(dir_fd: fd_t, file_path: []const u8, oflags: wasi.oflag_t, fdflags: wasi.fdflag_t, rights: wasi.rights_t) OpenError!fd_t { | |
| 947 | switch (wasi.path_open(dirfd, 0x0, &file_path, file_path.len, oflags, rights, 0x0, fdflags, &fd)) { | |
| 948 | 0 => {}, | |
| 949 | // TODO map errors | |
| 950 | else => |err| return unexpectedErrno(err), | |
| 951 | } | |
| 952 | ||
| 953 | return fd; | |
| 954 | } | |
| 955 | ||
| 950 | 956 | pub const openatC = @compileError("deprecated: renamed to openatZ"); |
| 951 | 957 | |
| 952 | 958 | /// Open and possibly create a file. Keeps trying if it gets interrupted. |