diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index ed1236ec0..56cecf973 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -107,6 +107,31 @@ add_custom_target( --rename wasi:cli/terminal-stdin@${wasip3-version}=terminal_stdin --rename wasi:cli/terminal-stdout@${wasip3-version}=terminal_stdout --rename wasi:cli/terminal-stderr@${wasip3-version}=terminal_stderr + + # Disable async bindings generation for some functions which are only + # ever called synchronously within libc. + "--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.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: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: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 COMMAND cmake -E copy wasip3.h ${bottom_half}/headers/public/wasi/__generated_wasip3.h COMMAND cmake -E copy wasip3_component_type.o ${bottom_half}/sources diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index d84358fe9..9996fa30a 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -1494,6 +1494,7 @@ vwprintf vwscanf wall_clock_now wall_clock_resolution +wasi_string_from_c wasip2_list_string_free wasip2_list_tuple2_string_string_free wasip2_list_u32_free @@ -1502,7 +1503,6 @@ wasip2_option_string_free wasip2_string_dup wasip2_string_dup_n wasip2_string_free -wasip2_string_from_c wasip2_string_set wasip2_tuple2_string_string_free wcpcpy diff --git a/expected/wasm32-wasip3/defined-symbols.txt b/expected/wasm32-wasip3/defined-symbols.txt index 02a9aafa9..7596f452f 100644 --- a/expected/wasm32-wasip3/defined-symbols.txt +++ b/expected/wasm32-wasip3/defined-symbols.txt @@ -331,7 +331,7 @@ __wasilibc_parse_port __wasilibc_populate_preopens __wasilibc_pthread_self __wasilibc_random -__wasilibc_read_stream3 +__wasilibc_read __wasilibc_rename_newat __wasilibc_rename_oldat __wasilibc_reset_preopens @@ -345,7 +345,7 @@ __wasilibc_unspecified_addr __wasilibc_utimens __wasilibc_wasi_family_to_libc __wasilibc_wasi_to_sockaddr -__wasilibc_write_stream3 +__wasilibc_write __wasm_call_dtors __wcscoll_l __wcsftime_l @@ -1463,21 +1463,25 @@ vswprintf vswscanf vwprintf vwscanf +wasi_string_from_c wasip3_backpressure_dec wasip3_backpressure_inc wasip3_context_get_0 wasip3_context_get_1 wasip3_context_set_0 wasip3_context_set_1 +wasip3_future_block_on wasip3_list_string_free wasip3_list_tuple2_string_string_free wasip3_list_u8_free wasip3_option_string_free +wasip3_stream_block_on wasip3_string_dup wasip3_string_dup_n wasip3_string_free wasip3_string_set wasip3_subtask_block_on +wasip3_subtask_block_on_and_drop wasip3_subtask_cancel wasip3_subtask_drop wasip3_task_cancel @@ -1495,7 +1499,6 @@ wasip3_thread_yield_cancellable wasip3_thread_yield_to_suspended wasip3_thread_yield_to_suspended_cancellable wasip3_tuple2_string_string_free -wasip3_waitable_block_on wasip3_waitable_join wasip3_waitable_set_drop wasip3_waitable_set_new diff --git a/libc-bottom-half/CMakeLists.txt b/libc-bottom-half/CMakeLists.txt index 65012cb03..5cd333930 100644 --- a/libc-bottom-half/CMakeLists.txt +++ b/libc-bottom-half/CMakeLists.txt @@ -139,6 +139,8 @@ else() sources/descriptor_table.c sources/getsockpeername.c sources/listen.c + sources/file_utils.c + sources/file.c sources/recv.c sources/send.c sources/shutdown.c @@ -154,8 +156,6 @@ if(WASI STREQUAL "p2") list(APPEND bottom_half_sources sources/netdb.c sources/wasip2.c - sources/wasip2_file.c - sources/wasip2_file_utils.c sources/wasip2_stdio.c ) endif() @@ -164,8 +164,6 @@ if (WASI STREQUAL "p3") list(APPEND bottom_half_sources sources/wasip3.c sources/wasip3_block_on.c - sources/wasip3_file.c - sources/wasip3_file_utils.c sources/wasip3_stdio.c ) endif() 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 a76205e58..18675a027 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/dirent_impl.h +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/dirent_impl.h @@ -28,7 +28,8 @@ struct _DIR { size_t skip; size_t offset; #elif defined(__wasip3__) - filesystem_stream_directory_entry_t stream; + filesystem_tuple2_stream_directory_entry_future_result_void_error_code_t stream; + bool stream_done; size_t skip; size_t offset; #else @@ -40,4 +41,27 @@ struct _DIR { size_t dirent_size; }; +static inline void dirent_close_streams(DIR *dirp) { +#if defined(__wasip1__) + // nothing to close ... +#elif defined(__wasip2__) + if (dirp->stream.__handle) { + filesystem_directory_entry_stream_drop_own(dirp->stream); + dirp->stream.__handle = 0; + } +#elif defined(__wasip3__) + 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); + dirp->stream.f1 = 0; + } +#else +# error "Unknown WASI version" +#endif +} + #endif diff --git a/libc-bottom-half/cloudlibc/src/libc/dirent/fdclosedir.c b/libc-bottom-half/cloudlibc/src/libc/dirent/fdclosedir.c index c4fc4c434..03765388f 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/fdclosedir.c +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/fdclosedir.c @@ -9,17 +9,10 @@ int fdclosedir(DIR *dirp) { int fd = dirp->fd; -#if defined(__wasip1__) +#ifdef __wasip1__ free(dirp->buffer); -#elif defined(__wasip2__) - if (dirp->stream.__handle != 0) - filesystem_directory_entry_stream_drop_own(dirp->stream); -#elif defined(__wasip3__) - if (dirp->stream != 0) - filesystem_stream_directory_entry_drop_readable(dirp->stream); -#else -# error "Unsupported WASI version" #endif + dirent_close_streams(dirp); free(dirp->dirent); free(dirp); return fd; diff --git a/libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c b/libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c index 03dd1138d..40bec050d 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c @@ -49,7 +49,7 @@ DIR *fdopendir(int fd) { dirp->dirent = NULL; dirp->dirent_size = 1; return dirp; -#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,6 +58,7 @@ DIR *fdopendir(int fd) { } // Read the directory +#if defined(__wasip2__) filesystem_own_directory_entry_stream_t result; filesystem_error_code_t error_code; bool ok = filesystem_method_descriptor_read_directory(file_handle, @@ -69,19 +70,17 @@ DIR *fdopendir(int fd) { return NULL; } - dirp->fd = 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; dirp->offset = 0; dirp->dirent = NULL; dirp->dirent_size = 1; return dirp; -#elif defined(__wasip3__) - (void) fd; - // TODO(wasip3) - errno = ENOTSUP; - free(dirp); - return NULL; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c b/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c index 82b94613a..0d0d1b460 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c @@ -31,8 +31,11 @@ static_assert(DT_REG == __WASI_FILETYPE_REGULAR_FILE, "Value mismatch"); static_assert(DT_UNKNOWN == __WASI_FILETYPE_UNKNOWN, "Value mismatch"); #endif +#ifdef __wasip3__ +#include +#endif + // Grows a buffer to be large enough to hold a certain amount of data. -#ifndef __wasip3__ static struct dirent* grow(struct dirent **buffer, size_t *buffer_size, size_t target_size) { if (*buffer_size < target_size) { size_t new_size = *buffer_size; @@ -48,7 +51,6 @@ static struct dirent* grow(struct dirent **buffer, size_t *buffer_size, size_t t } return *buffer; } -#endif #if defined(__wasip1__) struct dirent *readdir(DIR *dirp) { @@ -144,12 +146,13 @@ struct dirent *readdir(DIR *dirp) { } } -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) static int ensure_has_directory_stream(DIR *dirp, filesystem_borrow_descriptor_t *handle) { if (fd_to_file_handle(dirp->fd, handle) < 0) return -1; +#ifdef __wasip2__ if (dirp->stream.__handle != 0) return 0; @@ -161,10 +164,15 @@ static int ensure_has_directory_stream(DIR *dirp, filesystem_borrow_descriptor_t translate_error(error_code); return -1; } +#elif defined(__wasip3__) + if (dirp->stream.f0 == 0) + filesystem_method_descriptor_read_directory(*handle, &dirp->stream); +#endif return 0; } static struct dirent *readdir_next(DIR *dirp) { + bool ok; filesystem_metadata_hash_value_t metadata; filesystem_error_code_t error_code; filesystem_borrow_descriptor_t dir_handle; @@ -178,9 +186,9 @@ static struct dirent *readdir_next(DIR *dirp) { dirp->offset += 1; if (grow(&dirp->dirent, &dirp->dirent_size, offsetof(struct dirent, d_name) + 2) == NULL) return NULL; - bool ok = filesystem_method_descriptor_metadata_hash(dir_handle, - &metadata, - &error_code); + ok = filesystem_method_descriptor_metadata_hash(dir_handle, + &metadata, + &error_code); if (!ok) { translate_error(error_code); return NULL; @@ -206,11 +214,12 @@ static struct dirent *readdir_next(DIR *dirp) { return dirp->dirent; } +#if defined(__wasip2__) filesystem_borrow_directory_entry_stream_t stream = filesystem_borrow_directory_entry_stream(dirp->stream); filesystem_option_directory_entry_t dir_entry_optional; - bool ok = filesystem_method_directory_entry_stream_read_directory_entry(stream, - &dir_entry_optional, - &error_code); + ok = filesystem_method_directory_entry_stream_read_directory_entry(stream, + &dir_entry_optional, + &error_code); if (!ok) { translate_error(error_code); return NULL; @@ -222,10 +231,57 @@ static struct dirent *readdir_next(DIR *dirp) { filesystem_directory_entry_t dir_entry = dir_entry_optional.val; +#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. + while (!dirp->stream_done) { + size_t amount = + wasip3_stream_block_on( + filesystem_stream_directory_entry_read(dirp->stream.f0, &dir_entry, 1), + dirp->stream.f0, + &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 (!dirp->stream_done) + continue; + + // If the stream's result future hasn't been read yet, do so here. + if (dirp->stream.f1) { + filesystem_result_void_error_code_t result; + wasip3_future_block_on( + filesystem_future_result_void_error_code_read(dirp->stream.f1, &result), + dirp->stream.f1); + filesystem_future_result_void_error_code_drop_readable(dirp->stream.f1); + dirp->stream.f1 = 0; + if (result.is_err) + translate_error(result.val.err); + } + + // The stream is closed, so return NULL. If `errno` needs to be set it'll + // have been done above with `f1`. + return NULL; + } +#else +#error "Unknown WASI version" +#endif + // Ensure that the dirent is large enough to fit the filename size_t the_size = offsetof(struct dirent, d_name); if (grow(&dirp->dirent, &dirp->dirent_size, the_size + dir_entry.name.len + 1) == NULL) { +#ifdef __wasip2__ wasip2_string_free(&dir_entry.name); +#else + wasip3_string_free(&dir_entry.name); +#endif return NULL; } @@ -241,7 +297,11 @@ static struct dirent *readdir_next(DIR *dirp) { &dir_entry.name, &metadata, &error_code); +#ifdef __wasip2__ wasip2_string_free(&dir_entry.name); +#else + wasip3_string_free(&dir_entry.name); +#endif if (!ok) { translate_error(error_code); return NULL; @@ -260,13 +320,6 @@ struct dirent *readdir(DIR *dirp) { } return result; } -#elif defined(__wasip3__) -struct dirent *readdir(DIR *dirp) { - // TODO(wasip3) - errno = ENOTSUP; - free(dirp); - return NULL; -} #else # error "Unknown WASI version" #endif diff --git a/libc-bottom-half/cloudlibc/src/libc/dirent/rewinddir.c b/libc-bottom-half/cloudlibc/src/libc/dirent/rewinddir.c index e92b143e5..97d6dc427 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/rewinddir.c +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/rewinddir.c @@ -13,12 +13,8 @@ void rewinddir(DIR *dirp) { dirp->cookie = __WASI_DIRCOOKIE_START; // Mark entire buffer as processed to force a read of new data. dirp->buffer_used = dirp->buffer_processed = dirp->buffer_size; -#elif defined(__wasip2__) - dirp->stream.__handle = 0; - dirp->skip = 0; - dirp->offset = 0; -#elif defined(__wasip3__) - dirp->stream = 0; +#elif defined(__wasip2__) || defined(__wasip3__) + dirent_close_streams(dirp); dirp->skip = 0; dirp->offset = 0; #else diff --git a/libc-bottom-half/cloudlibc/src/libc/dirent/seekdir.c b/libc-bottom-half/cloudlibc/src/libc/dirent/seekdir.c index 80f76abdf..b87d079b0 100644 --- a/libc-bottom-half/cloudlibc/src/libc/dirent/seekdir.c +++ b/libc-bottom-half/cloudlibc/src/libc/dirent/seekdir.c @@ -13,12 +13,8 @@ void seekdir(DIR *dirp, long loc) { // Mark entire buffer as processed to force a read of new data. // TODO(ed): We could prevent a read if the offset is in the buffer. dirp->buffer_used = dirp->buffer_processed = dirp->buffer_size; -#elif defined(__wasip2__) - dirp->stream.__handle = 0; - dirp->skip = loc; - dirp->offset = 0; -#elif defined(__wasip3__) - dirp->stream = 0; +#elif defined(__wasip2__) || defined(__wasip3__) + dirent_close_streams(dirp); dirp->skip = loc; dirp->offset = 0; #else diff --git a/libc-bottom-half/cloudlibc/src/libc/fcntl/openat.c b/libc-bottom-half/cloudlibc/src/libc/fcntl/openat.c index 418898542..9762263aa 100644 --- a/libc-bottom-half/cloudlibc/src/libc/fcntl/openat.c +++ b/libc-bottom-half/cloudlibc/src/libc/fcntl/openat.c @@ -87,7 +87,7 @@ int __wasilibc_nocwd_openat_nomode(int fd, const char *path, int oflag) { return -1; } return newfd; -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Set up path flags filesystem_path_flags_t lookup_flags = 0; if ((oflag & O_NOFOLLOW) == 0) @@ -140,8 +140,8 @@ int __wasilibc_nocwd_openat_nomode(int fd, const char *path, int oflag) { return -1; // Construct a WASI string for the path - wasip2_string_t path2; - if (wasip2_string_from_c(path, &path2) < 0) + wasi_string_t wasi_path; + if (wasi_string_from_c(path, &wasi_path) < 0) return -1; // Open the file, yielding a new handle @@ -149,7 +149,7 @@ int __wasilibc_nocwd_openat_nomode(int fd, const char *path, int oflag) { filesystem_error_code_t error_code; bool ok = filesystem_method_descriptor_open_at(file_handle, lookup_flags, - &path2, + &wasi_path, open_flags, fs_flags, &new_handle, @@ -161,13 +161,6 @@ int __wasilibc_nocwd_openat_nomode(int fd, const char *path, int oflag) { // Update the descriptor table with the new handle return __wasilibc_add_file(new_handle, oflag); -#elif defined(__wasip3__) - (void) fd; - (void) path; - (void) oflag; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unsupported WASI version" #endif 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/cloudlibc/src/libc/poll/poll.c b/libc-bottom-half/cloudlibc/src/libc/poll/poll.c index 95ec03561..796f97c4b 100644 --- a/libc-bottom-half/cloudlibc/src/libc/poll/poll.c +++ b/libc-bottom-half/cloudlibc/src/libc/poll/poll.c @@ -216,7 +216,7 @@ static int poll_impl(struct pollfd *fds, size_t nfds, int timeout) { if (pollfd->events & POLLRDNORM) { if (entry->vtable->get_read_stream) { - wasip2_read_t read; + wasi_read_t read; if (entry->vtable->get_read_stream(entry->data, &read) < 0) return -1; if (__wasilibc_poll_add_input_stream(&state, read.input, read.pollable) < 0) @@ -229,7 +229,7 @@ static int poll_impl(struct pollfd *fds, size_t nfds, int timeout) { if (pollfd->events & POLLWRNORM) { if (entry->vtable->get_write_stream) { - wasip2_write_t write; + wasi_write_t write; if (entry->vtable->get_write_stream(entry->data, &write) < 0) return -1; if (__wasilibc_poll_add_output_stream(&state, write.output, write.pollable) < 0) diff --git a/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c b/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c index c2b4801d6..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,10 +30,10 @@ 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; - if (wasip2_string_from_c(old, &old_path) < 0) + wasi_string_t old_path, new_path; + if (wasi_string_from_c(old, &old_path) < 0) return -1; - if (wasip2_string_from_c(new, &new_path) < 0) + if (wasi_string_from_c(new, &new_path) < 0) return -1; // Rename the file @@ -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/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 cdc97959b..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,15 +35,15 @@ 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; - if (wasip2_string_from_c(path, &path_wasm_string) < 0) + wasi_string_t path_wasm_string; + if (wasi_string_from_c(path, &path_wasm_string) < 0) return -1; // Get the metadata hash for this file @@ -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/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/mkdirat.c b/libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c index b1f177849..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,8 +29,8 @@ int __wasilibc_nocwd_mkdirat_nomode(int fd, const char *path) { // Create the directory filesystem_error_code_t error; - wasip2_string_t path2; - if (wasip2_string_from_c(path, &path2) < 0) + wasi_string_t path2; + if (wasi_string_from_c(path, &path2) < 0) return -1; bool ok = filesystem_method_descriptor_create_directory_at(file_handle, &path2, @@ -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/cloudlibc/src/libc/sys/stat/utimensat.c b/libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c index 53f5b06f5..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,8 +58,8 @@ 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; - if (wasip2_string_from_c(path, &path_wasm_string) < 0) + wasi_string_t path_wasm_string; + if (wasi_string_from_c(path, &path_wasm_string) < 0) return -1; // Perform system call. @@ -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/cloudlibc/src/libc/time/clock_nanosleep.c b/libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c index 9c72d59ee..d868b542d 100644 --- a/libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c +++ b/libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c @@ -8,9 +8,6 @@ #include #include #include -#ifdef __wasip3__ -#include -#endif #ifdef __wasip1__ static_assert(TIMER_ABSTIME == __WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME, @@ -61,13 +58,11 @@ int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, poll_pollable_drop_own(pollable); #else // defined(__wasip3__) - wasip3_subtask_status_t status; if (flags & TIMER_ABSTIME) { - status = monotonic_clock_wait_until(duration); + monotonic_clock_wait_until(duration); } else { - status = monotonic_clock_wait_for(duration); + monotonic_clock_wait_for(duration); } - wasip3_subtask_block_on(status); #endif return 0; diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c index 5a6b93a4b..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,8 +63,8 @@ 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; - if (wasip2_string_from_c(path, &wasi_path) < 0) + wasi_string_t wasi_path; + if (wasi_string_from_c(path, &wasi_path) < 0) return -1; // Call stat() to check if the file exists @@ -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/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/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/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/cloudlibc/src/libc/unistd/linkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c index 8d1184768..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,10 +35,10 @@ 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; - if (wasip2_string_from_c(path1, &path1_wasi) < 0) + wasi_string_t path1_wasi, path2_wasi; + if (wasi_string_from_c(path1, &path1_wasi) < 0) return -1; - if (wasip2_string_from_c(path2, &path2_wasi) < 0) + if (wasi_string_from_c(path2, &path2_wasi) < 0) return -1; // Create the link @@ -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/cloudlibc/src/libc/unistd/lseek.c b/libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c index c9a6e3d0f..1305686a5 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c @@ -29,7 +29,7 @@ off_t __lseek(int fildes, off_t offset, int whence) { return -1; } return new_offset; -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Look up a stream for fildes descriptor_table_entry_t *entry = descriptor_table_get_ref(fildes); if (!entry) @@ -39,13 +39,6 @@ off_t __lseek(int fildes, off_t offset, int whence) { return -1; } return entry->vtable->seek(entry->data, offset, whence); -#elif defined(__wasip3__) - (void) fildes; - (void) offset; - (void) whence; - // TODO(wasip3) - errno = ENOTSUP; - return -1; #else # error "Unknown WASI version" #endif diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/pread.c b/libc-bottom-half/cloudlibc/src/libc/unistd/pread.c index 8a501889e..b427a164d 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/pread.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/pread.c @@ -12,6 +12,10 @@ #include #endif +#ifdef __wasip3__ +#include +#endif + ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset) { if (offset < 0) { errno = EINVAL; @@ -66,12 +70,38 @@ ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset) { return bytes_read; #elif defined(__wasip3__) - (void) fildes; - (void) buf; - (void) nbyte; - // TODO(wasip3) - errno = ENOTSUP; - return -1; + filesystem_borrow_descriptor_t file_handle; + if (fd_to_file_handle(fildes, &file_handle) < 0) + return -1; + + // Use `read-via-stream` to acquire a stream of data at this specified file + // offset, then issue a read and wait for it to finish. + filesystem_tuple2_stream_u8_future_result_void_error_code_t io; + filesystem_method_descriptor_read_via_stream(file_handle, offset, &io); + bool closed; + size_t ret = wasip3_stream_block_on( + filesystem_stream_u8_read(io.f0, buf, nbyte), + io.f0, + &closed); + filesystem_stream_u8_drop_readable(io.f0); + + // If zero bytes were written then read the provided future to see + // what happened. Otherwise close the future as we won't be reading the + // result. + if (ret == 0) { + filesystem_result_void_error_code_t result; + wasip3_future_block_on( + filesystem_future_result_void_error_code_read(io.f1, &result), + io.f1); + filesystem_future_result_void_error_code_drop_readable(io.f1); + if (result.is_err) { + translate_error(result.val.err); + return -1; + } + } else { + filesystem_future_result_void_error_code_drop_readable(io.f1); + } + return ret; #else # error "Unknown WASI version" #endif diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/pwrite.c b/libc-bottom-half/cloudlibc/src/libc/unistd/pwrite.c index 53dc39f6f..02c07cd2e 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/pwrite.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/pwrite.c @@ -11,6 +11,10 @@ #include #endif +#ifdef __wasip3__ +#include +#endif + ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) { if (offset < 0) { errno = EINVAL; @@ -62,12 +66,34 @@ ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) { return bytes_written; #elif defined(__wasip3__) - (void) fildes; - (void) buf; - (void) nbyte; - // TODO(wasip3) - errno = ENOTSUP; - return -1; + filesystem_borrow_descriptor_t file_handle; + if (fd_to_file_handle(fildes, &file_handle) < 0) + return -1; + + // Create a read/write stream, use `write-via-stream` to start writing, + // then perform the write to see how much was accepted. + filesystem_stream_u8_writer_t writer; + filesystem_stream_u8_t reader = filesystem_stream_u8_new(&writer); + filesystem_result_void_error_code_t result; + wasip3_subtask_status_t subtask_status = + filesystem_method_descriptor_write_via_stream(file_handle, reader, offset, &result); + bool closed; + size_t ret = wasip3_stream_block_on( + filesystem_stream_u8_write(writer, buf, nbyte), + writer, + &closed); + filesystem_stream_u8_drop_writable(writer); + + // Wait for the subtask to resolve now that the writer half is closed and if + // we failed to write bytes (0 bytes written) and the result is an error we + // can return -1. + if (WASIP3_SUBTASK_STATE(subtask_status) != WASIP3_SUBTASK_RETURNED) + wasip3_subtask_block_on_and_drop(WASIP3_SUBTASK_HANDLE(subtask_status)); + if (ret == 0 && result.is_err) { + translate_error(result.val.err); + return -1; + } + return ret; #else # error "Unsupported WASI version" #endif diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/read.c b/libc-bottom-half/cloudlibc/src/libc/unistd/read.c index 12db46717..d2f43e14f 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/read.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/read.c @@ -13,10 +13,6 @@ #include #endif -#ifdef __wasip3__ -#include -#endif - ssize_t read(int fildes, void *buf, size_t nbyte) { #if defined(__wasip1__) __wasi_iovec_t iov = {.buf = buf, .buf_len = nbyte}; @@ -27,12 +23,12 @@ ssize_t read(int fildes, void *buf, size_t nbyte) { return -1; } return bytes_read; -#elif defined(__wasip2__) +#else descriptor_table_entry_t *entry = descriptor_table_get_ref(fildes); if (!entry) return -1; if (entry->vtable->get_read_stream) { - wasip2_read_t read; + wasi_read_t read; if (entry->vtable->get_read_stream(entry->data, &read) < 0) return -1; return __wasilibc_read(&read, buf, nbyte); @@ -41,30 +37,5 @@ ssize_t read(int fildes, void *buf, size_t nbyte) { return entry->vtable->recvfrom(entry->data, buf, nbyte, 0, NULL, NULL); errno = EOPNOTSUPP; return -1; -#elif defined(__wasip3__) - filesystem_tuple2_stream_u8_future_result_void_error_code_t *stream; - off_t *off; - if (__wasilibc_read_stream3(fildes, &stream, &off)<0) - return -1; - wasip3_waitable_status_t status = - filesystem_stream_u8_read(stream->f0, buf, nbyte); - size_t amount = wasip3_waitable_block_on(status, stream->f0); - if (amount > 0 || nbyte == 0) { - if (off) - *off += amount; - return amount; - } else { - filesystem_result_void_error_code_t error; - status = filesystem_future_result_void_error_code_read(stream->f1, &error); - amount = wasip3_waitable_block_on(status, stream->f1); - if (amount > 0 && error.is_err) { - translate_error(error.val.err); - return -1; - } - // EOF - return 0; - } -#else -# error "Unsupported WASI version" #endif } diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c index a8339d7a6..f5c93a6eb 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c @@ -23,15 +23,15 @@ 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; - if (wasip2_string_from_c(path, &wasi_path) < 0) + wasi_string_t wasi_path, link_source; + if (wasi_string_from_c(path, &wasi_path) < 0) return -1; // Read the link @@ -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/cloudlibc/src/libc/unistd/symlinkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c index f727f8786..5ea2c97dd 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c @@ -19,17 +19,17 @@ 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; - if (wasip2_string_from_c(path1, &path1_wasi) < 0) + wasi_string_t path1_wasi, path2_wasi; + if (wasi_string_from_c(path1, &path1_wasi) < 0) return -1; - if (wasip2_string_from_c(path2, &path2_wasi) < 0) + if (wasi_string_from_c(path2, &path2_wasi) < 0) return -1; // Construct the link @@ -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/cloudlibc/src/libc/unistd/write.c b/libc-bottom-half/cloudlibc/src/libc/unistd/write.c index 8c2dead6d..c7e010e37 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/write.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/write.c @@ -13,10 +13,6 @@ #include #endif -#ifdef __wasip3__ -#include -#endif - ssize_t write(int fildes, const void *buf, size_t nbyte) { #if defined(__wasip1__) __wasi_ciovec_t iov = {.buf = buf, .buf_len = nbyte}; @@ -28,12 +24,12 @@ ssize_t write(int fildes, const void *buf, size_t nbyte) { return -1; } return bytes_written; -#elif defined(__wasip2__) +#else descriptor_table_entry_t *entry = descriptor_table_get_ref(fildes); if (!entry) return -1; if (entry->vtable->get_write_stream) { - wasip2_write_t write; + wasi_write_t write; if (entry->vtable->get_write_stream(entry->data, &write) < 0) return -1; return __wasilibc_write(&write, buf, nbyte); @@ -42,33 +38,5 @@ ssize_t write(int fildes, const void *buf, size_t nbyte) { return entry->vtable->sendto(entry->data, buf, nbyte, 0, NULL, 0); errno = EOPNOTSUPP; return -1; -#elif defined(__wasip3__) - wasip3_write_t *write_end; - off_t *off; - if (__wasilibc_write_stream3(fildes, &write_end, &off) < 0) - return -1; - if (WASIP3_SUBTASK_STATE(write_end->subtask) == WASIP3_SUBTASK_STARTING || - WASIP3_SUBTASK_STATE(write_end->subtask) == WASIP3_SUBTASK_STARTED) { - // the stream is still active - wasip3_waitable_status_t status = - filesystem_stream_u8_write(write_end->output, buf, nbyte); - size_t amount = wasip3_waitable_block_on(status, write_end->output); - if (amount > 0 || nbyte == 0) { - if (off) - *off += amount; - return amount; - } - // error or eof - wasip3_subtask_block_on(write_end->subtask); - write_end->subtask = WASIP3_SUBTASK_RETURNED; - } - if (write_end->pending_result.is_err) { - translate_error(write_end->pending_result.val.err); - return -1; - } - // EOF - return 0; -#else -# error "Unknown WASI version" #endif } diff --git a/libc-bottom-half/headers/private/wasi/descriptor_table.h b/libc-bottom-half/headers/private/wasi/descriptor_table.h index 254372fcd..4867a3e6f 100644 --- a/libc-bottom-half/headers/private/wasi/descriptor_table.h +++ b/libc-bottom-half/headers/private/wasi/descriptor_table.h @@ -8,48 +8,57 @@ #include #include -#ifdef __wasip2__ // Metadata for WASI reads which is used to delegate to `__wasilibc_read(...)` // to perform the actual read of a stream. -typedef struct wasip2_read_t { - // The `wasi:io/streams.input-stream` that this is reading from. - streams_borrow_input_stream_t input; +typedef struct wasi_read_t { // An optional pointer to the internal offset of this stream, updated on // successful reads. off_t *offset; - // A required pointer to an owned pollable for `input`. This is lazily - // initialized as-necessary. - poll_own_pollable_t *pollable; // Whether or not this read will use blocking I/O. bool blocking; // The timeout, in nanoseconds, for this operation. monotonic_clock_duration_t timeout; -} wasip2_read_t; +#ifdef __wasip2__ + // The `wasi:io/streams.input-stream` that this is reading from. + streams_borrow_input_stream_t input; + // A required pointer to an owned pollable for `input`. This is lazily + // initialized as-necessary. + poll_own_pollable_t *pollable; +#else + // The `stream` that's being read. + filesystem_stream_u8_t stream; + + // A callback/ptr pair to invoke when EOF is reached to set errno and return + // an error code. + int (*eof)(void*); + void *eof_data; +#endif +} wasi_read_t; -// Same as `wasip2_read_t`, but for writes. -typedef struct wasip2_write_t { - streams_borrow_output_stream_t output; +// Same as `wasip_read_t`, but for writes. +typedef struct wasi_write_t { off_t *offset; - poll_own_pollable_t *pollable; bool blocking; monotonic_clock_duration_t timeout; -} wasip2_write_t; + +#ifdef __wasip2__ + streams_borrow_output_stream_t output; + poll_own_pollable_t *pollable; +#else + // The actual stream that is being written to. + filesystem_stream_u8_writer_t output; + // An indicator if `output` has been closed/dropped. + bool *done; + // A callback/ptr pair to invoke when EOF is reached to set errno and return + // an error code. + int (*eof)(void*); + void *eof_data; #endif +} wasi_write_t; #ifdef __wasip3__ // create an alias to distinguish the handle type in the API typedef uint32_t waitable_t; - -/** - * This data structure represents the write end of a file - */ -typedef struct wasip3_write_t { - filesystem_stream_u8_writer_t output; - // contents will be filled by host (once write has an error) - filesystem_result_void_error_code_t pending_result; - // this task gets ready on error or eof - wasip3_subtask_t subtask; -} wasip3_write_t; #endif /** @@ -71,18 +80,12 @@ typedef struct descriptor_vtable_t { // ===================================================================== // Generic I/O -#ifdef __wasip2__ /// Looks up metadata to perform a read operation for this stream. This is used /// to implement the `read` syscall, for example, and is also used with `poll` /// when waiting for readability. - int (*get_read_stream)(void*, wasip2_read_t*); + int (*get_read_stream)(void*, wasi_read_t*); /// Same as `get_read_stream`, but for output streams. - int (*get_write_stream)(void*, wasip2_write_t*); -#endif -#ifdef __wasip3__ - int (*get_read_stream3)(void*, filesystem_tuple2_stream_u8_future_result_void_error_code_t **out, off_t** off); - int (*get_write_stream3)(void*, wasip3_write_t **write_end, off_t**); -#endif + int (*get_write_stream)(void*, wasi_write_t*); /// Sets the nonblocking flag for this object to the specified value. int (*set_blocking)(void*, bool); diff --git a/libc-bottom-half/headers/private/wasi/file_utils.h b/libc-bottom-half/headers/private/wasi/file_utils.h index d929b83f2..cd6f7dded 100644 --- a/libc-bottom-half/headers/private/wasi/file_utils.h +++ b/libc-bottom-half/headers/private/wasi/file_utils.h @@ -2,15 +2,14 @@ #define __wasi_file_utils_h #include - #if defined(__wasip2__) || defined(__wasip3__) + #include #include #include #include #include #include -#endif #ifdef __wasip2__ /// Handles a `wasi:io/streams.stream-error` for a `read`-style operation. @@ -39,18 +38,23 @@ static inline int wasip2_handle_write_error(streams_stream_error_t error) { errno = EIO; return -1; } +#endif + +#ifdef __wasip2__ +typedef wasip2_string_t wasi_string_t; +#else +typedef wasip3_string_t wasi_string_t; +#endif // Converts the C string `s` into a WASI string stored in `out`. // -// The returned `wasip2_string_t` should not be deallocated or free'd, and it +// The returned `wasip{2,3}_string_t` should not be deallocated or free'd, and it // can only be used while `s` is also valid. // // Returns 0 if `s` is valid utf-8. // Returns -1 and sets errno to `ENOENT` if `s` is not valid utf-8. -int wasip2_string_from_c(const char *s, wasip2_string_t* out); -#endif +int wasi_string_from_c(const char *s, wasi_string_t* out); -#if defined(__wasip2__) || defined(__wasip3__) // Succeed only if fd is bound to a file handle in the descriptor table static inline int fd_to_file_handle(int fd, filesystem_borrow_descriptor_t* result) { descriptor_table_entry_t* entry = descriptor_table_get_ref(fd); @@ -62,25 +66,16 @@ static inline int fd_to_file_handle(int fd, filesystem_borrow_descriptor_t* resu } return entry->vtable->get_file(entry->data, result); } -#endif -#ifdef __wasip2__ // Reads from `read` into `buf`/`len` // // This perform the read configured by `read`, e.g. whether it's blocking or // not, and places the result in the specified buffer. Used to implement // `read` and `recvfrom`, for example. -ssize_t __wasilibc_read(wasip2_read_t *read, void *buf, size_t len); +ssize_t __wasilibc_read(wasi_read_t *read, void *buf, size_t len); // Same as `__wasilibc_read`, but for writes. -ssize_t __wasilibc_write(wasip2_write_t *write, const void *buf, size_t len); -#endif - -#ifdef __wasip3__ -int __wasilibc_write_stream3(int fildes, wasip3_write_t **write_end, off_t **off); -int __wasilibc_read_stream3(int fildes, filesystem_tuple2_stream_u8_future_result_void_error_code_t **stream, off_t **off); -#endif +ssize_t __wasilibc_write(wasi_write_t *write, const void *buf, size_t len); -#if defined(__wasip2__) || defined(__wasip3__) static inline unsigned dir_entry_type_to_d_type(filesystem_descriptor_type_t ty) { switch(ty) { case FILESYSTEM_DESCRIPTOR_TYPE_UNKNOWN: @@ -104,6 +99,6 @@ static inline unsigned dir_entry_type_to_d_type(filesystem_descriptor_type_t ty) } } -#endif +#endif // __wasip2__ || __wasip3__ -#endif +#endif // __wasi_file_utils_h diff --git a/libc-bottom-half/headers/private/wasi/wasip3_block.h b/libc-bottom-half/headers/private/wasi/wasip3_block.h index a7dcf4a9a..d38d69e8e 100644 --- a/libc-bottom-half/headers/private/wasi/wasip3_block.h +++ b/libc-bottom-half/headers/private/wasi/wasip3_block.h @@ -8,9 +8,26 @@ #include // for waitable_t // Waits for a subtask to return -void wasip3_subtask_block_on(wasip3_subtask_status_t status); -// Waits for a (stream) transfer to complete -size_t wasip3_waitable_block_on(wasip3_waitable_status_t status, waitable_t stream); +void wasip3_subtask_block_on_and_drop(wasip3_subtask_t status); + +/// Waits for `future` to be resolved after a previous operation yielded +/// `status` as a result. +/// +/// This function will block if `status` indicates that the future is blocked, +/// and this function won't return until the future has become ready again. This is +/// suitable, for example, for waiting for future reads to complete. +void wasip3_future_block_on(wasip3_subtask_status_t status, uint32_t future); + +/// Waits for `stream` to be resolved after a previous operation yielded +/// `status` as a result. +/// +/// This function will block if `status` indicates that the stream is blocked, +/// and this function won't return until the stream has become ready again. This is +/// suitable, for example, for waiting for stream read or write to complete. +/// +/// The `closed` variable is set based on the result of the operation to +/// communicate what was received from the component model. +size_t wasip3_stream_block_on(wasip3_subtask_status_t status, uint32_t stream, bool *closed); #endif #endif // WASI_WASIP3_BLOCK_H diff --git a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h index 2a5d526ce..b956e3e48 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -574,43 +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 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_open_at_args { - 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_method_descriptor_open_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 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; @@ -1014,9 +977,9 @@ extern monotonic_clock_mark_t monotonic_clock_now(void); // corresponding to a clock tick. extern monotonic_clock_duration_t monotonic_clock_get_resolution(void); // Wait until the specified mark has occurred. -extern wasip3_subtask_status_t monotonic_clock_wait_until(monotonic_clock_mark_t when); +extern void monotonic_clock_wait_until(monotonic_clock_mark_t when); // Wait for the specified duration to elapse. -extern wasip3_subtask_status_t monotonic_clock_wait_for(monotonic_clock_duration_t how_long); +extern void monotonic_clock_wait_for(monotonic_clock_duration_t how_long); // Imported Functions from `wasi:clocks/system-clock@0.3.0-rc-2026-01-06` // Read the current value of the clock. @@ -1073,21 +1036,21 @@ 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 // 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. // // Note: This returns the value that was the `fs_flags` value returned // from `fdstat_get` in earlier versions of WASI. -extern wasip3_subtask_status_t filesystem_method_descriptor_get_flags(filesystem_borrow_descriptor_t self, filesystem_result_descriptor_flags_error_code_t *result); +extern bool filesystem_method_descriptor_get_flags(filesystem_borrow_descriptor_t self, filesystem_descriptor_flags_t *ret, filesystem_error_code_t *err); // Get the dynamic type of a descriptor. // // Note: This returns the same value as the `type` field of the `fd-stat` @@ -1103,13 +1066,13 @@ 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. // // 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 @@ -1122,18 +1085,18 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_set_times(filesystem // // This function returns a future, which will resolve to an error code if // reading full contents of the directory fails. -extern wasip3_subtask_status_t filesystem_method_descriptor_read_directory(filesystem_borrow_descriptor_t self, filesystem_tuple2_stream_directory_entry_future_result_void_error_code_t *result); +extern void filesystem_method_descriptor_read_directory(filesystem_borrow_descriptor_t self, filesystem_tuple2_stream_directory_entry_future_result_void_error_code_t *ret); // Synchronize the data and metadata of a file to disk. // // This function succeeds with no effect if the file descriptor is not // 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. -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 @@ -1143,7 +1106,7 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_create_directory_at( // modified, use `metadata-hash`. // // Note: This was called `fd_filestat_get` in earlier versions of WASI. -extern wasip3_subtask_status_t filesystem_method_descriptor_stat(filesystem_borrow_descriptor_t self, filesystem_result_descriptor_stat_error_code_t *result); +extern bool filesystem_method_descriptor_stat(filesystem_borrow_descriptor_t self, filesystem_descriptor_stat_t *ret, filesystem_error_code_t *err); // Return the attributes of a file or directory. // // Note: This is similar to `fstatat` in POSIX, except that it does not @@ -1151,14 +1114,14 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_stat(filesystem_borr // 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. // // 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, @@ -1166,7 +1129,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 @@ -1179,36 +1142,36 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_link_at(filesystem_m // `error-code::read-only`. // // Note: This is similar to `openat` in POSIX. -extern wasip3_subtask_status_t filesystem_method_descriptor_open_at(filesystem_method_descriptor_open_at_args_t *args, filesystem_result_own_descriptor_error_code_t *result); +extern 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); // Read the contents of a symbolic link. // // If the contents contain an absolute or rooted path in the underlying // 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. // // 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. -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 // `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. // 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 @@ -1235,12 +1198,12 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_is_same_object(files // computed hash. // // However, none of these is required. -extern wasip3_subtask_status_t filesystem_method_descriptor_metadata_hash(filesystem_borrow_descriptor_t self, filesystem_result_metadata_hash_value_error_code_t *result); +extern bool filesystem_method_descriptor_metadata_hash(filesystem_borrow_descriptor_t self, filesystem_metadata_hash_value_t *ret, filesystem_error_code_t *err); // Return a hash of the metadata associated with a filesystem object referred // to by a directory descriptor and a relative path. // // This performs the same hash computation as `metadata-hash`. -extern wasip3_subtask_status_t filesystem_method_descriptor_metadata_hash_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t path_flags, wasip3_string_t path, filesystem_result_metadata_hash_value_error_code_t *result); +extern bool filesystem_method_descriptor_metadata_hash_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t path_flags, wasip3_string_t *path, filesystem_metadata_hash_value_t *ret, filesystem_error_code_t *err); // Imported Functions from `wasi:filesystem/preopens@0.3.0-rc-2026-01-06` // Return the set of preopened directories, and their paths. diff --git a/libc-bottom-half/sources/__wasilibc_rmdirat.c b/libc-bottom-half/sources/__wasilibc_rmdirat.c index 6096a36c1..bb0e965d7 100644 --- a/libc-bottom-half/sources/__wasilibc_rmdirat.c +++ b/libc-bottom-half/sources/__wasilibc_rmdirat.c @@ -15,15 +15,15 @@ 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; - if (wasip2_string_from_c(path, &wasi_path) < 0) + 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_tell.c b/libc-bottom-half/sources/__wasilibc_tell.c index 8806596e2..658dfedb7 100644 --- a/libc-bottom-half/sources/__wasilibc_tell.c +++ b/libc-bottom-half/sources/__wasilibc_tell.c @@ -19,7 +19,7 @@ off_t __wasilibc_tell(int fildes) { return -1; } return offset; -#elif defined(__wasip2__) +#elif defined(__wasip2__) || defined(__wasip3__) // Look up a stream for fildes descriptor_table_entry_t *entry = descriptor_table_get_ref(fildes); if (!entry) @@ -29,11 +29,6 @@ off_t __wasilibc_tell(int fildes) { return -1; } return entry->vtable->seek(entry->data, 0, SEEK_CUR); -#elif defined(__wasip3__) - (void)fildes; - // 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 4ac919000..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,8 +33,8 @@ int __wasilibc_nocwd___wasilibc_unlinkat(int fd, const char *path) { return -1; // Create a Wasm string from the path - wasip2_string_t wasi_path; - if (wasip2_string_from_c(path, &wasi_path) < 0) + wasi_string_t wasi_path; + if (wasi_string_from_c(path, &wasi_path) < 0) return -1; // Unlink the file @@ -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/wasip2_file.c b/libc-bottom-half/sources/file.c similarity index 69% rename from libc-bottom-half/sources/wasip2_file.c rename to libc-bottom-half/sources/file.c index 116f6d4f3..0b787dacd 100644 --- a/libc-bottom-half/sources/wasip2_file.c +++ b/libc-bottom-half/sources/file.c @@ -5,30 +5,38 @@ #include #include #include - -#ifdef __wasip2__ +#include #include "libc/sys/stat/stat_impl.h" typedef struct { filesystem_own_descriptor_t file_handle; + // Current position in stream, relative to the beginning of the + // *file_handle*, measured in bytes + off_t offset; + int oflag; +#ifdef __wasip2__ // Lazily initialized read/write streams which track the current position // in the file. Seeking will close these streams and cause them to be // reopened on the next operation, for example. streams_own_input_stream_t read_stream; streams_own_output_stream_t write_stream; - // Current position in stream, relative to the beginning of the - // *file_handle*, measured in bytes - off_t offset; // Used for checking readiness to read/write to stream. Lazily initialized // and initially set to 0. streams_own_pollable_t read_pollable; streams_own_pollable_t write_pollable; - int oflag; +#else + filesystem_tuple2_stream_u8_future_result_void_error_code_t read; + filesystem_stream_u8_writer_t write; + wasip3_subtask_t write_subtask; + filesystem_result_void_error_code_t write_pending_result; + bool write_done; +#endif } file_t; static void file_close_streams(void *data) { file_t *file = (file_t *)data; +#ifdef __wasip2__ if (file->read_pollable.__handle != 0) { poll_pollable_drop_own(file->read_pollable); file->read_pollable.__handle = 0; @@ -45,6 +53,28 @@ static void file_close_streams(void *data) { streams_output_stream_drop_own(file->write_stream); file->write_stream.__handle = 0; } +#else + if (file->read.f0 != 0) { + filesystem_stream_u8_drop_readable(file->read.f0); + file->read.f0 = 0; + } + if (file->read.f1 != 0) { + filesystem_future_result_void_error_code_drop_readable(file->read.f1); + file->read.f1 = 0; + } + if (file->write != 0) { + filesystem_stream_u8_drop_writable(file->write); + file->write = 0; + } + if (file->write_subtask != 0) { + // TODO: this should use `wasip3_subtask_cancel` but right now that's buggy + // in Wasmtime. For now assume closign the stream above is enough to have + // the subtask here finish promptly, so block on the result. + wasip3_subtask_block_on_and_drop(file->write_subtask); + file->write_subtask = 0; + } + file->write_done = false; +#endif } static void file_free(void *data) { @@ -54,8 +84,29 @@ static void file_free(void *data) { free(file); } -static int file_get_read_stream(void *data, wasip2_read_t *read) { +#ifndef __wasip2__ +static int file_read_eof(void *data) { file_t *file = (file_t *)data; + + if (file->read.f1 != 0) { + filesystem_result_void_error_code_t result; + wasip3_future_block_on( + filesystem_future_result_void_error_code_read(file->read.f1, &result), + file->read.f1); + filesystem_future_result_void_error_code_drop_readable(file->read.f1); + file->read.f1 = 0; + if (result.is_err) { + translate_error(result.val.err); + return -1; + } + } + return 0; +} +#endif + +static int file_get_read_stream(void *data, wasi_read_t *read) { + file_t *file = (file_t *)data; +#ifdef __wasip2__ if (file->read_stream.__handle == 0) { filesystem_error_code_t error_code; bool ok = filesystem_method_descriptor_read_via_stream( @@ -67,15 +118,42 @@ static int file_get_read_stream(void *data, wasip2_read_t *read) { } } read->input = streams_borrow_input_stream(file->read_stream); - read->offset = &file->offset; read->pollable = &file->read_pollable; +#else + if (file->read.f0 == 0) { + filesystem_method_descriptor_read_via_stream( + filesystem_borrow_descriptor(file->file_handle), file->offset, + &file->read); + } + read->stream = file->read.f0; + read->eof = file_read_eof; + read->eof_data = data; +#endif + read->offset = &file->offset; read->timeout = 0; read->blocking = true; return 0; } -static int file_get_write_stream(void *data, wasip2_write_t *write) { +#ifndef __wasip2__ +static int file_write_eof(void *data) { + file_t *file = (file_t *)data; + + if (file->write_subtask != 0) { + wasip3_subtask_block_on_and_drop(file->write_subtask); + file->write_subtask = 0; + } + if (file->write_pending_result.is_err) { + translate_error(file->write_pending_result.val.err); + return -1; + } + return 0; +} +#endif + +static int file_get_write_stream(void *data, wasi_write_t *write) { file_t *file = (file_t *)data; +#ifdef __wasip2__ if (file->write_stream.__handle == 0) { filesystem_error_code_t error_code; bool ok; @@ -95,8 +173,30 @@ static int file_get_write_stream(void *data, wasip2_write_t *write) { } } write->output = streams_borrow_output_stream(file->write_stream); - write->offset = &file->offset; write->pollable = &file->write_pollable; +#else + 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; + 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); + } + write->output = file->write; + write->eof = file_write_eof; + write->eof_data = data; + write->done = &file->write_done; +#endif + write->offset = &file->offset; write->timeout = 0; write->blocking = true; return 0; @@ -257,5 +357,3 @@ int __wasilibc_add_file(filesystem_own_descriptor_t file_handle, int oflag) { entry.data = file; return descriptor_table_insert(entry); } - -#endif // __wasip2__ diff --git a/libc-bottom-half/sources/wasip2_file_utils.c b/libc-bottom-half/sources/file_utils.c similarity index 82% rename from libc-bottom-half/sources/wasip2_file_utils.c rename to libc-bottom-half/sources/file_utils.c index abecd8263..60175a446 100644 --- a/libc-bottom-half/sources/wasip2_file_utils.c +++ b/libc-bottom-half/sources/file_utils.c @@ -4,8 +4,7 @@ #include #include #include - -#ifdef __wasip2__ +#include /** * Validates that `ptr_signed` is a valid utf-8 string. @@ -72,7 +71,7 @@ static int validate_utf8(const char *ptr_signed) { return i; } -int wasip2_string_from_c(const char *s, wasip2_string_t *out) { +int wasi_string_from_c(const char *s, wasi_string_t *out) { int len = validate_utf8(s); if (len < 0) { errno = EILSEQ; @@ -83,8 +82,9 @@ int wasip2_string_from_c(const char *s, wasip2_string_t *out) { return 0; } -ssize_t __wasilibc_write(wasip2_write_t *write, const void *buffer, +ssize_t __wasilibc_write(wasi_write_t *write, const void *buffer, size_t length) { +#if defined(__wasip2__) assert(write->output.__handle != 0); while (true) { streams_stream_error_t error; @@ -158,9 +158,30 @@ ssize_t __wasilibc_write(wasip2_write_t *write, const void *buffer, poll_method_pollable_block(pollable_borrow); } } +#elif defined(__wasip3__) + assert(write->blocking); // TODO(wasip3) + assert(write->timeout == 0); // TODO(wasip3) + + // Perform writes until either a non-zero-length write completes or the stream + // is closed. + while (!*write->done) { + size_t amount = wasip3_stream_block_on( + filesystem_stream_u8_write(write->output, buffer, length), + write->output, write->done); + if (amount > 0 || length == 0) { + if (write->offset) + *write->offset += amount; + return amount; + } + } + return write->eof(write->eof_data); +#else +#error "Unknown WASI version" +#endif } -ssize_t __wasilibc_read(wasip2_read_t *read, void *buffer, size_t length) { +ssize_t __wasilibc_read(wasi_read_t *read, void *buffer, size_t length) { +#if defined(__wasip2__) while (true) { wasip2_list_u8_t result; streams_stream_error_t error; @@ -223,6 +244,25 @@ ssize_t __wasilibc_read(wasip2_read_t *read, void *buffer, size_t length) { poll_method_pollable_block(pollable_borrow); } } -} +#elif defined(__wasip3__) + assert(read->blocking); // TODO(wasip3) + assert(read->timeout == 0); // TODO(wasip3) -#endif // __wasip2__ + // Attempt reads until a nonzero-length read is encountered or the stream is + // closed. + bool closed = false; + while (!closed) { + size_t amount = wasip3_stream_block_on( + filesystem_stream_u8_read(read->stream, buffer, length), read->stream, + &closed); + if (amount > 0 || length == 0) { + if (read->offset) + *read->offset += amount; + return amount; + } + } + return read->eof(read->eof_data); +#else +#error "Unknown WASI version" +#endif +} diff --git a/libc-bottom-half/sources/tcp.c b/libc-bottom-half/sources/tcp.c index e32bf21e2..b9fe0be77 100644 --- a/libc-bottom-half/sources/tcp.c +++ b/libc-bottom-half/sources/tcp.c @@ -122,7 +122,7 @@ static void tcp_free(void *data) { } #ifdef __wasip2__ -static int tcp_get_read_stream(void *data, wasip2_read_t *read) { +static int tcp_get_read_stream(void *data, wasi_read_t *read) { tcp_socket_t *tcp = (tcp_socket_t *)data; if (tcp->state.tag != TCP_SOCKET_STATE_CONNECTED) { @@ -137,7 +137,7 @@ static int tcp_get_read_stream(void *data, wasip2_read_t *read) { return 0; } -static int tcp_get_write_stream(void *data, wasip2_write_t *write) { +static int tcp_get_write_stream(void *data, wasi_write_t *write) { tcp_socket_t *tcp = (tcp_socket_t *)data; if (tcp->state.tag != TCP_SOCKET_STATE_CONNECTED) { @@ -531,7 +531,7 @@ static ssize_t tcp_recvfrom(void *data, void *buffer, size_t length, int flags, return -1; } - wasip2_read_t read; + wasi_read_t read; if (tcp_get_read_stream(data, &read) < 0) return -1; @@ -555,7 +555,7 @@ static ssize_t tcp_sendto(void *data, const void *buffer, size_t length, return -1; } - wasip2_write_t write; + wasi_write_t write; if (tcp_get_write_stream(data, &write) < 0) return -1; diff --git a/libc-bottom-half/sources/wasip2_stdio.c b/libc-bottom-half/sources/wasip2_stdio.c index c4681517d..47e9044c2 100644 --- a/libc-bottom-half/sources/wasip2_stdio.c +++ b/libc-bottom-half/sources/wasip2_stdio.c @@ -36,7 +36,7 @@ static void stdio_free(void *data) { free(stdio); } -static int stdio_get_read_stream(void *data, wasip2_read_t *read) { +static int stdio_get_read_stream(void *data, wasi_read_t *read) { stdio_t *stdio = (stdio_t *)data; if (stdio->fd != 0) { errno = EOPNOTSUPP; @@ -52,7 +52,7 @@ static int stdio_get_read_stream(void *data, wasip2_read_t *read) { return 0; } -static int stdio_get_write_stream(void *data, wasip2_write_t *write) { +static int stdio_get_write_stream(void *data, wasi_write_t *write) { stdio_t *stdio = (stdio_t *)data; if (stdio->output.__handle == 0) { if (stdio->fd == 1) { diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index 8b0f3d960..6dc0f9521 100644 --- a/libc-bottom-half/sources/wasip3.c +++ b/libc-bottom-half/sources/wasip3.c @@ -57,11 +57,11 @@ extern int64_t __wasm_import_monotonic_clock_now(void); __attribute__((__import_module__("wasi:clocks/monotonic-clock@0.3.0-rc-2026-01-06"), __import_name__("get-resolution"))) extern int64_t __wasm_import_monotonic_clock_get_resolution(void); -__attribute__((__import_module__("wasi:clocks/monotonic-clock@0.3.0-rc-2026-01-06"), __import_name__("[async-lower]wait-until"))) -extern int32_t __wasm_import_monotonic_clock_wait_until(int64_t); +__attribute__((__import_module__("wasi:clocks/monotonic-clock@0.3.0-rc-2026-01-06"), __import_name__("wait-until"))) +extern void __wasm_import_monotonic_clock_wait_until(int64_t); -__attribute__((__import_module__("wasi:clocks/monotonic-clock@0.3.0-rc-2026-01-06"), __import_name__("[async-lower]wait-for"))) -extern int32_t __wasm_import_monotonic_clock_wait_for(int64_t); +__attribute__((__import_module__("wasi:clocks/monotonic-clock@0.3.0-rc-2026-01-06"), __import_name__("wait-for"))) +extern void __wasm_import_monotonic_clock_wait_for(int64_t); // Imported Functions from `wasi:clocks/system-clock@0.3.0-rc-2026-01-06` @@ -82,71 +82,71 @@ 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 *); +__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__("[async-lower][method]descriptor.get-flags"))) -extern int32_t __wasm_import_filesystem_method_descriptor_get_flags(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 *); __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 *); +__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__("[async-lower][method]descriptor.read-directory"))) -extern int32_t __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__("[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__("[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__("[async-lower][method]descriptor.stat"))) -extern int32_t __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"))) +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 *); +__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__("[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__("[async-lower][method]descriptor.open-at"))) -extern int32_t __wasm_import_filesystem_method_descriptor_open_at(uint8_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 *); -__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__("[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 *); +__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__("[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__("[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 *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.metadata-hash"))) -extern int32_t __wasm_import_filesystem_method_descriptor_metadata_hash(int32_t, uint8_t *); +__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[method]descriptor.metadata-hash"))) +extern void __wasm_import_filesystem_method_descriptor_metadata_hash(int32_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.metadata-hash-at"))) -extern int32_t __wasm_import_filesystem_method_descriptor_metadata_hash_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.metadata-hash-at"))) +extern void __wasm_import_filesystem_method_descriptor_metadata_hash_at(int32_t, int32_t, uint8_t *, size_t, uint8_t *); // Imported Functions from `wasi:filesystem/preopens@0.3.0-rc-2026-01-06` @@ -1383,12 +1383,12 @@ monotonic_clock_duration_t monotonic_clock_get_resolution(void) { return (uint64_t) (ret); } -wasip3_subtask_status_t monotonic_clock_wait_until(monotonic_clock_mark_t when) { - return __wasm_import_monotonic_clock_wait_until((int64_t) (when)); +void monotonic_clock_wait_until(monotonic_clock_mark_t when) { + __wasm_import_monotonic_clock_wait_until((int64_t) (when)); } -wasip3_subtask_status_t monotonic_clock_wait_for(monotonic_clock_duration_t how_long) { - return __wasm_import_monotonic_clock_wait_for((int64_t) (how_long)); +void monotonic_clock_wait_for(monotonic_clock_duration_t how_long) { + __wasm_import_monotonic_clock_wait_for((int64_t) (how_long)); } void system_clock_now(system_clock_instant_t *ret) { @@ -1426,92 +1426,720 @@ 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) { - 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; + } } -wasip3_subtask_status_t filesystem_method_descriptor_get_flags(filesystem_borrow_descriptor_t self, filesystem_result_descriptor_flags_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_get_flags((self).__handle, (uint8_t*) result); +bool filesystem_method_descriptor_get_flags(filesystem_borrow_descriptor_t self, filesystem_descriptor_flags_t *ret, 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_get_flags((self).__handle, ptr); + filesystem_result_descriptor_flags_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (int32_t) *((uint8_t*) (ptr + 1)); + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 1)); + 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_get_type(filesystem_borrow_descriptor_t self, filesystem_result_descriptor_type_error_code_t *result) { 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) { - 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; + } } -wasip3_subtask_status_t filesystem_method_descriptor_read_directory(filesystem_borrow_descriptor_t self, filesystem_tuple2_stream_directory_entry_future_result_void_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_read_directory((self).__handle, (uint8_t*) result); +void filesystem_method_descriptor_read_directory(filesystem_borrow_descriptor_t self, filesystem_tuple2_stream_directory_entry_future_result_void_error_code_t *ret) { + __attribute__((__aligned__(4))) + uint8_t ret_area[8]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_read_directory((self).__handle, ptr); + *ret = (filesystem_tuple2_stream_directory_entry_future_result_void_error_code_t) { + (filesystem_stream_directory_entry_t) ((uint32_t) *((int32_t*) (ptr + 0))), + (filesystem_future_result_void_error_code_t) ((uint32_t) *((int32_t*) (ptr + 4))), + }; } -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; + } } -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; + } } -wasip3_subtask_status_t filesystem_method_descriptor_stat(filesystem_borrow_descriptor_t self, filesystem_result_descriptor_stat_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_stat((self).__handle, (uint8_t*) result); +bool filesystem_method_descriptor_stat(filesystem_borrow_descriptor_t self, 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((self).__handle, 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_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) { - 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; + } } -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; + } } -wasip3_subtask_status_t filesystem_method_descriptor_open_at(filesystem_method_descriptor_open_at_args_t *args, filesystem_result_own_descriptor_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_open_at((uint8_t*) args, (uint8_t*) result); +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) { + __attribute__((__aligned__(4))) + uint8_t ret_area[8]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_open_at((self).__handle, path_flags, (uint8_t *) (*path).ptr, (*path).len, open_flags, flags, ptr); + filesystem_result_own_descriptor_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (filesystem_own_descriptor_t) { *((int32_t*) (ptr + 4)) }; + break; + } + case 1: { + result.is_err = true; + result.val.err = (int32_t) *((uint8_t*) (ptr + 4)); + 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_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; + } } -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) { - 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; + } } -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; + } } -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) { return __wasm_import_filesystem_method_descriptor_is_same_object((self).__handle, (other).__handle, (uint8_t*) result); } -wasip3_subtask_status_t filesystem_method_descriptor_metadata_hash(filesystem_borrow_descriptor_t self, filesystem_result_metadata_hash_value_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_metadata_hash((self).__handle, (uint8_t*) result); +bool filesystem_method_descriptor_metadata_hash(filesystem_borrow_descriptor_t self, filesystem_metadata_hash_value_t *ret, filesystem_error_code_t *err) { + __attribute__((__aligned__(8))) + uint8_t ret_area[24]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_metadata_hash((self).__handle, ptr); + filesystem_result_metadata_hash_value_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (filesystem_metadata_hash_value_t) { + (uint64_t) (uint64_t) (*((int64_t*) (ptr + 8))), + (uint64_t) (uint64_t) (*((int64_t*) (ptr + 16))), + }; + 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_metadata_hash_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t path_flags, wasip3_string_t path, filesystem_result_metadata_hash_value_error_code_t *result) { - return __wasm_import_filesystem_method_descriptor_metadata_hash_at((self).__handle, path_flags, (uint8_t *) (path).ptr, (path).len, (uint8_t*) result); +bool filesystem_method_descriptor_metadata_hash_at(filesystem_borrow_descriptor_t self, filesystem_path_flags_t path_flags, wasip3_string_t *path, filesystem_metadata_hash_value_t *ret, filesystem_error_code_t *err) { + __attribute__((__aligned__(8))) + uint8_t ret_area[24]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_filesystem_method_descriptor_metadata_hash_at((self).__handle, path_flags, (uint8_t *) (*path).ptr, (*path).len, ptr); + filesystem_result_metadata_hash_value_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (filesystem_metadata_hash_value_t) { + (uint64_t) (uint64_t) (*((int64_t*) (ptr + 8))), + (uint64_t) (uint64_t) (*((int64_t*) (ptr + 16))), + }; + 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; + } } void filesystem_preopens_get_directories(filesystem_preopens_list_tuple2_own_descriptor_string_t *ret) { diff --git a/libc-bottom-half/sources/wasip3_block_on.c b/libc-bottom-half/sources/wasip3_block_on.c index a8f16420e..bcb025d9b 100644 --- a/libc-bottom-half/sources/wasip3_block_on.c +++ b/libc-bottom-half/sources/wasip3_block_on.c @@ -5,49 +5,52 @@ #include #include -void wasip3_subtask_block_on(wasip3_subtask_status_t status) { - // we don't encounter cancelled state because this function won't cancel - if (WASIP3_SUBTASK_STATE(status) == WASIP3_SUBTASK_STARTING || - WASIP3_SUBTASK_STATE(status) == WASIP3_SUBTASK_STARTED) { - wasip3_subtask_t handle = WASIP3_SUBTASK_HANDLE(status); - wasip3_waitable_set_t set = wasip3_waitable_set_new(); - wasip3_waitable_join(handle, set); +static void waitable_block_on(uint32_t waitable, wasip3_event_t *event) { + wasip3_waitable_set_t set = wasip3_waitable_set_new(); + wasip3_waitable_join(waitable, set); + wasip3_waitable_set_wait(set, event); + // remove from set + wasip3_waitable_join(waitable, 0); + wasip3_waitable_set_drop(set); +} + +void wasip3_subtask_block_on_and_drop(wasip3_subtask_t handle) { + wasip3_event_t event; + waitable_block_on(handle, &event); + assert(event.event == WASIP3_EVENT_SUBTASK); + assert(event.waitable == handle); + assert(event.code == WASIP3_SUBTASK_RETURNED); + wasip3_subtask_drop(handle); +} + +void wasip3_future_block_on(wasip3_waitable_status_t status, uint32_t future) { + if (status == WASIP3_WAITABLE_STATUS_BLOCKED) { wasip3_event_t event; - event.code = WASIP3_SUBTASK_STATE(status); - while (event.code != WASIP3_SUBTASK_RETURNED) { - wasip3_waitable_set_wait(set, &event); - assert(event.event == WASIP3_EVENT_SUBTASK); - assert(event.waitable == handle); - } - wasip3_subtask_drop(event.waitable); - wasip3_waitable_set_drop(set); + waitable_block_on(future, &event); + assert(event.event == WASIP3_EVENT_FUTURE_READ || + event.event == WASIP3_EVENT_FUTURE_WRITE); + assert(event.waitable == future); + status = event.code; } + assert(WASIP3_WAITABLE_STATE(status) == WASIP3_WAITABLE_COMPLETED || + WASIP3_WAITABLE_STATE(status) == WASIP3_WAITABLE_DROPPED); + assert(WASIP3_WAITABLE_COUNT(status) == 0); } -size_t wasip3_waitable_block_on(wasip3_waitable_status_t status, - waitable_t stream) { +size_t wasip3_stream_block_on(wasip3_waitable_status_t status, uint32_t stream, + bool *closed) { if (status == WASIP3_WAITABLE_STATUS_BLOCKED) { - wasip3_waitable_set_t set = wasip3_waitable_set_new(); - wasip3_waitable_join(stream, set); wasip3_event_t event; - wasip3_waitable_set_wait(set, &event); - assert(event.event == WASIP3_EVENT_STREAM_WRITE || - event.event == WASIP3_EVENT_STREAM_READ || - event.event == WASIP3_EVENT_FUTURE_READ); + waitable_block_on(stream, &event); + assert(event.event == WASIP3_EVENT_STREAM_READ || + event.event == WASIP3_EVENT_STREAM_WRITE); assert(event.waitable == stream); - // remove from set - wasip3_waitable_join(stream, 0); - wasip3_waitable_set_drop(set); - size_t amount = event.event == WASIP3_EVENT_FUTURE_READ ? 1 : event.code; - return amount; - } else if (WASIP3_WAITABLE_STATE(status) == WASIP3_WAITABLE_COMPLETED || - WASIP3_WAITABLE_STATE(status) == WASIP3_WAITABLE_DROPPED) { - size_t amount = WASIP3_WAITABLE_COUNT(status); - return amount; - } else { - // other status (e.g. cancelled) shouldn't occur - abort(); + status = event.code; } + assert(WASIP3_WAITABLE_STATE(status) == WASIP3_WAITABLE_COMPLETED || + WASIP3_WAITABLE_STATE(status) == WASIP3_WAITABLE_DROPPED); + *closed = WASIP3_WAITABLE_STATE(status) == WASIP3_WAITABLE_DROPPED; + return WASIP3_WAITABLE_COUNT(status); } #endif diff --git a/libc-bottom-half/sources/wasip3_file.c b/libc-bottom-half/sources/wasip3_file.c deleted file mode 100644 index 9992b0437..000000000 --- a/libc-bottom-half/sources/wasip3_file.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -#ifdef __wasip3__ - -int __wasilibc_add_file(filesystem_own_descriptor_t file_handle, int oflag) { - (void)file_handle; - (void)oflag; - // TODO(wasip3) - errno = EOPNOTSUPP; - return -1; -} - -#endif // __wasip3__ diff --git a/libc-bottom-half/sources/wasip3_file_utils.c b/libc-bottom-half/sources/wasip3_file_utils.c deleted file mode 100644 index e80b21ead..000000000 --- a/libc-bottom-half/sources/wasip3_file_utils.c +++ /dev/null @@ -1,31 +0,0 @@ -#include - -#ifdef __wasip3__ -#include - -int __wasilibc_write_stream3(int fildes, wasip3_write_t **write_end, - off_t **off) { - descriptor_table_entry_t *entry = descriptor_table_get_ref(fildes); - if (!entry) - return -1; - if (!entry->vtable->get_write_stream3) { - errno = EOPNOTSUPP; - return -1; - } - return (*entry->vtable->get_write_stream3)(entry->data, write_end, off); -} - -int __wasilibc_read_stream3( - int fildes, - filesystem_tuple2_stream_u8_future_result_void_error_code_t **stream, - off_t **off) { - descriptor_table_entry_t *entry = descriptor_table_get_ref(fildes); - if (!entry) - return -1; - if (!entry->vtable->get_read_stream3) { - errno = EOPNOTSUPP; - return -1; - } - return (*entry->vtable->get_read_stream3)(entry->data, stream, off); -} -#endif // __wasip3__ diff --git a/libc-bottom-half/sources/wasip3_stdio.c b/libc-bottom-half/sources/wasip3_stdio.c index 3f3091189..af345dc4b 100644 --- a/libc-bottom-half/sources/wasip3_stdio.c +++ b/libc-bottom-half/sources/wasip3_stdio.c @@ -2,6 +2,7 @@ #include #ifdef __wasip3__ +#include #include #include #include @@ -20,7 +21,10 @@ typedef struct { typedef struct { // contains stream, result storage and result subtask - wasip3_write_t output; + wasip3_subtask_t subtask; + stdin_stream_u8_writer_t output; + bool output_done; + stdout_result_void_error_code_t pending_result; // tristate: zero=unknown, valid handle=yes, -1=no terminal_output_own_terminal_output_t terminal_out; // stream creation function (delayed) @@ -30,6 +34,23 @@ typedef struct { bool (*terminal_func)(terminal_stdout_own_terminal_output_t *ret); } stdout3_t; +static void translate_error(wasi_cli_types_error_code_t err) { + switch (err) { + case WASI_CLI_TYPES_ERROR_CODE_IO: + errno = EIO; + break; + case WASI_CLI_TYPES_ERROR_CODE_ILLEGAL_BYTE_SEQUENCE: + errno = EILSEQ; + break; + case WASI_CLI_TYPES_ERROR_CODE_PIPE: + errno = EPIPE; + break; + default: + assert(0); + break; + } +} + static void stdin3_free(void *data) { stdin3_t *stdio = (stdin3_t *)data; if (stdio->terminal_in.__handle > 0) @@ -45,38 +66,76 @@ static void stdout3_free(void *data) { stdout3_t *stdio = (stdout3_t *)data; if (stdio->terminal_out.__handle > 0) terminal_output_terminal_output_drop_own(stdio->terminal_out); - if (stdio->output.output) - stdin_stream_u8_drop_writable(stdio->output.output); - if (stdio->output.subtask) - wasip3_subtask_block_on(stdio->output.subtask); + if (stdio->output) + stdin_stream_u8_drop_writable(stdio->output); + if (stdio->subtask) + wasip3_subtask_block_on_and_drop(stdio->subtask); free(stdio); } -static int stdout3_write(void *data, wasip3_write_t **out, off_t **offs) { +static int stdout3_write_eof(void *data) { stdout3_t *stdio = (stdout3_t *)data; - if (!stdio->output.output) { - stdin_stream_u8_t read_side = stdin_stream_u8_new(&stdio->output.output); - stdio->output.subtask = (*stdio->stream_func)( - read_side, - (stdout_result_void_error_code_t *)&stdio->output.pending_result); - // subtask will be checked by write for error before writing + if (stdio->subtask != 0) { + wasip3_subtask_block_on_and_drop(stdio->subtask); + stdio->subtask = 0; + } + if (stdio->pending_result.is_err) { + translate_error(stdio->pending_result.val.err); + return -1; + } + return 0; +} + +static int stdout3_write(void *data, wasi_write_t *out) { + stdout3_t *stdio = (stdout3_t *)data; + if (!stdio->output) { + assert(!stdio->subtask); + stdin_stream_u8_t read_side = stdin_stream_u8_new(&stdio->output); + wasip3_subtask_status_t status = (*stdio->stream_func)( + read_side, &stdio->pending_result); + if (WASIP3_SUBTASK_STATE(status) != WASIP3_SUBTASK_RETURNED) + stdio->subtask = WASIP3_SUBTASK_HANDLE(status); + } + out->offset = NULL; + out->blocking = true; + out->timeout = 0; + out->output = stdio->output; + out->done = &stdio->output_done; + out->eof = stdout3_write_eof; + out->eof_data = data; + return 0; +} + +static int stdin3_read_eof(void *data) { + stdin3_t *stdio = (stdin3_t *)data; + + if (stdio->input.f1 != 0) { + stdin_result_void_error_code_t result; + wasip3_future_block_on( + stdin_future_result_void_error_code_read(stdio->input.f1, &result), + stdio->input.f1); + stdin_future_result_void_error_code_drop_readable(stdio->input.f1); + stdio->input.f1 = 0; + if (result.is_err) { + translate_error(result.val.err); + return -1; + } } - *out = &stdio->output; - *offs = NULL; return 0; } -static int -stdin3_read(void *data, - filesystem_tuple2_stream_u8_future_result_void_error_code_t **out, - off_t **offs) { +static int stdin3_read(void *data, wasi_read_t *read) { stdin3_t *stdio = (stdin3_t *)data; if (!stdio->input.f0) { + assert(!stdio->input.f1); stdin_read_via_stream(&stdio->input); } - *out = (filesystem_tuple2_stream_u8_future_result_void_error_code_t *)&stdio - ->input; - *offs = NULL; + read->stream = stdio->input.f0; + read->offset = NULL; + read->blocking = true; + read->timeout = 0; + read->eof_data = data; + read->eof = stdin3_read_eof; return 0; } @@ -116,7 +175,7 @@ static int stdout3_isatty(void *data) { static descriptor_vtable_t stdin3_vtable = { .free = stdin3_free, - .get_read_stream3 = stdin3_read, + .get_read_stream = stdin3_read, .fstat = stdio3_fstat, .fcntl_getfl = stdin3_fcntl_getfl, .isatty = stdin3_isatty, @@ -124,7 +183,7 @@ static descriptor_vtable_t stdin3_vtable = { static descriptor_vtable_t stdout3_vtable = { .free = stdout3_free, - .get_write_stream3 = stdout3_write, + .get_write_stream = stdout3_write, .fstat = stdio3_fstat, .fcntl_getfl = stdout3_fcntl_getfl, .isatty = stdout3_isatty, diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f22db1c38..764fe5c11 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -257,48 +257,47 @@ 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(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(close.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) -add_wasilibc_test(fallocate.c FS FAILP3) -add_wasilibc_test(fcntl.c FS FAILP3) -add_wasilibc_test(fdatasync.c FS FAILP3) -add_wasilibc_test(fdopen.c FS FAILP3) -add_wasilibc_test(feof.c FS FAILP3) -add_wasilibc_test(file_permissions.c FS FAILP3) -add_wasilibc_test(file_nonblocking.c FS FAILP3) -add_wasilibc_test(fseek.c FS FAILP3) -add_wasilibc_test(fstat.c FS FAILP3) -add_wasilibc_test(fsync.c FS FAILP3) -add_wasilibc_test(ftruncate.c FS FAILP3) -add_wasilibc_test(fts.c FS FAILP3) -add_wasilibc_test(fwscanf.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) +add_wasilibc_test(fdopen.c FS) +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) +add_wasilibc_test(fsync.c FS) +add_wasilibc_test(ftruncate.c FS) +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!") -add_wasilibc_test(ioctl.c FS FAILP3) -add_wasilibc_test(isatty.c FS FAILP3) -add_wasilibc_test(link.c FS FAILP3) -add_wasilibc_test(lseek.c FS FAILP3) +add_wasilibc_test(ioctl.c FS) +add_wasilibc_test(isatty.c FS) +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) -add_wasilibc_test(opendir.c FS FAILP3 ARGV /) -add_wasilibc_test(open_relative_path.c FS FAILP3 ARGV /) +add_wasilibc_test(opendir.c FS 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 FAILP3) -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(stdio.c FS) +add_wasilibc_test(preadvwritev.c FS) +add_wasilibc_test(preadwrite.c FS) +add_wasilibc_test(readlink.c FS) +add_wasilibc_test(readv.c FS) +add_wasilibc_test(rename.c FS) +add_wasilibc_test(rmdir.c FS) +add_wasilibc_test(scandir.c FS) +add_wasilibc_test(stat.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) add_wasilibc_test(strptime.c) @@ -307,14 +306,38 @@ 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(rewinddir.c FS FAILP3) -add_wasilibc_test(seekdir.c FS FAILP3) +add_wasilibc_test(utime.c FS) +add_wasilibc_test(rewinddir.c FS) +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) +add_wasilibc_test(close-stdio.c) + +# Testing stdio is a bit special so handle it specially here. A single +# executable is built which is then piped into itself in a few situations to +# test stdio. +add_test_executable(stdio.wasm src/stdio.c) +add_test( + NAME stdio-close-output + COMMAND + ${CMAKE_COMMAND} + -DENGINE=${ENGINE} + -DWASM=$ + -DARG=close-output + -P ${CMAKE_CURRENT_SOURCE_DIR}/stdio-test.cmake +) +add_test( + NAME stdio-close-input + COMMAND + ${CMAKE_COMMAND} + -DENGINE=${ENGINE} + -DWASM=$ + -DARG=close-input + -P ${CMAKE_CURRENT_SOURCE_DIR}/stdio-test.cmake +) if (TARGET_TRIPLE MATCHES "-threads") add_wasilibc_test(busywait.c) diff --git a/test/src/close-stdio.c b/test/src/close-stdio.c new file mode 100644 index 000000000..6902e501c --- /dev/null +++ b/test/src/close-stdio.c @@ -0,0 +1,25 @@ +#include "test.h" +#include +#include +#include +#include +#include +#include +#include + +#define TEST(c) \ + do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ + } while (0) + +int main() { + // Test that closing stdin/stdout/stderr is not an error + + TEST(close(0) == 0); + TEST(close(1) == 0); + TEST(close(2) == 0); + + return t_status; +} diff --git a/test/src/stdio.c b/test/src/stdio.c index f769f60e8..9320d8019 100644 --- a/test/src/stdio.c +++ b/test/src/stdio.c @@ -6,6 +6,7 @@ #include #include #include +#include #define TEST(c) \ do { \ @@ -14,12 +15,62 @@ t_error("%s failed (errno = %d)\n", #c, errno); \ } while (0) -int main(void) { - // Test that closing stdin/stdout/stderr is not an error +static int close_input_writer(void) { + TEST(write(1, "hello world\n", 12) == 12); + TEST(close(1) == 0); + return t_status; +} + +static int close_input_reader(void) { + char buf[13]; + ssize_t n = read(0, buf, 12); + TEST(n == 12); + buf[12] = '\0'; + TEST(strcmp(buf, "hello world\n") == 0); + // further reads should fail as there's nothing left + TEST(read(0, buf, 12) == 0); TEST(close(0) == 0); + return t_status; +} + +static int close_output_writer(void) { + while (write(1, "hello world\n", 12) == 12) { + // ... write again on the next iteration ... + } TEST(close(1) == 0); - TEST(close(2) == 0); + return t_status; +} + +static int close_output_reader(void) { + // Read one message successfully... + char buf[13]; + ssize_t n = read(0, buf, 12); + TEST(n == 12); + buf[12] = '\0'; + TEST(strcmp(buf, "hello world\n") == 0); + // ... but then close out stdin to let the other end know we're hanging up. + TEST(close(0) == 0); return t_status; } + +int main(int argc, char **argv) { + TEST(argc == 3); + bool writer = argv[2][0] == 'a'; + + if (strcmp(argv[1], "close-input") == 0) { + if (writer) + return close_input_writer(); + return close_input_reader(); + } + + if (strcmp(argv[1], "close-output") == 0) { + if (writer) + return close_output_writer(); + return close_output_reader(); + } + + printf("unknown test: %s\n", argv[1]); + return 1; +} diff --git a/test/stdio-test.cmake b/test/stdio-test.cmake new file mode 100644 index 000000000..48f86e282 --- /dev/null +++ b/test/stdio-test.cmake @@ -0,0 +1,9 @@ +# TODO + +execute_process( + COMMAND ${ENGINE} -Sp3 -Wcomponent-model-async ${WASM} ${ARG} a + COMMAND ${ENGINE} -Sp3 -Wcomponent-model-async ${WASM} ${ARG} b + TIMEOUT 5 + COMMAND_ERROR_IS_FATAL ANY + COMMAND_ECHO STDOUT +)