authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-05-01 12:33:11+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-05-05 15:08:52+02:00
log8e1cd69717e8d87f53e930bd87edb7ca701b3f0c
tree06ca1215459b2a72d98a54f61b5a5884c992f464
parentd7ca220121ade4031f09e6a7279fd08b617ee2c0

Implement std.fs.Dir.openFileWasi

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,7 +37,7 @@ pub const Watch = @import("fs/watch.zig").Watch;
37/// fit into a UTF-8 encoded array of this length.37/// fit into a UTF-8 encoded array of this length.
38/// The byte count includes room for a null sentinel byte.38/// The byte count includes room for a null sentinel byte.
39pub const MAX_PATH_BYTES = switch (builtin.os.tag) {39pub 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 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.41 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
42 // If it would require 4 UTF-8 bytes, then there would be a surrogate42 // If it would require 4 UTF-8 bytes, then there would be a surrogate
43 // pair in the UTF-16LE, and we (over)account 3 bytes for it that way.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,10 +584,33 @@ pub const Dir = struct {
584 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);584 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
585 return self.openFileW(path_w.span(), flags);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 const path_c = try os.toPosixPath(sub_path);590 const path_c = try os.toPosixPath(sub_path);
588 return self.openFileZ(&path_c, flags);591 return self.openFileZ(&path_c, flags);
589 }592 }
590593
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 pub const openFileC = @compileError("deprecated: renamed to openFileZ");614 pub const openFileC = @compileError("deprecated: renamed to openFileZ");
592615
593 /// Same as `openFile` but the path parameter is null-terminated.616 /// Same as `openFile` but the path parameter is null-terminated.
...@@ -671,12 +694,37 @@ pub const Dir = struct {...@@ -671,12 +694,37 @@ pub const Dir = struct {
671 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);694 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
672 return self.createFileW(path_w.span(), flags);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 const path_c = try os.toPosixPath(sub_path);700 const path_c = try os.toPosixPath(sub_path);
675 return self.createFileZ(&path_c, flags);701 return self.createFileZ(&path_c, flags);
676 }702 }
677703
678 pub const createFileC = @compileError("deprecated: renamed to createFileZ");704 pub const createFileC = @compileError("deprecated: renamed to createFileZ");
679705
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 /// Same as `createFile` but the path parameter is null-terminated.728 /// Same as `createFile` but the path parameter is null-terminated.
681 pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File {729 pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File {
682 if (builtin.os.tag == .windows) {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,6 +869,26 @@ pub fn open(file_path: []const u8, flags: u32, perm: mode_t) OpenError!fd_t {
869 return openZ(&file_path_c, flags, perm);869 return openZ(&file_path_c, flags, perm);
870}870}
871871
872pub 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
872pub const openC = @compileError("deprecated: renamed to openZ");892pub const openC = @compileError("deprecated: renamed to openZ");
873893
874/// Open and possibly create a file. Keeps trying if it gets interrupted.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,30 +899,6 @@ pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: mode_t) OpenError!fd_t
879 return openW(file_path_w.span(), flags, perm);899 return openW(file_path_w.span(), flags, perm);
880 }900 }
881 while (true) {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 const rc = system.open(file_path, flags, perm);902 const rc = system.open(file_path, flags, perm);
907 switch (errno(rc)) {903 switch (errno(rc)) {
908 0 => return @intCast(fd_t, rc),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,6 +943,16 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) Ope
947 return openatZ(dir_fd, &file_path_c, flags, mode);943 return openatZ(dir_fd, &file_path_c, flags, mode);
948}944}
949945
946pub 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
950pub const openatC = @compileError("deprecated: renamed to openatZ");956pub const openatC = @compileError("deprecated: renamed to openatZ");
951957
952/// Open and possibly create a file. Keeps trying if it gets interrupted.958/// Open and possibly create a file. Keeps trying if it gets interrupted.