Commit 07a968b344

Jakub Konka <kubkon@jakubkonka.com>
2020-05-05 17:05:30
Add docs
1 parent 558bb24
Changed files (2)
lib
lib/std/fs/wasi.zig
@@ -5,18 +5,30 @@ const Allocator = mem.Allocator;
 
 usingnamespace std.os.wasi;
 
+/// Type of WASI preopen.
+///
+/// WASI currently offers only `Dir` as a valid preopen resource.
 pub const PreopenType = enum {
     Dir,
 };
 
+/// WASI preopen struct. This struct consists of a WASI file descriptor
+/// and type of WASI preopen. It can be obtained directly from the WASI
+/// runtime using `PreopenList.populate()` method.
 pub const Preopen = struct {
+    /// WASI file descriptor.
     fd: fd_t,
+
+    /// Type of the preopen.
     @"type": union(PreopenType) {
+        /// Path to a preopened directory.
         Dir: []const u8,
     },
 
     const Self = @This();
 
+    /// Construct new `Preopen` instance of type `PreopenType.Dir` from
+    /// WASI file descriptor and WASI path.
     pub fn newDir(fd: fd_t, path: []const u8) Self {
         return Self{
             .fd = fd,
@@ -25,18 +37,29 @@ pub const Preopen = struct {
     }
 };
 
+/// Dynamically-sized array list of WASI preopens. This struct is a
+/// convenience wrapper for issuing `std.os.wasi.fd_prestat_get` and
+/// `std.os.wasi.fd_prestat_dir_name` syscalls to the WASI runtime, and
+/// collecting the returned preopens.
+///
+/// This struct is intended to be used in any WASI program which intends
+/// to use the capabilities as passed on by the user of the runtime.
 pub const PreopenList = struct {
     const InnerList = std.ArrayList(Preopen);
 
+    /// Internal dynamically-sized buffer for storing the gathered preopens.
     buffer: InnerList,
 
     const Self = @This();
+
     pub const Error = os.UnexpectedError || Allocator.Error;
 
+    /// Deinitialize with `deinit`.
     pub fn init(allocator: *Allocator) Self {
         return Self{ .buffer = InnerList.init(allocator) };
     }
 
+    /// Release all allocated memory.
     pub fn deinit(pm: Self) void {
         for (pm.buffer.items) |preopen| {
             switch (preopen.@"type") {
@@ -46,6 +69,8 @@ pub const PreopenList = struct {
         pm.buffer.deinit();
     }
 
+    /// Populate the list with the preopens by issuing `std.os.wasi.fd_prestat_get`
+    /// and `std.os.wasi.fd_prestat_dir_name` syscalls to the runtime.
     pub fn populate(self: *Self) Error!void {
         errdefer self.deinit();
         var fd: fd_t = 3; // start fd has to be beyond stdio fds
@@ -77,6 +102,12 @@ pub const PreopenList = struct {
         }
     }
 
+    /// Find preopen by path. If the preopen exists, return it.
+    /// Otherwise, return `null`.
+    ///
+    /// TODO make the function more generic by searching by `PreopenType` union. This will
+    /// be needed in the future when WASI extends its capabilities to resources
+    /// other than preopened directories.
     pub fn find(self: *const Self, path: []const u8) ?*const Preopen {
         for (self.buffer.items) |preopen| {
             switch (preopen.@"type") {
@@ -88,12 +119,14 @@ pub const PreopenList = struct {
         return null;
     }
 
+    /// Return the inner buffer as read-only slice.
     pub fn asSlice(self: *const Self) []const Preopen {
         return self.buffer.items;
     }
 };
 
-pub fn openat(dir_fd: fd_t, file_path: []const u8, oflags: oflags_t, fdflags: fdflags_t, rights: rights_t) std.os.OpenError!fd_t {
+/// Convenience wrapper for `std.os.wasi.path_open` syscall.
+pub fn openat(dir_fd: fd_t, file_path: []const u8, oflags: oflags_t, fdflags: fdflags_t, rights: rights_t) os.OpenError!fd_t {
     var fd: fd_t = undefined;
     switch (path_open(dir_fd, 0x0, file_path.ptr, file_path.len, oflags, rights, 0x0, fdflags, &fd)) {
         0 => {},
lib/std/fs.zig
@@ -592,19 +592,27 @@ pub const Dir = struct {
         return self.openFileZ(&path_c, flags);
     }
 
-    fn openFileWasi(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
-        var fdflags: wasi.fdflag_t = 0x0;
-        var rights: wasi.rights_t = 0x0;
+    /// Save as `openFile` but WASI only.
+    pub fn openFileWasi(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
+        const w = os.wasi;
+        var fdflags: w.fdflag_t = 0x0;
+        var rights: w.rights_t = 0x0;
         if (flags.read) {
-            rights |= wasi.FD_READ | wasi.FD_TELL | wasi.FD_FILESTAT_GET;
+            rights |= w.FD_READ | w.FD_TELL | w.FD_FILESTAT_GET;
         }
         if (flags.write) {
-            fdflags |= wasi.FDFLAG_APPEND;
-            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;
+            fdflags |= w.FDFLAG_APPEND;
+            rights |= w.FD_WRITE |
+                w.FD_DATASYNC |
+                w.FD_SEEK |
+                w.FD_FDSTAT_SET_FLAGS |
+                w.FD_SYNC |
+                w.FD_ALLOCATE |
+                w.FD_ADVISE |
+                w.FD_FILESTAT_SET_TIMES |
+                w.FD_FILESTAT_SET_SIZE;
         }
-
         const fd = try wasi.openat(self.fd, sub_path, 0x0, fdflags, rights);
-
         return File{ .handle = fd };
     }
 
@@ -700,17 +708,27 @@ pub const Dir = struct {
 
     pub const createFileC = @compileError("deprecated: renamed to createFileZ");
 
-    fn createFileWasi(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
-        var oflags: wasi.oflags_t = wasi.O_CREAT;
-        var rights: wasi.rights_t = wasi.RIGHT_FD_WRITE | wasi.RIGHT_FD_DATASYNC | wasi.RIGHT_FD_SEEK | wasi.RIGHT_FD_FDSTAT_SET_FLAGS | wasi.RIGHT_FD_SYNC | wasi.RIGHT_FD_ALLOCATE | wasi.RIGHT_FD_ADVISE | wasi.RIGHT_FD_FILESTAT_SET_TIMES | wasi.RIGHT_FD_FILESTAT_SET_SIZE;
+    /// Same as `createFile` but WASI only.
+    pub fn createFileWasi(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
+        const w = os.wasi;
+        var oflags = w.O_CREAT;
+        var rights = w.RIGHT_FD_WRITE |
+            w.RIGHT_FD_DATASYNC |
+            w.RIGHT_FD_SEEK |
+            w.RIGHT_FD_FDSTAT_SET_FLAGS |
+            w.RIGHT_FD_SYNC |
+            w.RIGHT_FD_ALLOCATE |
+            w.RIGHT_FD_ADVISE |
+            w.RIGHT_FD_FILESTAT_SET_TIMES |
+            w.RIGHT_FD_FILESTAT_SET_SIZE;
         if (flags.read) {
-            rights |= wasi.RIGHT_FD_READ | wasi.RIGHT_FD_TELL | wasi.RIGHT_FD_FILESTAT_GET;
+            rights |= w.RIGHT_FD_READ | w.RIGHT_FD_TELL | w.RIGHT_FD_FILESTAT_GET;
         }
         if (flags.truncate) {
-            oflags |= wasi.O_TRUNC;
+            oflags |= w.O_TRUNC;
         }
         if (flags.exclusive) {
-            oflags |= wasi.O_EXCL;
+            oflags |= w.O_EXCL;
         }
         const fd = try wasi.openat(self.fd, sub_path, oflags, 0x0, rights);
         return File{ .handle = fd };