Skip to content

Instantly share code, notes, and snippets.

@skeeto
Created April 5, 2025 14:57
Show Gist options
  • Save skeeto/7103f03abf663b88ca6dfc431b696f62 to your computer and use it in GitHub Desktop.
Save skeeto/7103f03abf663b88ca6dfc431b696f62 to your computer and use it in GitHub Desktop.
Question via Illume
!profile claude
!user
Please give me an example of using WASI `path_open` to open a file for writing. In particular, I don't know where to get the `dirfd` parameter.
!assistant
# Example of using WASI `path_open` to open a file for writing
The WASI `path_open` function requires a directory file descriptor (`dirfd`) as its first parameter because WASI uses a capability-based security model. Here's how to use it:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <wasi/api.h>
int main() {
// Get the pre-opened directory that was passed to the WASI module
// Typically fd=3 is the preopened directory for the current working directory
__wasi_fd_t dirfd = 3; // Typical value for the preopened directory
const char* path = "example.txt";
__wasi_fd_t fd;
// Open flags for creating a file for writing
__wasi_oflags_t oflags = __WASI_OFLAGS_CREAT;
__wasi_rights_t fs_rights_base = __WASI_RIGHTS_FD_WRITE | __WASI_RIGHTS_FD_SYNC | __WASI_RIGHTS_PATH_FILESTAT_GET;
__wasi_rights_t fs_rights_inheriting = 0;
__wasi_fdflags_t fs_flags = 0;
// Call path_open to open the file
__wasi_errno_t error = __wasi_path_open(
dirfd, // Directory FD
0, // dirflags (0 for no special handling)
path, // Path to the file
strlen(path), // Path length
oflags, // Open flags
fs_rights_base, // Rights for the file descriptor
fs_rights_inheriting, // Rights for inherited file descriptors
fs_flags, // File descriptor flags
&fd // Output file descriptor
);
if (error != 0) {
printf("Error opening file: %d\n", error);
return 1;
}
// Write some data to the file
const char* data = "Hello, WASI!\n";
__wasi_ciovec_t iov;
iov.buf = (uint8_t*)data;
iov.buf_len = strlen(data);
size_t nwritten;
error = __wasi_fd_write(fd, &iov, 1, &nwritten);
if (error != 0) {
printf("Error writing to file: %d\n", error);
return 1;
}
// Close the file descriptor
__wasi_fd_close(fd);
printf("Successfully wrote to file\n");
return 0;
}
```
## Where does `dirfd` come from?
In WASI, the `dirfd` typically comes from:
1. **Pre-opened directories**: When a WASI module is executed, the runtime pre-opens certain directories and passes their file descriptors to the module. Typically:
- `fd=3` is the first pre-opened directory (often corresponds to the current working directory)
- `fd=4` and above might be additional pre-opened directories
2. **Getting available pre-opened directories**: To properly determine which pre-opened directory to use, you can use `__wasi_fd_prestat_get` and `__wasi_fd_prestat_dir_name`:
```c
// More robust approach to find a suitable pre-opened directory
__wasi_fd_t find_preopened_dir() {
for (__wasi_fd_t fd = 3; fd < 10; ++fd) {
__wasi_prestat_t prestat;
__wasi_errno_t err = __wasi_fd_prestat_get(fd, &prestat);
if (err == 0 && prestat.tag == __WASI_PREOPENTYPE_DIR) {
// Found a pre-opened directory
char *path = malloc(prestat.u.dir.pr_name_len + 1);
err = __wasi_fd_prestat_dir_name(fd, path, prestat.u.dir.pr_name_len);
if (err == 0) {
path[prestat.u.dir.pr_name_len] = '\0';
printf("Found pre-opened directory: %s (fd=%d)\n", path, fd);
free(path);
return fd;
}
free(path);
}
}
return -1;
}
```
When running your WASI module, you need to make sure the runtime (like `wasmtime` or `wasmer`) pre-opens the necessary directories:
```
wasmtime --dir=. your_module.wasm
```
This command grants your WASI module access to the current directory (`.`).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment