Skip to content
Closed
1 change: 1 addition & 0 deletions expected/wasm32-wasip3/defined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1474,6 +1474,7 @@ wasip3_option_string_free
wasip3_string_dup
wasip3_string_dup_n
wasip3_string_free
wasip3_string_from_c
wasip3_string_set
wasip3_subtask_block_on
wasip3_subtask_cancel
Expand Down
2 changes: 1 addition & 1 deletion libc-bottom-half/cloudlibc/src/libc/dirent/dirent_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions libc-bottom-half/cloudlibc/src/libc/dirent/fdclosedir.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ int fdclosedir(DIR *dirp) {
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);
if (dirp->stream.f0 != 0)
filesystem_stream_directory_entry_drop_readable(dirp->stream.f0);
if (dirp->stream.f1 != 0)
filesystem_future_result_void_error_code_drop_readable(dirp->stream.f1);
#else
# error "Unsupported WASI version"
#endif
Expand Down
18 changes: 11 additions & 7 deletions libc-bottom-half/cloudlibc/src/libc/dirent/fdopendir.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#else
#endif

#ifdef __wasip3__
#include <wasi/wasip3_block.h>
#endif

#include "dirent_impl.h"

DIR *fdopendir(int fd) {
Expand Down Expand Up @@ -49,7 +53,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) {
Expand All @@ -58,6 +62,7 @@ DIR *fdopendir(int fd) {
}

// Read the directory
#ifdef __wasip2__
filesystem_own_directory_entry_stream_t result;
filesystem_error_code_t error_code;
bool ok = filesystem_method_descriptor_read_directory(file_handle,
Expand All @@ -69,18 +74,17 @@ DIR *fdopendir(int fd) {
return NULL;
}

dirp->fd = fd;
dirp->stream = result;
#elif defined(__wasip3__)
wasip3_subtask_status_t status = filesystem_method_descriptor_read_directory(file_handle, &dirp->stream);
wasip3_subtask_block_on(status);
#endif
dirp->fd = fd;
dirp->skip = 0;
dirp->offset = 0;
dirp->dirent = NULL;
dirp->dirent_size = 1;
return dirp;
#elif defined(__wasip3__)
// TODO(wasip3)
errno = ENOTSUP;
free(dirp);
return NULL;
#else
# error "Unsupported WASI version"
#endif
Expand Down
52 changes: 44 additions & 8 deletions libc-bottom-half/cloudlibc/src/libc/dirent/readdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ static_assert(DT_REG == __WASI_FILETYPE_REGULAR_FILE, "Value mismatch");
static_assert(DT_UNKNOWN == __WASI_FILETYPE_UNKNOWN, "Value mismatch");
#endif

#ifdef __wasip3__
#include <wasi/wasip3_block.h>
#endif

// Grows a buffer to be large enough to hold a certain amount of data.
#define GROW(buffer, buffer_size, target_size) \
do { \
Expand Down Expand Up @@ -140,12 +144,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;

Expand All @@ -157,6 +162,12 @@ 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) {
wasip3_subtask_status_t status = filesystem_method_descriptor_read_directory(*handle, &dirp->stream);
wasip3_subtask_block_on(status);
}
#endif
return 0;
}

Expand All @@ -173,13 +184,24 @@ static struct dirent *readdir_next(DIR *dirp) {
if (dirp->offset == 0) {
dirp->offset += 1;
GROW(dirp->dirent, dirp->dirent_size, offsetof(struct dirent, d_name) + 2);
#ifdef __wasip2__
bool ok = filesystem_method_descriptor_metadata_hash(dir_handle,
&metadata,
&error_code);
if (!ok) {
translate_error(error_code);
return NULL;
}
#else
filesystem_result_metadata_hash_value_error_code_t result;
wasip3_subtask_status_t status = filesystem_method_descriptor_metadata_hash(dir_handle, &result);
wasip3_subtask_block_on(status);
if (result.is_err) {
translate_error(result.val.err);
return NULL;
}
metadata = result.val.ok;
#endif
dirp->dirent->d_ino = metadata.lower;
dirp->dirent->d_type = DT_DIR;
dirp->dirent->d_name[0] = '.';
Expand All @@ -200,6 +222,7 @@ static struct dirent *readdir_next(DIR *dirp) {
return dirp->dirent;
}

#ifdef __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,
Expand All @@ -216,6 +239,14 @@ 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;
wasip3_waitable_status_t status = filesystem_stream_directory_entry_read(dirp->stream.f0, &dir_entry, 1);
ssize_t amount = wasip3_waitable_block_on(status, dirp->stream.f0);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/ssize_t/size_t/

if (amount<1)
return NULL;
Comment on lines +246 to +247
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upon reaching end-of-stream this'll want to block on the future-of-result to see if an error is going to be returned

#endif

// Ensure that the dirent is large enough to fit the filename
size_t the_size = offsetof(struct dirent, d_name);
GROW(dirp->dirent, dirp->dirent_size, the_size + dir_entry.name.len + 1);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is preexisting, but I'm realizing now that this GROW can leak memory because it can return-early on OOM which would leak dir_entry which has an owned string internally.

I'll file an issue to fix that.

Expand All @@ -227,6 +258,7 @@ static struct dirent *readdir_next(DIR *dirp) {

// Fill out `d_ino` with the metadata hash.
filesystem_path_flags_t path_flags = 0; // Don't follow symlinks
#ifdef __wasip2__
ok = filesystem_method_descriptor_metadata_hash_at(dir_handle,
path_flags,
&dir_entry.name,
Expand All @@ -237,6 +269,17 @@ static struct dirent *readdir_next(DIR *dirp) {
translate_error(error_code);
return NULL;
}
#else
filesystem_result_metadata_hash_value_error_code_t result;
status = filesystem_method_descriptor_metadata_hash_at(dir_handle, path_flags, dir_entry.name, &result);
wasip3_subtask_block_on(status);
//wasip3_string_free(&dir_entry.name);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debugging perhaps? (I think this is needed right?)

if (result.is_err) {
translate_error(result.val.err);
return NULL;
}
metadata = result.val.ok;
#endif
dirp->dirent->d_ino = metadata.lower;
dirp->offset += 1;

Expand All @@ -251,13 +294,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
9 changes: 8 additions & 1 deletion libc-bottom-half/cloudlibc/src/libc/dirent/rewinddir.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@ void rewinddir(DIR *dirp) {
dirp->skip = 0;
dirp->offset = 0;
#elif defined(__wasip3__)
dirp->stream = 0;
if (dirp->stream.f0 != 0) {
filesystem_stream_directory_entry_drop_readable(dirp->stream.f0);
dirp->stream.f0 = 0;
}
Comment on lines +21 to +24
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like below could this update the wasip2 branch above too to close the previous handle if present?

if (dirp->stream.f1 != 0) {
filesystem_future_result_void_error_code_drop_readable(dirp->stream.f1);
dirp->stream.f1 = 0;
}
dirp->skip = 0;
dirp->offset = 0;
#else
Expand Down
9 changes: 8 additions & 1 deletion libc-bottom-half/cloudlibc/src/libc/dirent/seekdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@ void seekdir(DIR *dirp, long loc) {
dirp->skip = loc;
dirp->offset = 0;
#elif defined(__wasip3__)
dirp->stream = 0;
if (dirp->stream.f0 != 0) {
filesystem_stream_directory_entry_drop_readable(dirp->stream.f0);
dirp->stream.f0 = 0;
}
Comment on lines +21 to +24
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is actually a bug of the wasip2 implementation where it doesn't close the previous handle on a call to seekdir. Could you update the wasip2 block above as well? Unfortunately hard to add a test for...

if (dirp->stream.f1 != 0) {
filesystem_future_result_void_error_code_drop_readable(dirp->stream.f1);
dirp->stream.f1 = 0;
}
dirp->skip = loc;
dirp->offset = 0;
#else
Expand Down
32 changes: 28 additions & 4 deletions libc-bottom-half/cloudlibc/src/libc/fcntl/openat.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
#include <common/errors.h>
#endif

#ifdef __wasip3__
#include <wasi/wasip3_block.h>
#endif

#ifdef __wasip1__
static_assert(O_APPEND == __WASI_FDFLAGS_APPEND, "Value mismatch");
static_assert(O_DSYNC == __WASI_FDFLAGS_DSYNC, "Value mismatch");
Expand Down Expand Up @@ -87,7 +91,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)
Expand Down Expand Up @@ -140,6 +144,7 @@ int __wasilibc_nocwd_openat_nomode(int fd, const char *path, int oflag) {
return -1;

// Construct a WASI string for the path
#ifdef __wasip2__
wasip2_string_t path2;
if (wasip2_string_from_c(path, &path2) < 0)
return -1;
Expand All @@ -162,9 +167,28 @@ 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__)
// TODO(wasip3)
errno = ENOTSUP;
return -1;
wasip3_string_t path3;
if (wasip3_string_from_c(path, &path3) < 0)
return -1;

// Open the file, yielding a new handle
filesystem_method_descriptor_open_at_args_t args;
args.self = file_handle;
args.flags = lookup_flags;
args.path = path3;
args.open_flags = open_flags;
args.path_flags = fs_flags;
filesystem_result_own_descriptor_error_code_t result;
wasip3_subtask_status_t status = filesystem_method_descriptor_open_at(&args, &result);
wasip3_subtask_block_on(status);
if (result.is_err) {
translate_error(result.val.err);
return -1;
}

// Update the descriptor table with the new handle
return __wasilibc_add_file(result.val.ok, oflag);
#endif
#else
# error "Unsupported WASI version"
#endif
Expand Down
6 changes: 1 addition & 5 deletions libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -39,10 +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__)
// TODO(wasip3)
errno = ENOTSUP;
return -1;
#else
# error "Unknown WASI version"
#endif
Expand Down
3 changes: 3 additions & 0 deletions libc-bottom-half/headers/private/wasi/file_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ static int wasip2_handle_write_error(streams_stream_error_t error) {
// 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
#ifdef __wasip3__
int wasip3_string_from_c(const char *s, wasip3_string_t* out);
#endif

#if defined(__wasip2__) || defined(__wasip3__)
// Succeed only if fd is bound to a file handle in the descriptor table
Expand Down
6 changes: 1 addition & 5 deletions libc-bottom-half/sources/__wasilibc_tell.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -29,10 +29,6 @@ off_t __wasilibc_tell(int fildes) {
return -1;
}
return entry->vtable->seek(entry->data, 0, SEEK_CUR);
#elif defined(__wasip3__)
// TODO(wasip3)
errno = ENOTSUP;
return -1;
#else
#error "Unsupported WASI version"
#endif
Expand Down
Loading