Created
April 5, 2025 14:57
-
-
Save skeeto/7103f03abf663b88ca6dfc431b696f62 to your computer and use it in GitHub Desktop.
Question via Illume
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!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