From 0c63bb24c8444699a8ec402fc2f1377f83e576b6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 27 Feb 2026 17:33:31 -0800 Subject: [PATCH 01/13] wasip3: Implement functions related to removing files/dirs Gets a few more tests passing --- cmake/bindings.cmake | 3 + .../cloudlibc/src/libc/unistd/faccessat.c | 10 +- .../headers/public/wasi/__generated_wasip3.h | 6 +- libc-bottom-half/sources/__wasilibc_rmdirat.c | 10 +- .../sources/__wasilibc_unlinkat.c | 10 +- libc-bottom-half/sources/wasip3.c | 142 ++++++++++++++++-- test/CMakeLists.txt | 16 +- 7 files changed, 150 insertions(+), 47 deletions(-) diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index 529d41f28..e7919a289 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -113,9 +113,12 @@ add_custom_target( "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.metadata-hash" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.metadata-hash-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.stat" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.stat-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.get-flags" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.open-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.read-directory" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.remove-directory-at" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.unlink-file-at" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-until" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-for" ${CMAKE_SOURCE_DIR}/wasi/p3/wit diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c index 38a48945f..052881173 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c @@ -55,7 +55,7 @@ int __wasilibc_nocwd_faccessat(int fd, const char *path, int amode, int flag) { return -1; } } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal handle // Translate the file descriptor to an internal handle filesystem_borrow_descriptor_t file_handle; @@ -63,7 +63,7 @@ int __wasilibc_nocwd_faccessat(int fd, const char *path, int amode, int flag) { return -1; // Convert the string into a WASI string - wasip2_string_t wasi_path; + wasi_string_t wasi_path; if (wasi_string_from_c(path, &wasi_path) < 0) return -1; @@ -109,12 +109,6 @@ int __wasilibc_nocwd_faccessat(int fd, const char *path, int amode, int flag) { return -1; } } -#elif defined(__wasip3__) - (void) fd; - (void) path; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h index cb1aa21df..ac7fab491 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -1144,7 +1144,7 @@ extern bool filesystem_method_descriptor_stat(filesystem_borrow_descriptor_t sel // discussion of alternatives. // // Note: This was called `path_filestat_get` in earlier versions of WASI. -extern wasip3_subtask_status_t filesystem_method_descriptor_stat_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t path_flags, wasip3_string_t path, filesystem_result_descriptor_stat_error_code_t *result); +extern bool filesystem_method_descriptor_stat_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t path_flags, wasip3_string_t *path, filesystem_descriptor_stat_t *ret, filesystem_error_code_t *err); // Adjust the timestamps of a file or directory. // // Note: This is similar to `utimensat` in POSIX. @@ -1185,7 +1185,7 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_readlink_at(filesyst // Return `error-code::not-empty` if the directory is not empty. // // Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. -extern wasip3_subtask_status_t filesystem_method_descriptor_remove_directory_at(filesystem_borrow_descriptor_t self, wasip3_string_t path, filesystem_result_void_error_code_t *result); +extern bool filesystem_method_descriptor_remove_directory_at(filesystem_borrow_descriptor_t self, wasip3_string_t *path, filesystem_error_code_t *err); // Rename a filesystem object. // // Note: This is similar to `renameat` in POSIX. @@ -1201,7 +1201,7 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_symlink_at(filesyste // // Return `error-code::is-directory` if the path refers to a directory. // Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. -extern wasip3_subtask_status_t filesystem_method_descriptor_unlink_file_at(filesystem_borrow_descriptor_t self, wasip3_string_t path, filesystem_result_void_error_code_t *result); +extern bool filesystem_method_descriptor_unlink_file_at(filesystem_borrow_descriptor_t self, wasip3_string_t *path, filesystem_error_code_t *err); // Test whether two descriptors refer to the same filesystem object. // // In POSIX, this corresponds to testing whether the two descriptors have the diff --git a/libc-bottom-half/sources/__wasilibc_rmdirat.c b/libc-bottom-half/sources/__wasilibc_rmdirat.c index 50bfef338..bb0e965d7 100644 --- a/libc-bottom-half/sources/__wasilibc_rmdirat.c +++ b/libc-bottom-half/sources/__wasilibc_rmdirat.c @@ -15,14 +15,14 @@ int __wasilibc_nocwd___wasilibc_rmdirat(int fd, const char *path) { errno = error; return -1; } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal handle filesystem_borrow_descriptor_t file_handle; if (fd_to_file_handle(fd, &file_handle) < 0) return -1; // Create a WASI string for the path - wasip2_string_t wasi_path; + wasi_string_t wasi_path; if (wasi_string_from_c(path, &wasi_path) < 0) return -1; filesystem_error_code_t error_code; @@ -34,12 +34,6 @@ int __wasilibc_nocwd___wasilibc_rmdirat(int fd, const char *path) { translate_error(error_code); return -1; } -#elif defined(__wasip3__) - (void)fd; - (void)path; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else #error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/sources/__wasilibc_unlinkat.c b/libc-bottom-half/sources/__wasilibc_unlinkat.c index 7bd2cde8e..3b5488ddc 100644 --- a/libc-bottom-half/sources/__wasilibc_unlinkat.c +++ b/libc-bottom-half/sources/__wasilibc_unlinkat.c @@ -16,7 +16,7 @@ int __wasilibc_nocwd___wasilibc_unlinkat(int fd, const char *path) { return -1; } return 0; -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal handle descriptor_table_entry_t *entry = descriptor_table_get_ref(fd); if (!entry) @@ -33,7 +33,7 @@ int __wasilibc_nocwd___wasilibc_unlinkat(int fd, const char *path) { return -1; // Create a Wasm string from the path - wasip2_string_t wasi_path; + wasi_string_t wasi_path; if (wasi_string_from_c(path, &wasi_path) < 0) return -1; @@ -47,12 +47,6 @@ int __wasilibc_nocwd___wasilibc_unlinkat(int fd, const char *path) { } return 0; -#elif defined(__wasip3__) - (void)fd; - (void)path; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else #error "Unknown WASI version" #endif diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index 8e25f23b5..14e11467d 100644 --- a/libc-bottom-half/sources/wasip3.c +++ b/libc-bottom-half/sources/wasip3.c @@ -112,8 +112,8 @@ extern int32_t __wasm_import_filesystem_method_descriptor_create_directory_at(in __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.stat"))) extern void __wasm_import_filesystem_method_descriptor_stat(int32_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.stat-at"))) -extern int32_t __wasm_import_filesystem_method_descriptor_stat_at(int32_t, int32_t, uint8_t *, size_t, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.stat-at"))) +extern void __wasm_import_filesystem_method_descriptor_stat_at(int32_t, int32_t, uint8_t *, size_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.set-times-at"))) extern int32_t __wasm_import_filesystem_method_descriptor_set_times_at(uint8_t *, uint8_t *); @@ -127,8 +127,8 @@ extern void __wasm_import_filesystem_method_descriptor_open_at(int32_t, int32_t, __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.readlink-at"))) extern int32_t __wasm_import_filesystem_method_descriptor_readlink_at(int32_t, uint8_t *, size_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.remove-directory-at"))) -extern int32_t __wasm_import_filesystem_method_descriptor_remove_directory_at(int32_t, uint8_t *, size_t, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.remove-directory-at"))) +extern void __wasm_import_filesystem_method_descriptor_remove_directory_at(int32_t, uint8_t *, size_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.rename-at"))) extern int32_t __wasm_import_filesystem_method_descriptor_rename_at(uint8_t *, uint8_t *); @@ -136,8 +136,8 @@ extern int32_t __wasm_import_filesystem_method_descriptor_rename_at(uint8_t *, u __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.symlink-at"))) extern int32_t __wasm_import_filesystem_method_descriptor_symlink_at(uint8_t *, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.unlink-file-at"))) -extern int32_t __wasm_import_filesystem_method_descriptor_unlink_file_at(int32_t, uint8_t *, size_t, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.unlink-file-at"))) +extern void __wasm_import_filesystem_method_descriptor_unlink_file_at(int32_t, uint8_t *, size_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.is-same-object"))) extern int32_t __wasm_import_filesystem_method_descriptor_is_same_object(int32_t, int32_t, uint8_t *); @@ -1572,8 +1572,84 @@ bool filesystem_method_descriptor_stat(filesystem_borrow_descriptor_t self, file } } -wasip3_subtask_status_t filesystem_method_descriptor_stat_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t path_flags, wasip3_string_t path, filesystem_result_descriptor_stat_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_stat_at((self).__handle, path_flags, (uint8_t *) (path).ptr, (path).len, (uint8_t*) result); +bool filesystem_method_descriptor_stat_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t path_flags, wasip3_string_t *path, filesystem_descriptor_stat_t *ret, filesystem_error_code_t *err) { + __attribute__((__aligned__(8))) + uint8_t ret_area[104]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_stat_at((self).__handle, path_flags, (uint8_t *) (*path).ptr, (*path).len, ptr); + filesystem_result_descriptor_stat_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + filesystem_option_instant_t option; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + option.val = (system_clock_instant_t) { + (int64_t) *((int64_t*) (ptr + 40)), + (uint32_t) (uint32_t) (*((int32_t*) (ptr + 48))), + }; + break; + } + } + filesystem_option_instant_t option0; + switch ((int32_t) *((uint8_t*) (ptr + 56))) { + case 0: { + option0.is_some = false; + break; + } + case 1: { + option0.is_some = true; + option0.val = (system_clock_instant_t) { + (int64_t) *((int64_t*) (ptr + 64)), + (uint32_t) (uint32_t) (*((int32_t*) (ptr + 72))), + }; + break; + } + } + filesystem_option_instant_t option1; + switch ((int32_t) *((uint8_t*) (ptr + 80))) { + case 0: { + option1.is_some = false; + break; + } + case 1: { + option1.is_some = true; + option1.val = (system_clock_instant_t) { + (int64_t) *((int64_t*) (ptr + 88)), + (uint32_t) (uint32_t) (*((int32_t*) (ptr + 96))), + }; + break; + } + } + + result.val.ok = (filesystem_descriptor_stat_t) { + (filesystem_descriptor_type_t) (int32_t) *((uint8_t*) (ptr + 8)), + (filesystem_link_count_t) (uint64_t) (*((int64_t*) (ptr + 16))), + (filesystem_filesize_t) (uint64_t) (*((int64_t*) (ptr + 24))), + (filesystem_option_instant_t) option, + (filesystem_option_instant_t) option0, + (filesystem_option_instant_t) option1, + }; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 8)); + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + *err = result.val.err; + return 0; + } } wasip3_subtask_status_t filesystem_method_descriptor_set_times_at(filesystem_method_descriptor_set_times_at_args_t *args, filesystem_result_void_error_code_t *result) { @@ -1615,8 +1691,29 @@ wasip3_subtask_status_t filesystem_method_descriptor_readlink_at(filesystem_borr return __wasm_import_filesystem_method_descriptor_readlink_at((self).__handle, (uint8_t *) (path).ptr, (path).len, (uint8_t*) result); } -wasip3_subtask_status_t filesystem_method_descriptor_remove_directory_at(filesystem_borrow_descriptor_t self, wasip3_string_t path, filesystem_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_remove_directory_at((self).__handle, (uint8_t *) (path).ptr, (path).len, (uint8_t*) result); +bool filesystem_method_descriptor_remove_directory_at(filesystem_borrow_descriptor_t self, wasip3_string_t *path, filesystem_error_code_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_remove_directory_at((self).__handle, (uint8_t *) (*path).ptr, (*path).len, ptr); + filesystem_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } } wasip3_subtask_status_t filesystem_method_descriptor_rename_at(filesystem_method_descriptor_rename_at_args_t *args, filesystem_result_void_error_code_t *result) { @@ -1627,8 +1724,29 @@ wasip3_subtask_status_t filesystem_method_descriptor_symlink_at(filesystem_metho return __wasm_import_filesystem_method_descriptor_symlink_at((uint8_t*) args, (uint8_t*) result); } -wasip3_subtask_status_t filesystem_method_descriptor_unlink_file_at(filesystem_borrow_descriptor_t self, wasip3_string_t path, filesystem_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_unlink_file_at((self).__handle, (uint8_t *) (path).ptr, (path).len, (uint8_t*) result); +bool filesystem_method_descriptor_unlink_file_at(filesystem_borrow_descriptor_t self, wasip3_string_t *path, filesystem_error_code_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_unlink_file_at((self).__handle, (uint8_t *) (*path).ptr, (*path).len, ptr); + filesystem_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } } wasip3_subtask_status_t filesystem_method_descriptor_is_same_object(filesystem_borrow_descriptor_t self, filesystem_borrow_descriptor_t other, bool *result) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 10995f2a3..0e22e4e80 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -257,7 +257,7 @@ endfunction() # TODO: this test fails with `-Sthreads` in Wasmtime since that uses a different # implementation of WASI which causes this test to fail. if (NOT TARGET_TRIPLE MATCHES "-threads") - add_wasilibc_test(access.c FS FAILP3) + add_wasilibc_test(access.c FS) endif() add_wasilibc_test(append.c FS FAILP3) add_wasilibc_test(argv_two_args.c ARGV foo bar) @@ -266,14 +266,14 @@ add_wasilibc_test(chdir.c FS FAILP3) add_wasilibc_test(close.c FS) add_wasilibc_test(external_env.c ENV VAR1=foo VAR2=bar) add_wasilibc_test(fadvise.c FS FAILP3) -add_wasilibc_test(fallocate.c FS FAILP3) -add_wasilibc_test(fcntl.c FS FAILP3) +add_wasilibc_test(fallocate.c FS) +add_wasilibc_test(fcntl.c FS) add_wasilibc_test(fdatasync.c FS FAILP3) -add_wasilibc_test(fdopen.c FS FAILP3) +add_wasilibc_test(fdopen.c FS) add_wasilibc_test(feof.c FS) -add_wasilibc_test(file_permissions.c FS FAILP3) +add_wasilibc_test(file_permissions.c FS) add_wasilibc_test(file_nonblocking.c FS) -add_wasilibc_test(fseek.c FS FAILP3) +add_wasilibc_test(fseek.c FS) add_wasilibc_test(fstat.c FS FAILP3) add_wasilibc_test(fsync.c FS FAILP3) add_wasilibc_test(ftruncate.c FS FAILP3) @@ -281,8 +281,8 @@ add_wasilibc_test(fts.c FS FAILP3) add_wasilibc_test(fwscanf.c FS) add_wasilibc_test(getentropy.c) add_wasilibc_test(hello.c PASS_REGULAR_EXPRESSION "Hello, World!") -add_wasilibc_test(ioctl.c FS FAILP3) -add_wasilibc_test(isatty.c FS FAILP3) +add_wasilibc_test(ioctl.c FS) +add_wasilibc_test(isatty.c FS) add_wasilibc_test(link.c FS FAILP3) add_wasilibc_test(lseek.c FS) add_wasilibc_test(memchr.c LDFLAGS -Wl,--stack-first -Wl,--initial-memory=327680) From 584631d66109c1b3bf3f9248fa5a48cc175a8827 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 27 Feb 2026 17:35:22 -0800 Subject: [PATCH 02/13] wasip3: Fix `append.c` test Handle `O_APPEND` by calling `append-via-stream` --- libc-bottom-half/sources/file.c | 14 ++++++++++---- test/CMakeLists.txt | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libc-bottom-half/sources/file.c b/libc-bottom-half/sources/file.c index ad7119c69..6f1d87c3e 100644 --- a/libc-bottom-half/sources/file.c +++ b/libc-bottom-half/sources/file.c @@ -181,10 +181,16 @@ static int file_get_write_stream(void *data, wasi_write_t *write) { if (file->write == 0) { assert(file->write_subtask == 0); filesystem_stream_u8_t write_read = filesystem_stream_u8_new(&file->write); - wasip3_subtask_status_t status = - filesystem_method_descriptor_write_via_stream( - filesystem_borrow_descriptor(file->file_handle), write_read, - file->offset, &file->write_pending_result); + wasip3_subtask_status_t status; + if (file->oflag & O_APPEND) { + status = filesystem_method_descriptor_append_via_stream( + filesystem_borrow_descriptor(file->file_handle), write_read, + &file->write_pending_result); + } else { + status = filesystem_method_descriptor_write_via_stream( + filesystem_borrow_descriptor(file->file_handle), write_read, + file->offset, &file->write_pending_result); + } if (WASIP3_SUBTASK_STATE(status) != WASIP3_SUBTASK_RETURNED) file->write_subtask = WASIP3_SUBTASK_HANDLE(status); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0e22e4e80..3595d76ef 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -259,7 +259,7 @@ endfunction() if (NOT TARGET_TRIPLE MATCHES "-threads") add_wasilibc_test(access.c FS) endif() -add_wasilibc_test(append.c FS FAILP3) +add_wasilibc_test(append.c FS) add_wasilibc_test(argv_two_args.c ARGV foo bar) add_wasilibc_test(clock_nanosleep.c) add_wasilibc_test(chdir.c FS FAILP3) From 0785d955819a594da94dc3f1bbd3f349bc28aa6c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 27 Feb 2026 17:38:23 -0800 Subject: [PATCH 03/13] wasip3: Ungate some `stat`-related tests Use the same WASIp2 implementation for WASIp3 --- cmake/bindings.cmake | 1 + .../cloudlibc/src/libc/sys/stat/fstat.c | 8 +---- .../cloudlibc/src/libc/sys/stat/fstatat.c | 12 ++------ .../cloudlibc/src/libc/sys/stat/mkdirat.c | 10 ++----- .../headers/public/wasi/__generated_wasip3.h | 2 +- libc-bottom-half/sources/wasip3.c | 29 ++++++++++++++++--- test/CMakeLists.txt | 16 +++++----- 7 files changed, 40 insertions(+), 38 deletions(-) diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index e7919a289..7c2c12743 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -117,6 +117,7 @@ add_custom_target( "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.get-flags" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.open-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.read-directory" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.create-directory-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.remove-directory-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.unlink-file-at" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-until" diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstat.c b/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstat.c index 01cc633ae..3a672067e 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstat.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstat.c @@ -18,18 +18,12 @@ int fstat(int fildes, struct stat *buf) { } to_public_stat(&internal_stat, buf); return 0; -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal handle descriptor_table_entry_t *entry = descriptor_table_get_ref(fildes); if (!entry) return -1; return entry->vtable->fstat(entry->data, buf); -#elif defined(__wasip3__) - (void) fildes; - (void) buf; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c b/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c index 7d8561edb..03d2a1a70 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c @@ -35,14 +35,14 @@ int __wasilibc_nocwd_fstatat(int fd, const char *restrict path, struct stat *res to_public_stat(&internal_stat, buf); return 0; -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal handle filesystem_borrow_descriptor_t file_handle; if (fd_to_file_handle(fd, &file_handle) < 0) return -1; // Convert the string into a Wasm string - wasip2_string_t path_wasm_string; + wasi_string_t path_wasm_string; if (wasi_string_from_c(path, &path_wasm_string) < 0) return -1; @@ -80,14 +80,6 @@ int __wasilibc_nocwd_fstatat(int fd, const char *restrict path, struct stat *res // Convert the internal data to an external struct to_public_stat(&metadata, &internal_stat, buf); return 0; -#elif defined(__wasip3__) - (void) fd; - (void) path; - (void) buf; - (void) flag; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c b/libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c index 52f9fef26..d758a9a99 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c @@ -21,7 +21,7 @@ int __wasilibc_nocwd_mkdirat_nomode(int fd, const char *path) { return -1; } return 0; -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal handle filesystem_borrow_descriptor_t file_handle; if (fd_to_file_handle(fd, &file_handle) < 0) @@ -29,7 +29,7 @@ int __wasilibc_nocwd_mkdirat_nomode(int fd, const char *path) { // Create the directory filesystem_error_code_t error; - wasip2_string_t path2; + wasi_string_t path2; if (wasi_string_from_c(path, &path2) < 0) return -1; bool ok = filesystem_method_descriptor_create_directory_at(file_handle, @@ -40,12 +40,6 @@ int __wasilibc_nocwd_mkdirat_nomode(int fd, const char *path) { return -1; } return 0; -#elif defined(__wasip3__) - (void) fd; - (void) path; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h index ac7fab491..c47893609 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -1126,7 +1126,7 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_sync(filesystem_borr // Create a directory. // // Note: This is similar to `mkdirat` in POSIX. -extern wasip3_subtask_status_t filesystem_method_descriptor_create_directory_at(filesystem_borrow_descriptor_t self, wasip3_string_t path, filesystem_result_void_error_code_t *result); +extern bool filesystem_method_descriptor_create_directory_at(filesystem_borrow_descriptor_t self, wasip3_string_t *path, filesystem_error_code_t *err); // Return the attributes of an open file or directory. // // Note: This is similar to `fstat` in POSIX, except that it does not return diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index 14e11467d..941e8e3b9 100644 --- a/libc-bottom-half/sources/wasip3.c +++ b/libc-bottom-half/sources/wasip3.c @@ -106,8 +106,8 @@ extern void __wasm_import_filesystem_method_descriptor_read_directory(int32_t, u __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.sync"))) extern int32_t __wasm_import_filesystem_method_descriptor_sync(int32_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.create-directory-at"))) -extern int32_t __wasm_import_filesystem_method_descriptor_create_directory_at(int32_t, uint8_t *, size_t, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.create-directory-at"))) +extern void __wasm_import_filesystem_method_descriptor_create_directory_at(int32_t, uint8_t *, size_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.stat"))) extern void __wasm_import_filesystem_method_descriptor_stat(int32_t, uint8_t *); @@ -1488,8 +1488,29 @@ wasip3_subtask_status_t filesystem_method_descriptor_sync(filesystem_borrow_desc return __wasm_import_filesystem_method_descriptor_sync((self).__handle, (uint8_t*) result); } -wasip3_subtask_status_t filesystem_method_descriptor_create_directory_at(filesystem_borrow_descriptor_t self, wasip3_string_t path, filesystem_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_create_directory_at((self).__handle, (uint8_t *) (path).ptr, (path).len, (uint8_t*) result); +bool filesystem_method_descriptor_create_directory_at(filesystem_borrow_descriptor_t self, wasip3_string_t *path, filesystem_error_code_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_create_directory_at((self).__handle, (uint8_t *) (*path).ptr, (*path).len, ptr); + filesystem_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } } bool filesystem_method_descriptor_stat(filesystem_borrow_descriptor_t self, filesystem_descriptor_stat_t *ret, filesystem_error_code_t *err) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3595d76ef..64050318f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -262,7 +262,7 @@ endif() add_wasilibc_test(append.c FS) add_wasilibc_test(argv_two_args.c ARGV foo bar) add_wasilibc_test(clock_nanosleep.c) -add_wasilibc_test(chdir.c FS FAILP3) +add_wasilibc_test(chdir.c FS) add_wasilibc_test(close.c FS) add_wasilibc_test(external_env.c ENV VAR1=foo VAR2=bar) add_wasilibc_test(fadvise.c FS FAILP3) @@ -274,7 +274,7 @@ add_wasilibc_test(feof.c FS) add_wasilibc_test(file_permissions.c FS) add_wasilibc_test(file_nonblocking.c FS) add_wasilibc_test(fseek.c FS) -add_wasilibc_test(fstat.c FS FAILP3) +add_wasilibc_test(fstat.c FS) add_wasilibc_test(fsync.c FS FAILP3) add_wasilibc_test(ftruncate.c FS FAILP3) add_wasilibc_test(fts.c FS FAILP3) @@ -288,16 +288,16 @@ add_wasilibc_test(lseek.c FS) add_wasilibc_test(memchr.c LDFLAGS -Wl,--stack-first -Wl,--initial-memory=327680) add_wasilibc_test(memcmp.c LDFLAGS -Wl,--stack-first -Wl,--initial-memory=327680) add_wasilibc_test(opendir.c FS ARGV /) -add_wasilibc_test(open_relative_path.c FS FAILP3 ARGV /) +add_wasilibc_test(open_relative_path.c FS ARGV /) add_wasilibc_test(poll.c FS FAILP3) add_wasilibc_test(preadvwritev.c FS FAILP3) add_wasilibc_test(preadwrite.c FS FAILP3) add_wasilibc_test(readlink.c FS FAILP3) add_wasilibc_test(readv.c FS) add_wasilibc_test(rename.c FS FAILP3) -add_wasilibc_test(rmdir.c FS FAILP3) -add_wasilibc_test(scandir.c FS FAILP3) -add_wasilibc_test(stat.c FS FAILP3) +add_wasilibc_test(rmdir.c FS) +add_wasilibc_test(scandir.c FS) +add_wasilibc_test(stat.c FS) add_wasilibc_test(stdio.c FS) add_wasilibc_test(strchrnul.c LDFLAGS -Wl,--stack-first -Wl,--initial-memory=327680) add_wasilibc_test(strlen.c LDFLAGS -Wl,--stack-first -Wl,--initial-memory=327680) @@ -309,11 +309,11 @@ add_wasilibc_test(time_and_times.c add_wasilibc_test(time.c) add_wasilibc_test(utime.c FS FAILP3) add_wasilibc_test(rewinddir.c FS FAILP3) -add_wasilibc_test(seekdir.c FS FAILP3) +add_wasilibc_test(seekdir.c FS) add_wasilibc_test(usleep.c) add_wasilibc_test(nanosleep.c) add_wasilibc_test(sleep.c) -add_wasilibc_test(write.c FS FAILP3) +add_wasilibc_test(write.c FS) add_wasilibc_test(wasi-defines.c) if (TARGET_TRIPLE MATCHES "-threads") From 1f26bbb477bc76a58e2570abe71681d9f994d501 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 27 Feb 2026 17:39:33 -0800 Subject: [PATCH 04/13] wasip3: Implement `fadvise` Use the wasip2 implementation --- cmake/bindings.cmake | 1 + .../cloudlibc/src/libc/fcntl/posix_fadvise.c | 8 +---- .../headers/public/wasi/__generated_wasip3.h | 2 +- libc-bottom-half/sources/wasip3.c | 29 ++++++++++++++++--- test/CMakeLists.txt | 2 +- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index 7c2c12743..853dd96ed 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -120,6 +120,7 @@ add_custom_target( "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.create-directory-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.remove-directory-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.unlink-file-at" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.advise" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-until" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-for" ${CMAKE_SOURCE_DIR}/wasi/p3/wit diff --git a/libc-bottom-half/cloudlibc/src/libc/fcntl/posix_fadvise.c b/libc-bottom-half/cloudlibc/src/libc/fcntl/posix_fadvise.c index 7a16be169..c27fc5565 100644 --- a/libc-bottom-half/cloudlibc/src/libc/fcntl/posix_fadvise.c +++ b/libc-bottom-half/cloudlibc/src/libc/fcntl/posix_fadvise.c @@ -30,7 +30,7 @@ int posix_fadvise(int fd, off_t offset, off_t len, int advice) { #if defined(__wasip1__) return __wasi_fd_advise(fd, offset, len, advice); -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) filesystem_borrow_descriptor_t file_handle; if (fd_to_file_handle(fd, &file_handle) < 0) return EBADF; @@ -71,12 +71,6 @@ int posix_fadvise(int fd, off_t offset, off_t len, int advice) { return errno; } return 0; -#elif defined(__wasip3__) - (void) fd; - (void) advice; - // TODO(wasip3) - errno = ENOTSUP; - return ENOTSUP; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h index c47893609..acad81cf2 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -1066,7 +1066,7 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_append_via_stream(fi // Provide file advisory information on a descriptor. // // This is similar to `posix_fadvise` in POSIX. -extern wasip3_subtask_status_t filesystem_method_descriptor_advise(filesystem_borrow_descriptor_t self, filesystem_filesize_t offset, filesystem_filesize_t length, filesystem_advice_t advice, filesystem_result_void_error_code_t *result); +extern bool filesystem_method_descriptor_advise(filesystem_borrow_descriptor_t self, filesystem_filesize_t offset, filesystem_filesize_t length, filesystem_advice_t advice, filesystem_error_code_t *err); // Synchronize the data of a file to disk. // // This function succeeds with no effect if the file descriptor is not diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index 941e8e3b9..2db58e499 100644 --- a/libc-bottom-half/sources/wasip3.c +++ b/libc-bottom-half/sources/wasip3.c @@ -82,8 +82,8 @@ extern int32_t __wasm_import_filesystem_method_descriptor_write_via_stream(int32 __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.append-via-stream"))) extern int32_t __wasm_import_filesystem_method_descriptor_append_via_stream(int32_t, int32_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.advise"))) -extern int32_t __wasm_import_filesystem_method_descriptor_advise(int32_t, int64_t, int64_t, int32_t, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.advise"))) +extern void __wasm_import_filesystem_method_descriptor_advise(int32_t, int64_t, int64_t, int32_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.sync-data"))) extern int32_t __wasm_import_filesystem_method_descriptor_sync_data(int32_t, uint8_t *); @@ -1426,8 +1426,29 @@ wasip3_subtask_status_t filesystem_method_descriptor_append_via_stream(filesyste return __wasm_import_filesystem_method_descriptor_append_via_stream((self).__handle, ((int32_t) data), (uint8_t*) result); } -wasip3_subtask_status_t filesystem_method_descriptor_advise(filesystem_borrow_descriptor_t self, filesystem_filesize_t offset, filesystem_filesize_t length, filesystem_advice_t advice, filesystem_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_advise((self).__handle, (int64_t) (offset), (int64_t) (length), (int32_t) advice, (uint8_t*) result); +bool filesystem_method_descriptor_advise(filesystem_borrow_descriptor_t self, filesystem_filesize_t offset, filesystem_filesize_t length, filesystem_advice_t advice, filesystem_error_code_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_advise((self).__handle, (int64_t) (offset), (int64_t) (length), (int32_t) advice, ptr); + filesystem_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } } wasip3_subtask_status_t filesystem_method_descriptor_sync_data(filesystem_borrow_descriptor_t self, filesystem_result_void_error_code_t *result) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 64050318f..be85d38bb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -265,7 +265,7 @@ add_wasilibc_test(clock_nanosleep.c) add_wasilibc_test(chdir.c FS) add_wasilibc_test(close.c FS) add_wasilibc_test(external_env.c ENV VAR1=foo VAR2=bar) -add_wasilibc_test(fadvise.c FS FAILP3) +add_wasilibc_test(fadvise.c FS) add_wasilibc_test(fallocate.c FS) add_wasilibc_test(fcntl.c FS) add_wasilibc_test(fdatasync.c FS FAILP3) From 18ad0fb203c652bf3f35ba2f2ff7713263e47b28 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 27 Feb 2026 17:40:16 -0800 Subject: [PATCH 05/13] wasip3: Implement `fdatasync` Use the wasip2 implementation --- cmake/bindings.cmake | 1 + .../cloudlibc/src/libc/unistd/fdatasync.c | 7 +---- .../headers/public/wasi/__generated_wasip3.h | 2 +- libc-bottom-half/sources/wasip3.c | 29 ++++++++++++++++--- test/CMakeLists.txt | 2 +- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index 853dd96ed..738befe09 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -121,6 +121,7 @@ add_custom_target( "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.remove-directory-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.unlink-file-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.advise" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.sync-data" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-until" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-for" ${CMAKE_SOURCE_DIR}/wasi/p3/wit diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/fdatasync.c b/libc-bottom-half/cloudlibc/src/libc/unistd/fdatasync.c index 66d4d452b..57a13942b 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/fdatasync.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/fdatasync.c @@ -19,7 +19,7 @@ int fdatasync(int fildes) { errno = error == ENOTCAPABLE ? EBADF : error; return -1; } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal handle filesystem_borrow_descriptor_t file_handle; if (fd_to_file_handle(fildes, &file_handle) < 0) @@ -31,11 +31,6 @@ int fdatasync(int fildes) { translate_error(error_code); return -1; } -#elif defined(__wasip3__) - (void) fildes; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h index acad81cf2..c6654328e 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -1073,7 +1073,7 @@ extern bool filesystem_method_descriptor_advise(filesystem_borrow_descriptor_t s // opened for writing. // // Note: This is similar to `fdatasync` in POSIX. -extern wasip3_subtask_status_t filesystem_method_descriptor_sync_data(filesystem_borrow_descriptor_t self, filesystem_result_void_error_code_t *result); +extern bool filesystem_method_descriptor_sync_data(filesystem_borrow_descriptor_t self, filesystem_error_code_t *err); // Get flags associated with a descriptor. // // Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX. diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index 2db58e499..cdfd2995b 100644 --- a/libc-bottom-half/sources/wasip3.c +++ b/libc-bottom-half/sources/wasip3.c @@ -85,8 +85,8 @@ extern int32_t __wasm_import_filesystem_method_descriptor_append_via_stream(int3 __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.advise"))) extern void __wasm_import_filesystem_method_descriptor_advise(int32_t, int64_t, int64_t, int32_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.sync-data"))) -extern int32_t __wasm_import_filesystem_method_descriptor_sync_data(int32_t, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.sync-data"))) +extern void __wasm_import_filesystem_method_descriptor_sync_data(int32_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.get-flags"))) extern void __wasm_import_filesystem_method_descriptor_get_flags(int32_t, uint8_t *); @@ -1451,8 +1451,29 @@ bool filesystem_method_descriptor_advise(filesystem_borrow_descriptor_t self, fi } } -wasip3_subtask_status_t filesystem_method_descriptor_sync_data(filesystem_borrow_descriptor_t self, filesystem_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_sync_data((self).__handle, (uint8_t*) result); +bool filesystem_method_descriptor_sync_data(filesystem_borrow_descriptor_t self, filesystem_error_code_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_sync_data((self).__handle, ptr); + filesystem_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } } bool filesystem_method_descriptor_get_flags(filesystem_borrow_descriptor_t self, filesystem_descriptor_flags_t *ret, filesystem_error_code_t *err) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index be85d38bb..ad8530bdf 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -268,7 +268,7 @@ add_wasilibc_test(external_env.c ENV VAR1=foo VAR2=bar) add_wasilibc_test(fadvise.c FS) add_wasilibc_test(fallocate.c FS) add_wasilibc_test(fcntl.c FS) -add_wasilibc_test(fdatasync.c FS FAILP3) +add_wasilibc_test(fdatasync.c FS) add_wasilibc_test(fdopen.c FS) add_wasilibc_test(feof.c FS) add_wasilibc_test(file_permissions.c FS) From fd6bdb62ccb8ba3288d3d27be6962c594bdfc1e8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 27 Feb 2026 17:41:12 -0800 Subject: [PATCH 06/13] wasip3: Implement `fsync` Use the wasip2 implementation --- cmake/bindings.cmake | 1 + .../cloudlibc/src/libc/unistd/fsync.c | 7 +---- .../headers/public/wasi/__generated_wasip3.h | 2 +- libc-bottom-half/sources/wasip3.c | 29 ++++++++++++++++--- test/CMakeLists.txt | 2 +- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index 738befe09..948ede25c 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -122,6 +122,7 @@ add_custom_target( "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.unlink-file-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.advise" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.sync-data" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.sync" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-until" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-for" ${CMAKE_SOURCE_DIR}/wasi/p3/wit diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/fsync.c b/libc-bottom-half/cloudlibc/src/libc/unistd/fsync.c index ef12c2e5d..01e8df443 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/fsync.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/fsync.c @@ -18,7 +18,7 @@ int fsync(int fildes) { errno = error == ENOTCAPABLE ? EINVAL : error; return -1; } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal handle filesystem_borrow_descriptor_t file_handle; if (fd_to_file_handle(fildes, &file_handle) < 0) @@ -30,11 +30,6 @@ int fsync(int fildes) { translate_error(error_code); return -1; } -#elif defined(__wasip3__) - (void) fildes; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h index c6654328e..c9e84cd08 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -1122,7 +1122,7 @@ extern void filesystem_method_descriptor_read_directory(filesystem_borrow_descri // opened for writing. // // Note: This is similar to `fsync` in POSIX. -extern wasip3_subtask_status_t filesystem_method_descriptor_sync(filesystem_borrow_descriptor_t self, filesystem_result_void_error_code_t *result); +extern bool filesystem_method_descriptor_sync(filesystem_borrow_descriptor_t self, filesystem_error_code_t *err); // Create a directory. // // Note: This is similar to `mkdirat` in POSIX. diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index cdfd2995b..672637121 100644 --- a/libc-bottom-half/sources/wasip3.c +++ b/libc-bottom-half/sources/wasip3.c @@ -103,8 +103,8 @@ extern int32_t __wasm_import_filesystem_method_descriptor_set_times(uint8_t *, u __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.read-directory"))) extern void __wasm_import_filesystem_method_descriptor_read_directory(int32_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.sync"))) -extern int32_t __wasm_import_filesystem_method_descriptor_sync(int32_t, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.sync"))) +extern void __wasm_import_filesystem_method_descriptor_sync(int32_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.create-directory-at"))) extern void __wasm_import_filesystem_method_descriptor_create_directory_at(int32_t, uint8_t *, size_t, uint8_t *); @@ -1526,8 +1526,29 @@ void filesystem_method_descriptor_read_directory(filesystem_borrow_descriptor_t }; } -wasip3_subtask_status_t filesystem_method_descriptor_sync(filesystem_borrow_descriptor_t self, filesystem_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_sync((self).__handle, (uint8_t*) result); +bool filesystem_method_descriptor_sync(filesystem_borrow_descriptor_t self, filesystem_error_code_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_sync((self).__handle, ptr); + filesystem_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } } bool filesystem_method_descriptor_create_directory_at(filesystem_borrow_descriptor_t self, wasip3_string_t *path, filesystem_error_code_t *err) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ad8530bdf..1d059e3b0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -275,7 +275,7 @@ add_wasilibc_test(file_permissions.c FS) add_wasilibc_test(file_nonblocking.c FS) add_wasilibc_test(fseek.c FS) add_wasilibc_test(fstat.c FS) -add_wasilibc_test(fsync.c FS FAILP3) +add_wasilibc_test(fsync.c FS) add_wasilibc_test(ftruncate.c FS FAILP3) add_wasilibc_test(fts.c FS FAILP3) add_wasilibc_test(fwscanf.c FS) From d7ac5bff871e78c6f3cbb5c241adde22bf537aea Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 27 Feb 2026 17:42:01 -0800 Subject: [PATCH 07/13] wasip3: Implement `ftruncate` Use the wasip2 implementation --- cmake/bindings.cmake | 1 + .../cloudlibc/src/libc/unistd/ftruncate.c | 7 +---- .../headers/public/wasi/__generated_wasip3.h | 2 +- libc-bottom-half/sources/wasip3.c | 29 ++++++++++++++++--- test/CMakeLists.txt | 2 +- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index 948ede25c..661d2ffb1 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -123,6 +123,7 @@ add_custom_target( "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.advise" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.sync-data" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.sync" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.set-size" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-until" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-for" ${CMAKE_SOURCE_DIR}/wasi/p3/wit diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/ftruncate.c b/libc-bottom-half/cloudlibc/src/libc/unistd/ftruncate.c index 2722b95e2..08a1d685e 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/ftruncate.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/ftruncate.c @@ -24,7 +24,7 @@ int ftruncate(int fildes, off_t length) { errno = error; return -1; } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal file handle filesystem_borrow_descriptor_t file_handle; if (fd_to_file_handle(fildes, &file_handle) < 0) @@ -35,11 +35,6 @@ int ftruncate(int fildes, off_t length) { translate_error(error_code); return -1; } -#elif defined(__wasip3__) - (void) fildes; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h index c9e84cd08..8a8bdc15b 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -1096,7 +1096,7 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_get_type(filesystem_ // extra bytes are filled with zeros. // // Note: This was called `fd_filestat_set_size` in earlier versions of WASI. -extern wasip3_subtask_status_t filesystem_method_descriptor_set_size(filesystem_borrow_descriptor_t self, filesystem_filesize_t size, filesystem_result_void_error_code_t *result); +extern bool filesystem_method_descriptor_set_size(filesystem_borrow_descriptor_t self, filesystem_filesize_t size, filesystem_error_code_t *err); // Adjust the timestamps of an open file or directory. // // Note: This is similar to `futimens` in POSIX. diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index 672637121..19eb93816 100644 --- a/libc-bottom-half/sources/wasip3.c +++ b/libc-bottom-half/sources/wasip3.c @@ -94,8 +94,8 @@ extern void __wasm_import_filesystem_method_descriptor_get_flags(int32_t, uint8_ __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.get-type"))) extern int32_t __wasm_import_filesystem_method_descriptor_get_type(int32_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.set-size"))) -extern int32_t __wasm_import_filesystem_method_descriptor_set_size(int32_t, int64_t, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.set-size"))) +extern void __wasm_import_filesystem_method_descriptor_set_size(int32_t, int64_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.set-times"))) extern int32_t __wasm_import_filesystem_method_descriptor_set_times(uint8_t *, uint8_t *); @@ -1507,8 +1507,29 @@ wasip3_subtask_status_t filesystem_method_descriptor_get_type(filesystem_borrow_ return __wasm_import_filesystem_method_descriptor_get_type((self).__handle, (uint8_t*) result); } -wasip3_subtask_status_t filesystem_method_descriptor_set_size(filesystem_borrow_descriptor_t self, filesystem_filesize_t size, filesystem_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_set_size((self).__handle, (int64_t) (size), (uint8_t*) result); +bool filesystem_method_descriptor_set_size(filesystem_borrow_descriptor_t self, filesystem_filesize_t size, filesystem_error_code_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_set_size((self).__handle, (int64_t) (size), ptr); + filesystem_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } } wasip3_subtask_status_t filesystem_method_descriptor_set_times(filesystem_method_descriptor_set_times_args_t *args, filesystem_result_void_error_code_t *result) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1d059e3b0..e07be3eb8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -276,7 +276,7 @@ add_wasilibc_test(file_nonblocking.c FS) add_wasilibc_test(fseek.c FS) add_wasilibc_test(fstat.c FS) add_wasilibc_test(fsync.c FS) -add_wasilibc_test(ftruncate.c FS FAILP3) +add_wasilibc_test(ftruncate.c FS) add_wasilibc_test(fts.c FS FAILP3) add_wasilibc_test(fwscanf.c FS) add_wasilibc_test(getentropy.c) From 9d516f12153f7953359965df14255593d23a6435 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 27 Feb 2026 17:42:54 -0800 Subject: [PATCH 08/13] wasip3: Implement `symlinkat` Use the wasip2 implementation --- cmake/bindings.cmake | 1 + .../cloudlibc/src/libc/unistd/symlinkat.c | 11 ++----- .../headers/public/wasi/__generated_wasip3.h | 7 +---- libc-bottom-half/sources/wasip3.c | 29 ++++++++++++++++--- test/CMakeLists.txt | 2 +- 5 files changed, 30 insertions(+), 20 deletions(-) diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index 661d2ffb1..07a57a0a9 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -124,6 +124,7 @@ add_custom_target( "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.sync-data" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.sync" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.set-size" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.symlink-at" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-until" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-for" ${CMAKE_SOURCE_DIR}/wasi/p3/wit diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c index 96aea65be..5ea2c97dd 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c @@ -19,14 +19,14 @@ int __wasilibc_nocwd_symlinkat(const char *path1, int fd, const char *path2) { errno = error; return -1; } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal handle filesystem_borrow_descriptor_t file_handle; if (fd_to_file_handle(fd, &file_handle) < 0) return -1; // Convert the paths into WASI paths - wasip2_string_t path1_wasi, path2_wasi; + wasi_string_t path1_wasi, path2_wasi; if (wasi_string_from_c(path1, &path1_wasi) < 0) return -1; if (wasi_string_from_c(path2, &path2_wasi) < 0) @@ -44,13 +44,6 @@ int __wasilibc_nocwd_symlinkat(const char *path1, int fd, const char *path2) { translate_error(error_code); return -1; } -#elif defined(__wasip3__) - (void) path1; - (void) path2; - (void) fd; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h index 8a8bdc15b..ecfbd28f8 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -599,11 +599,6 @@ typedef struct filesystem_method_descriptor_rename_at_args { filesystem_borrow_descriptor_t new_descriptor; wasip3_string_t new_path; } filesystem_method_descriptor_rename_at_args_t; -typedef struct filesystem_method_descriptor_symlink_at_args { - filesystem_borrow_descriptor_t self; - wasip3_string_t old_path; - wasip3_string_t new_path; -} filesystem_method_descriptor_symlink_at_args_t; typedef filesystem_own_descriptor_t filesystem_preopens_own_descriptor_t; @@ -1196,7 +1191,7 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_rename_at(filesystem // `error-code::not-permitted`. // // Note: This is similar to `symlinkat` in POSIX. -extern wasip3_subtask_status_t filesystem_method_descriptor_symlink_at(filesystem_method_descriptor_symlink_at_args_t *args, filesystem_result_void_error_code_t *result); +extern bool filesystem_method_descriptor_symlink_at(filesystem_borrow_descriptor_t self, wasip3_string_t *old_path, wasip3_string_t *new_path, filesystem_error_code_t *err); // Unlink a filesystem object that is not a directory. // // Return `error-code::is-directory` if the path refers to a directory. diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index 19eb93816..df7922b93 100644 --- a/libc-bottom-half/sources/wasip3.c +++ b/libc-bottom-half/sources/wasip3.c @@ -133,8 +133,8 @@ extern void __wasm_import_filesystem_method_descriptor_remove_directory_at(int32 __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.rename-at"))) extern int32_t __wasm_import_filesystem_method_descriptor_rename_at(uint8_t *, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.symlink-at"))) -extern int32_t __wasm_import_filesystem_method_descriptor_symlink_at(uint8_t *, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.symlink-at"))) +extern void __wasm_import_filesystem_method_descriptor_symlink_at(int32_t, uint8_t *, size_t, uint8_t *, size_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.unlink-file-at"))) extern void __wasm_import_filesystem_method_descriptor_unlink_file_at(int32_t, uint8_t *, size_t, uint8_t *); @@ -1825,8 +1825,29 @@ wasip3_subtask_status_t filesystem_method_descriptor_rename_at(filesystem_method return __wasm_import_filesystem_method_descriptor_rename_at((uint8_t*) args, (uint8_t*) result); } -wasip3_subtask_status_t filesystem_method_descriptor_symlink_at(filesystem_method_descriptor_symlink_at_args_t *args, filesystem_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_symlink_at((uint8_t*) args, (uint8_t*) result); +bool filesystem_method_descriptor_symlink_at(filesystem_borrow_descriptor_t self, wasip3_string_t *old_path, wasip3_string_t *new_path, filesystem_error_code_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_symlink_at((self).__handle, (uint8_t *) (*old_path).ptr, (*old_path).len, (uint8_t *) (*new_path).ptr, (*new_path).len, ptr); + filesystem_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } } bool filesystem_method_descriptor_unlink_file_at(filesystem_borrow_descriptor_t self, wasip3_string_t *path, filesystem_error_code_t *err) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e07be3eb8..4b3a24715 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -277,7 +277,7 @@ add_wasilibc_test(fseek.c FS) add_wasilibc_test(fstat.c FS) add_wasilibc_test(fsync.c FS) add_wasilibc_test(ftruncate.c FS) -add_wasilibc_test(fts.c FS FAILP3) +add_wasilibc_test(fts.c FS) add_wasilibc_test(fwscanf.c FS) add_wasilibc_test(getentropy.c) add_wasilibc_test(hello.c PASS_REGULAR_EXPRESSION "Hello, World!") From 253e7c6e26df5d8cfb4776d639c5a785894e51ac Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 27 Feb 2026 17:43:37 -0800 Subject: [PATCH 09/13] wasip3: Implement `linkat` Use the wasip2 implementation --- cmake/bindings.cmake | 1 + .../cloudlibc/src/libc/unistd/linkat.c | 13 ++------- .../headers/public/wasi/__generated_wasip3.h | 9 +----- libc-bottom-half/sources/wasip3.c | 29 ++++++++++++++++--- test/CMakeLists.txt | 2 +- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index 07a57a0a9..6d3106386 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -125,6 +125,7 @@ add_custom_target( "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.sync" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.set-size" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.symlink-at" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.link-at" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-until" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-for" ${CMAKE_SOURCE_DIR}/wasi/p3/wit diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c index 2cbd27dc1..17d54eca8 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c @@ -26,7 +26,7 @@ int __wasilibc_nocwd_linkat(int fd1, const char *path1, int fd2, const char *pat errno = error; return -1; } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptors to internal handles filesystem_borrow_descriptor_t file_handle1, file_handle2; if (fd_to_file_handle(fd1, &file_handle1) < 0) @@ -35,7 +35,7 @@ int __wasilibc_nocwd_linkat(int fd1, const char *path1, int fd2, const char *pat return -1; // Convert the strings into WASI strings - wasip2_string_t path1_wasi, path2_wasi; + wasi_string_t path1_wasi, path2_wasi; if (wasi_string_from_c(path1, &path1_wasi) < 0) return -1; if (wasi_string_from_c(path2, &path2_wasi) < 0) @@ -56,15 +56,6 @@ int __wasilibc_nocwd_linkat(int fd1, const char *path1, int fd2, const char *pat translate_error(error_code); return -1; } -#elif defined(__wasip3__) - (void) fd1; - (void) path1; - (void) fd2; - (void) path2; - (void) flag; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h index ecfbd28f8..413af18e7 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -586,13 +586,6 @@ typedef struct filesystem_method_descriptor_set_times_at_args { filesystem_new_timestamp_t data_access_timestamp; filesystem_new_timestamp_t data_modification_timestamp; } filesystem_method_descriptor_set_times_at_args_t; -typedef struct filesystem_method_descriptor_link_at_args { - filesystem_borrow_descriptor_t self; - filesystem_path_flags_t old_path_flags; - wasip3_string_t old_path; - filesystem_borrow_descriptor_t new_descriptor; - wasip3_string_t new_path; -} filesystem_method_descriptor_link_at_args_t; typedef struct filesystem_method_descriptor_rename_at_args { filesystem_borrow_descriptor_t self; wasip3_string_t old_path; @@ -1154,7 +1147,7 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_set_times_at(filesys // `error-code::not-permitted` if the old path is not a file. // // Note: This is similar to `linkat` in POSIX. -extern wasip3_subtask_status_t filesystem_method_descriptor_link_at(filesystem_method_descriptor_link_at_args_t *args, filesystem_result_void_error_code_t *result); +extern bool filesystem_method_descriptor_link_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t old_path_flags, wasip3_string_t *old_path, filesystem_borrow_descriptor_t new_descriptor, wasip3_string_t *new_path, filesystem_error_code_t *err); // Open a file or directory. // // If `flags` contains `descriptor-flags::mutate-directory`, and the base diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index df7922b93..d384eef32 100644 --- a/libc-bottom-half/sources/wasip3.c +++ b/libc-bottom-half/sources/wasip3.c @@ -118,8 +118,8 @@ extern void __wasm_import_filesystem_method_descriptor_stat_at(int32_t, int32_t, __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.set-times-at"))) extern int32_t __wasm_import_filesystem_method_descriptor_set_times_at(uint8_t *, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.link-at"))) -extern int32_t __wasm_import_filesystem_method_descriptor_link_at(uint8_t *, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.link-at"))) +extern void __wasm_import_filesystem_method_descriptor_link_at(int32_t, int32_t, uint8_t *, size_t, int32_t, uint8_t *, size_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.open-at"))) extern void __wasm_import_filesystem_method_descriptor_open_at(int32_t, int32_t, uint8_t *, size_t, int32_t, int32_t, uint8_t *); @@ -1761,8 +1761,29 @@ wasip3_subtask_status_t filesystem_method_descriptor_set_times_at(filesystem_met return __wasm_import_filesystem_method_descriptor_set_times_at((uint8_t*) args, (uint8_t*) result); } -wasip3_subtask_status_t filesystem_method_descriptor_link_at(filesystem_method_descriptor_link_at_args_t *args, filesystem_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_link_at((uint8_t*) args, (uint8_t*) result); +bool filesystem_method_descriptor_link_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t old_path_flags, wasip3_string_t *old_path, filesystem_borrow_descriptor_t new_descriptor, wasip3_string_t *new_path, filesystem_error_code_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_link_at((self).__handle, old_path_flags, (uint8_t *) (*old_path).ptr, (*old_path).len, (new_descriptor).__handle, (uint8_t *) (*new_path).ptr, (*new_path).len, ptr); + filesystem_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } } bool filesystem_method_descriptor_open_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t path_flags, wasip3_string_t *path, filesystem_open_flags_t open_flags, filesystem_descriptor_flags_t flags, filesystem_own_descriptor_t *ret, filesystem_error_code_t *err) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4b3a24715..7056352dd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -283,7 +283,7 @@ add_wasilibc_test(getentropy.c) add_wasilibc_test(hello.c PASS_REGULAR_EXPRESSION "Hello, World!") add_wasilibc_test(ioctl.c FS) add_wasilibc_test(isatty.c FS) -add_wasilibc_test(link.c FS FAILP3) +add_wasilibc_test(link.c FS) add_wasilibc_test(lseek.c FS) add_wasilibc_test(memchr.c LDFLAGS -Wl,--stack-first -Wl,--initial-memory=327680) add_wasilibc_test(memcmp.c LDFLAGS -Wl,--stack-first -Wl,--initial-memory=327680) From a006bc1774d061604916f2911c9ecc3b0582b665 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 27 Feb 2026 17:46:38 -0800 Subject: [PATCH 10/13] wasip3: Implement `readlink` Use the wasip2 version --- cmake/bindings.cmake | 1 + .../cloudlibc/src/libc/unistd/readlinkat.c | 16 ++++------ .../headers/public/wasi/__generated_wasip3.h | 2 +- libc-bottom-half/sources/wasip3.c | 31 ++++++++++++++++--- test/CMakeLists.txt | 2 +- 5 files changed, 36 insertions(+), 16 deletions(-) diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index 6d3106386..f991b6ef5 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -126,6 +126,7 @@ add_custom_target( "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.set-size" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.symlink-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.link-at" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.readlink-at" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-until" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-for" ${CMAKE_SOURCE_DIR}/wasi/p3/wit diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c index 656b9c501..f5c93a6eb 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c @@ -23,14 +23,14 @@ ssize_t __wasilibc_nocwd_readlinkat(int fd, const char *restrict path, char *res errno = error; return -1; } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal handle filesystem_borrow_descriptor_t file_handle; if (fd_to_file_handle(fd, &file_handle) < 0) return -1; // Convert the path into a WASI path - wasip2_string_t wasi_path, link_source; + wasi_string_t wasi_path, link_source; if (wasi_string_from_c(path, &wasi_path) < 0) return -1; @@ -48,15 +48,11 @@ ssize_t __wasilibc_nocwd_readlinkat(int fd, const char *restrict path, char *res // Copy the contents of the output path back into the buffer provided bufused = bufsize < link_source.len ? bufsize : link_source.len; memcpy(buf, link_source.ptr, bufused); +#ifdef __wasip2__ wasip2_string_free(&link_source); -#elif defined(__wasip3__) - (void) fd; - (void) path; - (void) buf; - (void) bufsize; - // TODO(wasip3) - errno = ENOTSUP; - return -1; +#else + wasip3_string_free(&link_source); +#endif #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h index 413af18e7..b0925c577 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -1167,7 +1167,7 @@ extern bool filesystem_method_descriptor_open_at(filesystem_borrow_descriptor_t // filesystem, this function fails with `error-code::not-permitted`. // // Note: This is similar to `readlinkat` in POSIX. -extern wasip3_subtask_status_t filesystem_method_descriptor_readlink_at(filesystem_borrow_descriptor_t self, wasip3_string_t path, filesystem_result_string_error_code_t *result); +extern bool filesystem_method_descriptor_readlink_at(filesystem_borrow_descriptor_t self, wasip3_string_t *path, wasip3_string_t *ret, filesystem_error_code_t *err); // Remove a directory. // // Return `error-code::not-empty` if the directory is not empty. diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index d384eef32..43554eae4 100644 --- a/libc-bottom-half/sources/wasip3.c +++ b/libc-bottom-half/sources/wasip3.c @@ -124,8 +124,8 @@ extern void __wasm_import_filesystem_method_descriptor_link_at(int32_t, int32_t, __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.open-at"))) extern void __wasm_import_filesystem_method_descriptor_open_at(int32_t, int32_t, uint8_t *, size_t, int32_t, int32_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.readlink-at"))) -extern int32_t __wasm_import_filesystem_method_descriptor_readlink_at(int32_t, uint8_t *, size_t, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.readlink-at"))) +extern void __wasm_import_filesystem_method_descriptor_readlink_at(int32_t, uint8_t *, size_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.remove-directory-at"))) extern void __wasm_import_filesystem_method_descriptor_remove_directory_at(int32_t, uint8_t *, size_t, uint8_t *); @@ -1813,8 +1813,31 @@ bool filesystem_method_descriptor_open_at(filesystem_borrow_descriptor_t self, f } } -wasip3_subtask_status_t filesystem_method_descriptor_readlink_at(filesystem_borrow_descriptor_t self, wasip3_string_t path, filesystem_result_string_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_readlink_at((self).__handle, (uint8_t *) (path).ptr, (path).len, (uint8_t*) result); +bool filesystem_method_descriptor_readlink_at(filesystem_borrow_descriptor_t self, wasip3_string_t *path, wasip3_string_t *ret, filesystem_error_code_t *err) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(3*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_readlink_at((self).__handle, (uint8_t *) (*path).ptr, (*path).len, ptr); + filesystem_result_string_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (wasip3_string_t) { (uint8_t*)(*((uint8_t **) (ptr + sizeof(void*)))), (*((size_t*) (ptr + (2*sizeof(void*))))) }; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + sizeof(void*))); + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + *err = result.val.err; + return 0; + } } bool filesystem_method_descriptor_remove_directory_at(filesystem_borrow_descriptor_t self, wasip3_string_t *path, filesystem_error_code_t *err) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7056352dd..d9aac0bfe 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -292,7 +292,7 @@ add_wasilibc_test(open_relative_path.c FS ARGV /) add_wasilibc_test(poll.c FS FAILP3) add_wasilibc_test(preadvwritev.c FS FAILP3) add_wasilibc_test(preadwrite.c FS FAILP3) -add_wasilibc_test(readlink.c FS FAILP3) +add_wasilibc_test(readlink.c FS) add_wasilibc_test(readv.c FS) add_wasilibc_test(rename.c FS FAILP3) add_wasilibc_test(rmdir.c FS) From 469ba266f3b36b7fcc466239ddd5dc867c18cf2d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 27 Feb 2026 17:47:32 -0800 Subject: [PATCH 11/13] wasip3: Implement `renameat` Use the wasip2 implementation --- cmake/bindings.cmake | 1 + .../cloudlibc/src/libc/stdio/renameat.c | 12 ++------ .../headers/public/wasi/__generated_wasip3.h | 8 +---- libc-bottom-half/sources/wasip3.c | 29 ++++++++++++++++--- test/CMakeLists.txt | 2 +- 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index f991b6ef5..4702b15d9 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -127,6 +127,7 @@ add_custom_target( "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.symlink-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.link-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.readlink-at" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.rename-at" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-until" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-for" ${CMAKE_SOURCE_DIR}/wasi/p3/wit diff --git a/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c b/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c index 39d2730ad..0a576ef71 100644 --- a/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c +++ b/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c @@ -19,7 +19,7 @@ int __wasilibc_nocwd_renameat(int oldfd, const char *old, int newfd, const char errno = error; return -1; } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptors to internal handles filesystem_borrow_descriptor_t old_file_handle; if (fd_to_file_handle(oldfd, &old_file_handle) < 0) @@ -30,7 +30,7 @@ int __wasilibc_nocwd_renameat(int oldfd, const char *old, int newfd, const char return -1; // Convert the strings into WASI strings - wasip2_string_t old_path, new_path; + wasi_string_t old_path, new_path; if (wasi_string_from_c(old, &old_path) < 0) return -1; if (wasi_string_from_c(new, &new_path) < 0) @@ -47,14 +47,6 @@ int __wasilibc_nocwd_renameat(int oldfd, const char *old, int newfd, const char translate_error(error_code); return -1; } -#elif defined(__wasip3__) - (void) oldfd; - (void) old; - (void) newfd; - (void) new; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unknown WASI version" #endif diff --git a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h index b0925c577..1bc42a1f2 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -586,12 +586,6 @@ typedef struct filesystem_method_descriptor_set_times_at_args { filesystem_new_timestamp_t data_access_timestamp; filesystem_new_timestamp_t data_modification_timestamp; } filesystem_method_descriptor_set_times_at_args_t; -typedef struct filesystem_method_descriptor_rename_at_args { - filesystem_borrow_descriptor_t self; - wasip3_string_t old_path; - filesystem_borrow_descriptor_t new_descriptor; - wasip3_string_t new_path; -} filesystem_method_descriptor_rename_at_args_t; typedef filesystem_own_descriptor_t filesystem_preopens_own_descriptor_t; @@ -1177,7 +1171,7 @@ extern bool filesystem_method_descriptor_remove_directory_at(filesystem_borrow_d // Rename a filesystem object. // // Note: This is similar to `renameat` in POSIX. -extern wasip3_subtask_status_t filesystem_method_descriptor_rename_at(filesystem_method_descriptor_rename_at_args_t *args, filesystem_result_void_error_code_t *result); +extern bool filesystem_method_descriptor_rename_at(filesystem_borrow_descriptor_t self, wasip3_string_t *old_path, filesystem_borrow_descriptor_t new_descriptor, wasip3_string_t *new_path, filesystem_error_code_t *err); // Create a symbolic link (also known as a "symlink"). // // If `old-path` starts with `/`, the function fails with diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index 43554eae4..882683fb6 100644 --- a/libc-bottom-half/sources/wasip3.c +++ b/libc-bottom-half/sources/wasip3.c @@ -130,8 +130,8 @@ extern void __wasm_import_filesystem_method_descriptor_readlink_at(int32_t, uint __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.remove-directory-at"))) extern void __wasm_import_filesystem_method_descriptor_remove_directory_at(int32_t, uint8_t *, size_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.rename-at"))) -extern int32_t __wasm_import_filesystem_method_descriptor_rename_at(uint8_t *, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.rename-at"))) +extern void __wasm_import_filesystem_method_descriptor_rename_at(int32_t, uint8_t *, size_t, int32_t, uint8_t *, size_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.symlink-at"))) extern void __wasm_import_filesystem_method_descriptor_symlink_at(int32_t, uint8_t *, size_t, uint8_t *, size_t, uint8_t *); @@ -1865,8 +1865,29 @@ bool filesystem_method_descriptor_remove_directory_at(filesystem_borrow_descript } } -wasip3_subtask_status_t filesystem_method_descriptor_rename_at(filesystem_method_descriptor_rename_at_args_t *args, filesystem_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_rename_at((uint8_t*) args, (uint8_t*) result); +bool filesystem_method_descriptor_rename_at(filesystem_borrow_descriptor_t self, wasip3_string_t *old_path, filesystem_borrow_descriptor_t new_descriptor, wasip3_string_t *new_path, filesystem_error_code_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_rename_at((self).__handle, (uint8_t *) (*old_path).ptr, (*old_path).len, (new_descriptor).__handle, (uint8_t *) (*new_path).ptr, (*new_path).len, ptr); + filesystem_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } } bool filesystem_method_descriptor_symlink_at(filesystem_borrow_descriptor_t self, wasip3_string_t *old_path, wasip3_string_t *new_path, filesystem_error_code_t *err) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d9aac0bfe..c1206bc62 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -294,7 +294,7 @@ add_wasilibc_test(preadvwritev.c FS FAILP3) add_wasilibc_test(preadwrite.c FS FAILP3) add_wasilibc_test(readlink.c FS) add_wasilibc_test(readv.c FS) -add_wasilibc_test(rename.c FS FAILP3) +add_wasilibc_test(rename.c FS) add_wasilibc_test(rmdir.c FS) add_wasilibc_test(scandir.c FS) add_wasilibc_test(stat.c FS) From a847cab47ac80e6a56b680d510386763c090115f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 27 Feb 2026 17:48:42 -0800 Subject: [PATCH 12/13] wasip3: Get `utime`-related functions working Use the wasip2 implementations --- cmake/bindings.cmake | 2 + .../cloudlibc/src/libc/sys/stat/futimens.c | 8 +- .../cloudlibc/src/libc/sys/stat/utimensat.c | 12 +- .../headers/public/wasi/__generated_wasip3.h | 16 +- libc-bottom-half/sources/wasip3.c | 154 +++++++++++++++++- test/CMakeLists.txt | 2 +- 6 files changed, 154 insertions(+), 40 deletions(-) diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index 4702b15d9..56cecf973 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -128,6 +128,8 @@ add_custom_target( "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.link-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.readlink-at" "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.rename-at" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.set-times-at" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.set-times" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-until" "--async=-wasi:clocks/monotonic-clock@${wasip3-version}#wait-for" ${CMAKE_SOURCE_DIR}/wasi/p3/wit diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/stat/futimens.c b/libc-bottom-half/cloudlibc/src/libc/sys/stat/futimens.c index 4311cf36d..ac1daea06 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/futimens.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/futimens.c @@ -29,7 +29,7 @@ int futimens(int fd, const struct timespec *times) { errno = error; return -1; } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal handle filesystem_borrow_descriptor_t file_handle; if (fd_to_file_handle(fd, &file_handle) < 0) @@ -52,12 +52,6 @@ int futimens(int fd, const struct timespec *times) { translate_error(error); return -1; } -#elif defined(__wasip3__) - (void) fd; - (void) times; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c b/libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c index 4be2d0a1e..4b270b5fe 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c @@ -38,7 +38,7 @@ int __wasilibc_nocwd_utimensat(int fd, const char *path, const struct timespec t errno = error; return -1; } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Translate the file descriptor to an internal handle filesystem_borrow_descriptor_t file_handle; if (fd_to_file_handle(fd, &file_handle) < 0) @@ -58,7 +58,7 @@ int __wasilibc_nocwd_utimensat(int fd, const char *path, const struct timespec t lookup_flags |= FILESYSTEM_PATH_FLAGS_SYMLINK_FOLLOW; // Convert the string into a Wasm string - wasip2_string_t path_wasm_string; + wasi_string_t path_wasm_string; if (wasi_string_from_c(path, &path_wasm_string) < 0) return -1; @@ -74,14 +74,6 @@ int __wasilibc_nocwd_utimensat(int fd, const char *path, const struct timespec t translate_error(error); return -1; } -#elif defined(__wasip3__) - (void) fd; - (void) path; - (void) times; - (void) flag; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h index 1bc42a1f2..b956e3e48 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -574,18 +574,6 @@ typedef struct { filesystem_error_code_t err; } val; } filesystem_result_metadata_hash_value_error_code_t; -typedef struct filesystem_method_descriptor_set_times_args { - filesystem_borrow_descriptor_t self; - filesystem_new_timestamp_t data_access_timestamp; - filesystem_new_timestamp_t data_modification_timestamp; -} filesystem_method_descriptor_set_times_args_t; -typedef struct filesystem_method_descriptor_set_times_at_args { - filesystem_borrow_descriptor_t self; - filesystem_path_flags_t path_flags; - wasip3_string_t path; - filesystem_new_timestamp_t data_access_timestamp; - filesystem_new_timestamp_t data_modification_timestamp; -} filesystem_method_descriptor_set_times_at_args_t; typedef filesystem_own_descriptor_t filesystem_preopens_own_descriptor_t; @@ -1084,7 +1072,7 @@ extern bool filesystem_method_descriptor_set_size(filesystem_borrow_descriptor_t // Note: This is similar to `futimens` in POSIX. // // Note: This was called `fd_filestat_set_times` in earlier versions of WASI. -extern wasip3_subtask_status_t filesystem_method_descriptor_set_times(filesystem_method_descriptor_set_times_args_t *args, filesystem_result_void_error_code_t *result); +extern bool filesystem_method_descriptor_set_times(filesystem_borrow_descriptor_t self, filesystem_new_timestamp_t *data_access_timestamp, filesystem_new_timestamp_t *data_modification_timestamp, filesystem_error_code_t *err); // Read directory entries from a directory. // // On filesystems where directories contain entries referring to themselves @@ -1133,7 +1121,7 @@ extern bool filesystem_method_descriptor_stat_at(filesystem_borrow_descriptor_t // // Note: This was called `path_filestat_set_times` in earlier versions of // WASI. -extern wasip3_subtask_status_t filesystem_method_descriptor_set_times_at(filesystem_method_descriptor_set_times_at_args_t *args, filesystem_result_void_error_code_t *result); +extern bool filesystem_method_descriptor_set_times_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t path_flags, wasip3_string_t *path, filesystem_new_timestamp_t *data_access_timestamp, filesystem_new_timestamp_t *data_modification_timestamp, filesystem_error_code_t *err); // Create a hard link. // // Fails with `error-code::no-entry` if the old path does not exist, diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index 882683fb6..6dc0f9521 100644 --- a/libc-bottom-half/sources/wasip3.c +++ b/libc-bottom-half/sources/wasip3.c @@ -97,8 +97,8 @@ extern int32_t __wasm_import_filesystem_method_descriptor_get_type(int32_t, uint __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.set-size"))) extern void __wasm_import_filesystem_method_descriptor_set_size(int32_t, int64_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.set-times"))) -extern int32_t __wasm_import_filesystem_method_descriptor_set_times(uint8_t *, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.set-times"))) +extern void __wasm_import_filesystem_method_descriptor_set_times(int32_t, int32_t, int64_t, int32_t, int32_t, int64_t, int32_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.read-directory"))) extern void __wasm_import_filesystem_method_descriptor_read_directory(int32_t, uint8_t *); @@ -115,8 +115,8 @@ extern void __wasm_import_filesystem_method_descriptor_stat(int32_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.stat-at"))) extern void __wasm_import_filesystem_method_descriptor_stat_at(int32_t, int32_t, uint8_t *, size_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.set-times-at"))) -extern int32_t __wasm_import_filesystem_method_descriptor_set_times_at(uint8_t *, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.set-times-at"))) +extern void __wasm_import_filesystem_method_descriptor_set_times_at(int32_t, int32_t, uint8_t *, size_t, int32_t, int64_t, int32_t, int32_t, int64_t, int32_t, uint8_t *); __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.link-at"))) extern void __wasm_import_filesystem_method_descriptor_link_at(int32_t, int32_t, uint8_t *, size_t, int32_t, uint8_t *, size_t, uint8_t *); @@ -1532,8 +1532,77 @@ bool filesystem_method_descriptor_set_size(filesystem_borrow_descriptor_t self, } } -wasip3_subtask_status_t filesystem_method_descriptor_set_times(filesystem_method_descriptor_set_times_args_t *args, filesystem_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_set_times((uint8_t*) args, (uint8_t*) result); +bool filesystem_method_descriptor_set_times(filesystem_borrow_descriptor_t self, filesystem_new_timestamp_t *data_access_timestamp, filesystem_new_timestamp_t *data_modification_timestamp, filesystem_error_code_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + int32_t variant; + int64_t variant2; + int32_t variant3; + switch ((int32_t) (*data_access_timestamp).tag) { + case 0: { + variant = 0; + variant2 = 0; + variant3 = 0; + break; + } + case 1: { + variant = 1; + variant2 = 0; + variant3 = 0; + break; + } + case 2: { + const filesystem_instant_t *payload1 = &(*data_access_timestamp).val.timestamp; + variant = 2; + variant2 = (*payload1).seconds; + variant3 = (int32_t) ((*payload1).nanoseconds); + break; + } + } + int32_t variant7; + int64_t variant8; + int32_t variant9; + switch ((int32_t) (*data_modification_timestamp).tag) { + case 0: { + variant7 = 0; + variant8 = 0; + variant9 = 0; + break; + } + case 1: { + variant7 = 1; + variant8 = 0; + variant9 = 0; + break; + } + case 2: { + const filesystem_instant_t *payload6 = &(*data_modification_timestamp).val.timestamp; + variant7 = 2; + variant8 = (*payload6).seconds; + variant9 = (int32_t) ((*payload6).nanoseconds); + break; + } + } + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_set_times((self).__handle, variant, variant2, variant3, variant7, variant8, variant9, ptr); + filesystem_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } } void filesystem_method_descriptor_read_directory(filesystem_borrow_descriptor_t self, filesystem_tuple2_stream_directory_entry_future_result_void_error_code_t *ret) { @@ -1757,8 +1826,77 @@ bool filesystem_method_descriptor_stat_at(filesystem_borrow_descriptor_t self, f } } -wasip3_subtask_status_t filesystem_method_descriptor_set_times_at(filesystem_method_descriptor_set_times_at_args_t *args, filesystem_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_set_times_at((uint8_t*) args, (uint8_t*) result); +bool filesystem_method_descriptor_set_times_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t path_flags, wasip3_string_t *path, filesystem_new_timestamp_t *data_access_timestamp, filesystem_new_timestamp_t *data_modification_timestamp, filesystem_error_code_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + int32_t variant; + int64_t variant2; + int32_t variant3; + switch ((int32_t) (*data_access_timestamp).tag) { + case 0: { + variant = 0; + variant2 = 0; + variant3 = 0; + break; + } + case 1: { + variant = 1; + variant2 = 0; + variant3 = 0; + break; + } + case 2: { + const filesystem_instant_t *payload1 = &(*data_access_timestamp).val.timestamp; + variant = 2; + variant2 = (*payload1).seconds; + variant3 = (int32_t) ((*payload1).nanoseconds); + break; + } + } + int32_t variant7; + int64_t variant8; + int32_t variant9; + switch ((int32_t) (*data_modification_timestamp).tag) { + case 0: { + variant7 = 0; + variant8 = 0; + variant9 = 0; + break; + } + case 1: { + variant7 = 1; + variant8 = 0; + variant9 = 0; + break; + } + case 2: { + const filesystem_instant_t *payload6 = &(*data_modification_timestamp).val.timestamp; + variant7 = 2; + variant8 = (*payload6).seconds; + variant9 = (int32_t) ((*payload6).nanoseconds); + break; + } + } + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_set_times_at((self).__handle, path_flags, (uint8_t *) (*path).ptr, (*path).len, variant, variant2, variant3, variant7, variant8, variant9, ptr); + filesystem_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } } bool filesystem_method_descriptor_link_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t old_path_flags, wasip3_string_t *old_path, filesystem_borrow_descriptor_t new_descriptor, wasip3_string_t *new_path, filesystem_error_code_t *err) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c1206bc62..6281bf93e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -307,7 +307,7 @@ add_wasilibc_test(time_and_times.c CFLAGS -D_WASI_EMULATED_PROCESS_CLOCKS LDFLAGS -lwasi-emulated-process-clocks) add_wasilibc_test(time.c) -add_wasilibc_test(utime.c FS FAILP3) +add_wasilibc_test(utime.c FS) add_wasilibc_test(rewinddir.c FS FAILP3) add_wasilibc_test(seekdir.c FS) add_wasilibc_test(usleep.c) From 8d28ae53ebc2955e6b8bdb19f908ff919900fec0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 2 Mar 2026 18:07:20 -0800 Subject: [PATCH 13/13] wasip3: Fix `rewinddir` test and reading a finished stream Don't re-read a stream once its termination has been received. --- .../cloudlibc/src/libc/dirent/dirent_impl.h | 2 ++ .../cloudlibc/src/libc/dirent/fdopendir.c | 1 + .../cloudlibc/src/libc/dirent/readdir.c | 15 +++++++++------ test/CMakeLists.txt | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/libc-bottom-half/cloudlibc/src/libc/dirent/dirent_impl.h b/libc-bottom-half/cloudlibc/src/libc/dirent/dirent_impl.h index 7febd3112..c125dfd08 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/dirent_impl.h +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/dirent_impl.h @@ -29,6 +29,7 @@ struct _DIR { size_t offset; #elif defined(__wasip3__) filesystem_tuple2_stream_directory_entry_future_result_void_error_code_t stream; + bool stream_done; size_t skip; size_t offset; #else @@ -53,6 +54,7 @@ static inline void dirent_close_streams(DIR *dirp) { if (dirp->stream.f0 != 0) { filesystem_stream_directory_entry_drop_readable(dirp->stream.f0); dirp->stream.f0 = 0; + dirp->stream_done = false; } if (dirp->stream.f1 != 0) { filesystem_future_result_void_error_code_drop_readable(dirp->stream.f1); diff --git a/libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c b/libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c index edd0476fd..40bec050d 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c @@ -73,6 +73,7 @@ DIR *fdopendir(int fd) { dirp->stream = result; #elif defined(__wasip3__) filesystem_method_descriptor_read_directory(file_handle, &dirp->stream); + dirp->stream_done = false; #endif dirp->fd = fd; dirp->skip = 0; diff --git a/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c b/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c index 96d379d3b..55c182462 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c @@ -234,21 +234,24 @@ static struct dirent *readdir_next(DIR *dirp) { #elif defined(__wasip3__) filesystem_directory_entry_t dir_entry; + // Don't try to keep reading once the stream is closed. + if (dirp->stream_done) + return NULL; + // Loop until at least one stream entry is read, or until the stream is closed. - bool closed = false; - while (1) { + while (!dirp->stream_done) { size_t amount = __wasilibc_stream_block_on( filesystem_stream_directory_entry_read(dirp->stream.f0, &dir_entry, 1), dirp->stream.f0, - &closed); + &dirp->stream_done); // If something was read, then break out and process that below. if (amount > 0) break; // If nothing was read and the stream isn't finished yet, try again. - if (!closed) + if (!dirp->stream_done) continue; // If the stream's result future hasn't been read yet, do so here. @@ -263,8 +266,8 @@ static struct dirent *readdir_next(DIR *dirp) { translate_error(result.val.err); } - // The stream is closed, so return NULL. This'll set `errno` based on the - // result of the future above. + // The stream is closed, so return NULL. If `errno` needs to be set it'll + // have been done above with `f1`. return NULL; } #else diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6281bf93e..d576060ba 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -308,7 +308,7 @@ add_wasilibc_test(time_and_times.c LDFLAGS -lwasi-emulated-process-clocks) add_wasilibc_test(time.c) add_wasilibc_test(utime.c FS) -add_wasilibc_test(rewinddir.c FS FAILP3) +add_wasilibc_test(rewinddir.c FS) add_wasilibc_test(seekdir.c FS) add_wasilibc_test(usleep.c) add_wasilibc_test(nanosleep.c)