diff --git a/cmake/bindings.cmake b/cmake/bindings.cmake index ed1236ec0..529d41f28 100644 --- a/cmake/bindings.cmake +++ b/cmake/bindings.cmake @@ -107,6 +107,17 @@ 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.get-flags" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.open-at" + "--async=-wasi:filesystem/types@${wasip3-version}#[method]descriptor.read-directory" + "--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 850cfee4a..144ff7d82 100644 --- a/expected/wasm32-wasip3/defined-symbols.txt +++ b/expected/wasm32-wasip3/defined-symbols.txt @@ -302,6 +302,7 @@ __wasilibc_fd_renumber __wasilibc_find_abspath __wasilibc_find_relpath __wasilibc_find_relpath_alloc +__wasilibc_future_block_on __wasilibc_get_environ __wasilibc_get_service_entry_by_name __wasilibc_get_service_entry_by_port @@ -339,6 +340,8 @@ __wasilibc_rmdirat __wasilibc_sockaddr_to_wasi __wasilibc_sockaddr_validate __wasilibc_stat +__wasilibc_stream_block_on +__wasilibc_subtask_block_on_and_drop __wasilibc_tell __wasilibc_unlinkat __wasilibc_unspecified_addr @@ -1463,6 +1466,7 @@ vswprintf vswscanf vwprintf vwscanf +wasi_string_from_c wasip3_backpressure_dec wasip3_backpressure_inc wasip3_context_get_0 @@ -1477,7 +1481,6 @@ wasip3_string_dup wasip3_string_dup_n wasip3_string_free wasip3_string_set -wasip3_subtask_block_on wasip3_subtask_cancel wasip3_subtask_drop wasip3_task_cancel @@ -1495,7 +1498,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 4bdce3ff8..5cd333930 100644 --- a/libc-bottom-half/CMakeLists.txt +++ b/libc-bottom-half/CMakeLists.txt @@ -140,6 +140,7 @@ else() sources/getsockpeername.c sources/listen.c sources/file_utils.c + sources/file.c sources/recv.c sources/send.c sources/shutdown.c @@ -155,7 +156,6 @@ if(WASI STREQUAL "p2") list(APPEND bottom_half_sources sources/netdb.c sources/wasip2.c - sources/wasip2_file.c sources/wasip2_stdio.c ) endif() @@ -164,7 +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_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..7febd3112 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,7 @@ 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; size_t skip; size_t offset; #else @@ -40,4 +40,27 @@ struct _DIR { size_t dirent_size; }; +static inline void dirent_close_streams(DIR *dirp) { +#if defined(__wasip1__) + (void) dirp; + // 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; + } + 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..edd0476fd 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,16 @@ DIR *fdopendir(int fd) { return NULL; } - dirp->fd = fd; dirp->stream = result; +#elif defined(__wasip3__) + filesystem_method_descriptor_read_directory(file_handle, &dirp->stream); +#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..96d379d3b 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,54 @@ 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; + + // Loop until at least one stream entry is read, or until the stream is closed. + bool closed = false; + while (1) { + size_t amount = + __wasilibc_stream_block_on( + filesystem_stream_directory_entry_read(dirp->stream.f0, &dir_entry, 1), + dirp->stream.f0, + &closed); + + // If something was read, then break out and process that below. + if (amount > 0) + break; + + // If nothing was read and the stream isn't finished yet, try again. + if (!closed) + 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; + __wasilibc_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. This'll set `errno` based on the + // result of the future above. + 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 +294,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 +317,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/stdio/renameat.c b/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c index c2b4801d6..39d2730ad 100644 --- a/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c +++ b/libc-bottom-half/cloudlibc/src/libc/stdio/renameat.c @@ -31,9 +31,9 @@ int __wasilibc_nocwd_renameat(int oldfd, const char *old, int newfd, const char // Convert the strings into WASI strings wasip2_string_t old_path, new_path; - if (wasip2_string_from_c(old, &old_path) < 0) + 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 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..7d8561edb 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c @@ -43,7 +43,7 @@ int __wasilibc_nocwd_fstatat(int fd, const char *restrict path, struct stat *res // Convert the string into a Wasm string wasip2_string_t path_wasm_string; - if (wasip2_string_from_c(path, &path_wasm_string) < 0) + if (wasi_string_from_c(path, &path_wasm_string) < 0) return -1; // Get the metadata hash for this file 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..52f9fef26 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c @@ -30,7 +30,7 @@ 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) + if (wasi_string_from_c(path, &path2) < 0) return -1; bool ok = filesystem_method_descriptor_create_directory_at(file_handle, &path2, 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..4be2d0a1e 100644 --- a/libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c +++ b/libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c @@ -59,7 +59,7 @@ int __wasilibc_nocwd_utimensat(int fd, const char *path, const struct timespec t // Convert the string into a Wasm string wasip2_string_t path_wasm_string; - if (wasip2_string_from_c(path, &path_wasm_string) < 0) + if (wasi_string_from_c(path, &path_wasm_string) < 0) return -1; // Perform system call. 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..38a48945f 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c @@ -64,7 +64,7 @@ int __wasilibc_nocwd_faccessat(int fd, const char *path, int amode, int flag) { // Convert the string into a WASI string wasip2_string_t wasi_path; - if (wasip2_string_from_c(path, &wasi_path) < 0) + if (wasi_string_from_c(path, &wasi_path) < 0) return -1; // Call stat() to check if the file exists diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c index 8d1184768..2cbd27dc1 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/linkat.c @@ -36,9 +36,9 @@ int __wasilibc_nocwd_linkat(int fd1, const char *path1, int fd2, const char *pat // Convert the strings into WASI strings wasip2_string_t path1_wasi, path2_wasi; - if (wasip2_string_from_c(path1, &path1_wasi) < 0) + 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 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/read.c b/libc-bottom-half/cloudlibc/src/libc/unistd/read.c index 36f2241ce..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}; diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c index a8339d7a6..656b9c501 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/readlinkat.c @@ -31,7 +31,7 @@ ssize_t __wasilibc_nocwd_readlinkat(int fd, const char *restrict path, char *res // Convert the path into a WASI path wasip2_string_t wasi_path, link_source; - if (wasip2_string_from_c(path, &wasi_path) < 0) + if (wasi_string_from_c(path, &wasi_path) < 0) return -1; // Read the link diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c b/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c index f727f8786..96aea65be 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/symlinkat.c @@ -27,9 +27,9 @@ int __wasilibc_nocwd_symlinkat(const char *path1, int fd, const char *path2) { // Convert the paths into WASI paths wasip2_string_t path1_wasi, path2_wasi; - if (wasip2_string_from_c(path1, &path1_wasi) < 0) + 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 diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/write.c b/libc-bottom-half/cloudlibc/src/libc/unistd/write.c index ca191910b..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}; diff --git a/libc-bottom-half/headers/private/wasi/descriptor_table.h b/libc-bottom-half/headers/private/wasi/descriptor_table.h index e7841aeb5..4867a3e6f 100644 --- a/libc-bottom-half/headers/private/wasi/descriptor_table.h +++ b/libc-bottom-half/headers/private/wasi/descriptor_table.h @@ -45,11 +45,14 @@ typedef struct wasi_write_t { 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; - // 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; + // 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; diff --git a/libc-bottom-half/headers/private/wasi/file_utils.h b/libc-bottom-half/headers/private/wasi/file_utils.h index 11dc1e9eb..cd6f7dded 100644 --- a/libc-bottom-half/headers/private/wasi/file_utils.h +++ b/libc-bottom-half/headers/private/wasi/file_utils.h @@ -38,16 +38,22 @@ 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); // 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) { diff --git a/libc-bottom-half/headers/private/wasi/wasip3_block.h b/libc-bottom-half/headers/private/wasi/wasip3_block.h index a7dcf4a9a..27ae486f3 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 __wasilibc_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 __wasilibc_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 __wasilibc_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..cb1aa21df 100644 --- a/libc-bottom-half/headers/public/wasi/__generated_wasip3.h +++ b/libc-bottom-half/headers/public/wasi/__generated_wasip3.h @@ -593,13 +593,6 @@ typedef struct filesystem_method_descriptor_link_at_args { 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; @@ -1014,9 +1007,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. @@ -1087,7 +1080,7 @@ extern wasip3_subtask_status_t filesystem_method_descriptor_sync_data(filesystem // // 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` @@ -1122,7 +1115,7 @@ 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 @@ -1143,7 +1136,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 @@ -1179,7 +1172,7 @@ 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 @@ -1235,12 +1228,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..50bfef338 100644 --- a/libc-bottom-half/sources/__wasilibc_rmdirat.c +++ b/libc-bottom-half/sources/__wasilibc_rmdirat.c @@ -23,7 +23,7 @@ int __wasilibc_nocwd___wasilibc_rmdirat(int fd, const char *path) { // Create a WASI string for the path wasip2_string_t wasi_path; - if (wasip2_string_from_c(path, &wasi_path) < 0) + if (wasi_string_from_c(path, &wasi_path) < 0) return -1; filesystem_error_code_t error_code; 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..7bd2cde8e 100644 --- a/libc-bottom-half/sources/__wasilibc_unlinkat.c +++ b/libc-bottom-half/sources/__wasilibc_unlinkat.c @@ -34,7 +34,7 @@ int __wasilibc_nocwd___wasilibc_unlinkat(int fd, const char *path) { // Create a Wasm string from the path wasip2_string_t wasi_path; - if (wasip2_string_from_c(path, &wasi_path) < 0) + if (wasi_string_from_c(path, &wasi_path) < 0) return -1; // Unlink the file diff --git a/libc-bottom-half/sources/wasip2_file.c b/libc-bottom-half/sources/file.c similarity index 71% rename from libc-bottom-half/sources/wasip2_file.c rename to libc-bottom-half/sources/file.c index 7da5cb8a3..ad7119c69 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,31 @@ 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 closing the stream above is enough to have + // the subtask here finish promptly, so block on the result. + // + // Once Wasmtime 43.0.0 is released and used in wasi-libc's CI that can be + // used here instead. + __wasilibc_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 +87,29 @@ static void file_free(void *data) { free(file); } +#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; + __wasilibc_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 +121,42 @@ static int file_get_read_stream(void *data, wasi_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; } +#ifndef __wasip2__ +static int file_write_eof(void *data) { + file_t *file = (file_t *)data; + + if (file->write_subtask != 0) { + __wasilibc_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 +176,24 @@ static int file_get_write_stream(void *data, wasi_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 = + 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 +354,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/file_utils.c b/libc-bottom-half/sources/file_utils.c index 9c2a50fbc..48555c329 100644 --- a/libc-bottom-half/sources/file_utils.c +++ b/libc-bottom-half/sources/file_utils.c @@ -6,7 +6,6 @@ #include #include -#ifdef __wasip2__ /** * 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; @@ -82,7 +81,6 @@ int wasip2_string_from_c(const char *s, wasip2_string_t *out) { out->len = len; return 0; } -#endif ssize_t __wasilibc_write(wasi_write_t *write, const void *buffer, size_t length) { @@ -161,28 +159,22 @@ ssize_t __wasilibc_write(wasi_write_t *write, const void *buffer, } } #elif defined(__wasip3__) - if (WASIP3_SUBTASK_STATE(*write->subtask) == WASIP3_SUBTASK_STARTING || - WASIP3_SUBTASK_STATE(*write->subtask) == WASIP3_SUBTASK_STARTED) { - // the stream is still active - wasip3_waitable_status_t status = - filesystem_stream_u8_write(write->output, buffer, length); - size_t amount = wasip3_waitable_block_on(status, write->output); + 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 = __wasilibc_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; } - // error or eof - wasip3_subtask_block_on(*write->subtask); - wasip3_subtask_drop(*write->subtask); - *write->subtask = WASIP3_SUBTASK_RETURNED; } - if (write->pending_result.is_err) { - translate_error(write->pending_result.val.err); - return -1; - } - // EOF - return 0; + return write->eof(write->eof_data); #else #error "Unknown WASI version" #endif @@ -253,13 +245,21 @@ ssize_t __wasilibc_read(wasi_read_t *read, void *buffer, size_t length) { } } #elif defined(__wasip3__) - wasip3_waitable_status_t status = - filesystem_stream_u8_read(read->stream, buffer, length); - size_t amount = wasip3_waitable_block_on(status, read->stream); - if (amount > 0 || length == 0) { - if (read->offset) - *read->offset += amount; - return amount; + assert(read->blocking); // TODO(wasip3) + assert(read->timeout == 0); // TODO(wasip3) + + // Attempt reads until a nonzero-length read is encountered or the stream is + // closed. + bool closed = false; + while (!closed) { + size_t amount = __wasilibc_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 diff --git a/libc-bottom-half/sources/wasip3.c b/libc-bottom-half/sources/wasip3.c index 8b0f3d960..8e25f23b5 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` @@ -88,8 +88,8 @@ extern int32_t __wasm_import_filesystem_method_descriptor_advise(int32_t, int64_ __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__("[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 *); @@ -100,8 +100,8 @@ extern int32_t __wasm_import_filesystem_method_descriptor_set_size(int32_t, int6 __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__("[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 *); @@ -109,8 +109,8 @@ extern int32_t __wasm_import_filesystem_method_descriptor_sync(int32_t, uint8_t __attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[async-lower][method]descriptor.create-directory-at"))) extern int32_t __wasm_import_filesystem_method_descriptor_create_directory_at(int32_t, uint8_t *, size_t, uint8_t *); -__attribute__((__import_module__("wasi:filesystem/types@0.3.0-rc-2026-01-06"), __import_name__("[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 *); @@ -121,8 +121,8 @@ extern int32_t __wasm_import_filesystem_method_descriptor_set_times_at(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__("[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 *); @@ -142,11 +142,11 @@ extern int32_t __wasm_import_filesystem_method_descriptor_unlink_file_at(int32_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) { @@ -1434,8 +1434,31 @@ wasip3_subtask_status_t filesystem_method_descriptor_sync_data(filesystem_borrow return __wasm_import_filesystem_method_descriptor_sync_data((self).__handle, (uint8_t*) result); } -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) { @@ -1450,8 +1473,15 @@ wasip3_subtask_status_t filesystem_method_descriptor_set_times(filesystem_method return __wasm_import_filesystem_method_descriptor_set_times((uint8_t*) args, (uint8_t*) result); } -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) { @@ -1462,8 +1492,84 @@ wasip3_subtask_status_t filesystem_method_descriptor_create_directory_at(filesys return __wasm_import_filesystem_method_descriptor_create_directory_at((self).__handle, (uint8_t *) (path).ptr, (path).len, (uint8_t*) result); } -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) { @@ -1478,8 +1584,31 @@ wasip3_subtask_status_t filesystem_method_descriptor_link_at(filesystem_method_d return __wasm_import_filesystem_method_descriptor_link_at((uint8_t*) args, (uint8_t*) result); } -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) { @@ -1506,12 +1635,64 @@ wasip3_subtask_status_t filesystem_method_descriptor_is_same_object(filesystem_b 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..ca7ffdc7f 100644 --- a/libc-bottom-half/sources/wasip3_block_on.c +++ b/libc-bottom-half/sources/wasip3_block_on.c @@ -5,49 +5,53 @@ #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 __wasilibc_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 __wasilibc_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 __wasilibc_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_stdio.c b/libc-bottom-half/sources/wasip3_stdio.c index 3104f2def..370704420 100644 --- a/libc-bottom-half/sources/wasip3_stdio.c +++ b/libc-bottom-half/sources/wasip3_stdio.c @@ -23,7 +23,8 @@ typedef struct { // contains stream, result storage and result subtask wasip3_subtask_t subtask; stdin_stream_u8_writer_t output; - stdin_result_void_error_code_t pending_result; + 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) @@ -33,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) @@ -51,53 +69,57 @@ static void stdout3_free(void *data) { if (stdio->output) stdin_stream_u8_drop_writable(stdio->output); if (stdio->subtask) - wasip3_subtask_block_on(stdio->subtask); + __wasilibc_subtask_block_on_and_drop(stdio->subtask); free(stdio); } +static int stdout3_write_eof(void *data) { + stdout3_t *stdio = (stdout3_t *)data; + if (stdio->subtask != 0) { + __wasilibc_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); - stdio->subtask = (*stdio->stream_func)( - read_side, (stdout_result_void_error_code_t *)&stdio->pending_result); - // subtask will be checked by write for error before writing + 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; - stdin_result_void_error_code_t result; - wasip3_waitable_status_t status = - stdin_future_result_void_error_code_read(stdio->input.f1, &result); - size_t amt = wasip3_waitable_block_on(status, stdio->input.f1); - assert(amt == 1); - (void) amt; - stdin_future_result_void_error_code_drop_readable(stdio->input.f1); - stdio->input.f1 = 0; - if (result.is_err) { - switch (result.val.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; + if (stdio->input.f1 != 0) { + stdin_result_void_error_code_t result; + __wasilibc_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; } - return -1; } return 0; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f22db1c38..10995f2a3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -263,37 +263,37 @@ add_wasilibc_test(append.c FS FAILP3) 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(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(feof.c FS) add_wasilibc_test(file_permissions.c FS FAILP3) -add_wasilibc_test(file_nonblocking.c FS FAILP3) +add_wasilibc_test(file_nonblocking.c FS) 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(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(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(opendir.c FS ARGV /) add_wasilibc_test(open_relative_path.c FS FAILP3 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(readv.c FS) add_wasilibc_test(rename.c FS FAILP3) add_wasilibc_test(rmdir.c FS FAILP3) add_wasilibc_test(scandir.c FS FAILP3)