Implement the remaining Windows filesystem functions (#3166)

Now that the filesystem implementation is now complete, the previous
test filters on Windows can be removed. Some of the tests only pass when
certain environment variables have been set on Windows so an extra step
has been added in the wasi test runner script to modify the test config
files before the tests begin.
This commit is contained in:
zoraaver 2024-02-28 03:02:42 +00:00 committed by GitHub
parent 4f6d70bc52
commit 92bd3ba17d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 463 additions and 114 deletions

View File

@ -213,14 +213,6 @@ has_symlink_attribute(DWORD attributes)
return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
}
static bool
is_symlink(const wchar_t *path)
{
DWORD attributes = GetFileAttributesW(path);
return has_symlink_attribute(attributes);
}
static void
init_dir_stream(os_dir_stream dir_stream, os_file_handle handle)
{
@ -229,6 +221,13 @@ init_dir_stream(os_dir_stream dir_stream, os_file_handle handle)
dir_stream->cookie = 0;
}
static void
reset_dir_stream(os_dir_stream dir_stream)
{
dir_stream->cursor = 0;
dir_stream->cookie = 0;
}
// Advances to the next directory entry and optionally reads into to the
// provided buffer if not NULL.
static __wasi_errno_t
@ -562,7 +561,32 @@ os_fstatat(os_file_handle handle, const char *path,
{
CHECK_VALID_FILE_HANDLE(handle);
return __WASI_ENOSYS;
wchar_t absolute_path[PATH_MAX];
__wasi_errno_t error = get_absolute_filepath(handle->raw.handle, path,
absolute_path, PATH_MAX);
if (error != __WASI_ESUCCESS)
return error;
windows_handle resolved_handle = {
.type = windows_handle_type_file,
.fdflags = 0,
.raw = { .handle = create_handle(
absolute_path, is_directory(absolute_path),
((lookup_flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0),
true) },
.access_mode = windows_access_mode_read
};
if (resolved_handle.raw.handle == INVALID_HANDLE_VALUE)
return convert_windows_error_code(GetLastError());
error = get_file_information(&resolved_handle, buf);
CloseHandle(resolved_handle.raw.handle);
return error;
}
__wasi_errno_t
@ -579,7 +603,33 @@ os_file_set_fdflags(os_file_handle handle, __wasi_fdflags_t flags)
{
CHECK_VALID_HANDLE(handle);
return __WASI_ENOSYS;
if (handle->type == windows_handle_type_socket
&& (((handle->fdflags ^ flags) & __WASI_FDFLAG_NONBLOCK) != 0)) {
u_long non_block = flags & __WASI_FDFLAG_NONBLOCK;
int ret = ioctlsocket(handle->raw.socket, (long)FIONBIO, &non_block);
if (ret != 0)
return convert_winsock_error_code(WSAGetLastError());
if (non_block)
handle->fdflags |= __WASI_FDFLAG_NONBLOCK;
else
handle->fdflags &= ~__WASI_FDFLAG_NONBLOCK;
return __WASI_ESUCCESS;
}
// It's not supported setting FILE_FLAG_WRITE_THROUGH or
// FILE_FLAG_NO_BUFFERING via SetFileAttributes so __WASI_FDFLAG_APPEND is
// the only flags we can do anything with.
if (((handle->fdflags ^ flags) & __WASI_FDFLAG_APPEND) != 0) {
if ((flags & __WASI_FDFLAG_APPEND) != 0)
handle->fdflags |= __WASI_FDFLAG_APPEND;
else
handle->fdflags &= ~__WASI_FDFLAG_APPEND;
}
return __WASI_ESUCCESS;
}
__wasi_errno_t
@ -599,12 +649,21 @@ os_file_get_access_mode(os_file_handle handle,
return __WASI_ESUCCESS;
}
static __wasi_errno_t
flush_file_buffers_on_handle(HANDLE handle)
{
bool success = FlushFileBuffers(handle);
return success ? __WASI_ESUCCESS
: convert_windows_error_code(GetLastError());
}
__wasi_errno_t
os_fdatasync(os_file_handle handle)
{
CHECK_VALID_FILE_HANDLE(handle);
return __WASI_ENOSYS;
return flush_file_buffers_on_handle(handle->raw.handle);
}
__wasi_errno_t
@ -612,7 +671,7 @@ os_fsync(os_file_handle handle)
{
CHECK_VALID_FILE_HANDLE(handle);
return __WASI_ENOSYS;
return flush_file_buffers_on_handle(handle->raw.handle);
}
__wasi_errno_t
@ -680,16 +739,6 @@ os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags,
__wasi_errno_t error = __WASI_ESUCCESS;
DWORD access_flags = 0;
if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) {
if ((attributes & (FILE_FLAG_NO_BUFFERING)) != 0) {
// FILE_APPEND_DATA and FILE_FLAG_NO_BUFFERING are mutually
// exclusive - CreateFile2 returns 87 (invalid parameter) when they
// are combined.
error = __WASI_ENOTSUP;
goto fail;
}
access_flags |= FILE_APPEND_DATA;
}
switch (access_mode) {
case WASI_LIBC_ACCESS_MODE_READ_ONLY:
@ -743,14 +792,30 @@ os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags,
if ((lookup_flags & __WASI_LOOKUP_SYMLINK_FOLLOW) == 0)
attributes |= FILE_FLAG_OPEN_REPARSE_POINT;
// Check that we're not trying to open an existing file as a directory.
// Windows doesn't seem to throw an error in this case so add an
// explicit check.
if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0
&& creation_disposition == OPEN_EXISTING
&& !is_directory(absolute_path)) {
error = __WASI_ENOTDIR;
goto fail;
// Windows doesn't seem to throw an error for the following cases where the
// file/directory already exists so add explicit checks.
if (creation_disposition == OPEN_EXISTING) {
DWORD file_attributes = GetFileAttributesW(absolute_path);
if (file_attributes != INVALID_FILE_ATTRIBUTES) {
bool is_dir = file_attributes & FILE_ATTRIBUTE_DIRECTORY;
bool is_symlink = file_attributes & FILE_ATTRIBUTE_REPARSE_POINT;
// Check that we're not trying to open an existing file/symlink as a
// directory.
if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0
&& (!is_dir || is_symlink)) {
error = __WASI_ENOTDIR;
goto fail;
}
// Check that we're not trying to open an existing symlink with
// O_NOFOLLOW.
if ((file_attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0
&& (lookup_flags & __WASI_LOOKUP_SYMLINK_FOLLOW) == 0) {
error = __WASI_ELOOP;
goto fail;
}
}
}
CREATEFILE2_EXTENDED_PARAMETERS create_params;
@ -1035,7 +1100,31 @@ os_fallocate(os_file_handle handle, __wasi_filesize_t offset,
{
CHECK_VALID_FILE_HANDLE(handle);
return __WASI_ENOSYS;
LARGE_INTEGER current_file_size;
int ret = GetFileSizeEx(handle->raw.handle, &current_file_size);
if (ret == 0)
return convert_windows_error_code(GetLastError());
if (offset > INT64_MAX || length > INT64_MAX || offset + length > INT64_MAX)
return __WASI_EINVAL;
// The best we can do here is to increase the size of the file if it's less
// than the offset + length.
const LONGLONG requested_size = (LONGLONG)(offset + length);
FILE_END_OF_FILE_INFO end_of_file_info;
end_of_file_info.EndOfFile.QuadPart = requested_size;
if (requested_size <= current_file_size.QuadPart)
return __WASI_ESUCCESS;
bool success =
SetFileInformationByHandle(handle->raw.handle, FileEndOfFileInfo,
&end_of_file_info, sizeof(end_of_file_info));
return success ? __WASI_ESUCCESS
: convert_windows_error_code(GetLastError());
}
__wasi_errno_t
@ -1043,7 +1132,42 @@ os_ftruncate(os_file_handle handle, __wasi_filesize_t size)
{
CHECK_VALID_FILE_HANDLE(handle);
return __WASI_ENOSYS;
FILE_END_OF_FILE_INFO end_of_file_info;
end_of_file_info.EndOfFile.QuadPart = (LONGLONG)size;
bool success =
SetFileInformationByHandle(handle->raw.handle, FileEndOfFileInfo,
&end_of_file_info, sizeof(end_of_file_info));
return success ? __WASI_ESUCCESS
: convert_windows_error_code(GetLastError());
}
static __wasi_errno_t
set_file_times(HANDLE handle, __wasi_timestamp_t access_time,
__wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags)
{
FILETIME atim = { 0, 0 };
FILETIME mtim = { 0, 0 };
if ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0) {
atim = convert_wasi_timestamp_to_filetime(access_time);
}
else if ((fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0) {
GetSystemTimePreciseAsFileTime(&atim);
}
if ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0) {
mtim = convert_wasi_timestamp_to_filetime(modification_time);
}
else if ((fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0) {
GetSystemTimePreciseAsFileTime(&mtim);
}
bool success = SetFileTime(handle, NULL, &atim, &mtim);
return success ? __WASI_ESUCCESS
: convert_windows_error_code(GetLastError());
}
__wasi_errno_t
@ -1052,7 +1176,8 @@ os_futimens(os_file_handle handle, __wasi_timestamp_t access_time,
{
CHECK_VALID_FILE_HANDLE(handle);
return __WASI_ENOSYS;
return set_file_times(handle->raw.handle, access_time, modification_time,
fstflags);
}
__wasi_errno_t
@ -1063,7 +1188,26 @@ os_utimensat(os_file_handle handle, const char *path,
{
CHECK_VALID_FILE_HANDLE(handle);
return __WASI_ENOSYS;
wchar_t absolute_path[PATH_MAX];
__wasi_errno_t error = get_absolute_filepath(handle->raw.handle, path,
absolute_path, PATH_MAX);
if (error != __WASI_ESUCCESS)
return error;
HANDLE resolved_handle = create_handle(
absolute_path, is_directory(absolute_path),
(lookup_flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0, false);
if (resolved_handle == INVALID_HANDLE_VALUE)
return convert_windows_error_code(GetLastError());
error = set_file_times(resolved_handle, access_time, modification_time,
fstflags);
CloseHandle(resolved_handle);
return error;
}
__wasi_errno_t
@ -1213,7 +1357,7 @@ os_readlinkat(os_file_handle handle, const char *path, char *buf,
}
#else
error = __WASI_ENOTSUP;
#endif
#endif /* end of WINAPI_PARTITION_DESKTOP == 0 */
fail:
CloseHandle(link_handle);
return error;
@ -1224,18 +1368,96 @@ os_linkat(os_file_handle from_handle, const char *from_path,
os_file_handle to_handle, const char *to_path,
__wasi_lookupflags_t lookup_flags)
{
#if WINAPI_PARTITION_DESKTOP == 0
return __WASI_ENOSYS;
#else
CHECK_VALID_FILE_HANDLE(from_handle);
CHECK_VALID_FILE_HANDLE(to_handle);
return __WASI_ENOSYS;
wchar_t absolute_from_path[PATH_MAX];
__wasi_errno_t error = get_absolute_filepath(
from_handle->raw.handle, from_path, absolute_from_path, PATH_MAX);
if (error != __WASI_ESUCCESS)
return error;
wchar_t absolute_to_path[PATH_MAX];
error = get_absolute_filepath(to_handle->raw.handle, to_path,
absolute_to_path, PATH_MAX);
if (error != __WASI_ESUCCESS)
return error;
size_t to_path_len = strlen(to_path);
// Windows doesn't throw an error in the case that the new path has a
// trailing slash but the target to link to is a file.
if (to_path[to_path_len - 1] == '/'
|| to_path[to_path_len - 1] == '\\'
&& !is_directory(absolute_from_path)) {
return __WASI_ENOENT;
}
int ret = CreateHardLinkW(absolute_to_path, absolute_from_path, NULL);
if (ret == 0)
error = convert_windows_error_code(GetLastError());
return error;
#endif /* end of WINAPI_PARTITION_DESKTOP == 0 */
}
__wasi_errno_t
os_symlinkat(const char *old_path, os_file_handle handle, const char *new_path)
{
#if WINAPI_PARTITION_DESKTOP == 0
return __WASI_ENOSYS;
#else
CHECK_VALID_FILE_HANDLE(handle);
return __WASI_ENOSYS;
wchar_t absolute_new_path[PATH_MAX];
__wasi_errno_t error = get_absolute_filepath(handle->raw.handle, new_path,
absolute_new_path, PATH_MAX);
if (error != __WASI_ESUCCESS)
return error;
DWORD target_type = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
wchar_t old_wpath[PATH_MAX];
size_t old_path_len = 0;
error = convert_to_wchar(old_path, old_wpath, PATH_MAX);
if (error != __WASI_ESUCCESS)
goto fail;
wchar_t absolute_old_path[PATH_MAX];
error = get_absolute_filepath(handle->raw.handle, old_path,
absolute_old_path, PATH_MAX);
if (error != __WASI_ESUCCESS)
goto fail;
if (is_directory(absolute_old_path))
target_type |= SYMBOLIC_LINK_FLAG_DIRECTORY;
bool success =
CreateSymbolicLinkW(absolute_new_path, old_wpath, target_type);
if (!success) {
DWORD win_error = GetLastError();
// Return a more useful error code if a file/directory already exists at
// the symlink location.
if (win_error == ERROR_ACCESS_DENIED || win_error == ERROR_INVALID_NAME)
error = __WASI_ENOENT;
else
error = convert_windows_error_code(GetLastError());
}
fail:
return error;
#endif /* end of WINAPI_PARTITION_DESKTOP == 0 */
}
__wasi_errno_t
@ -1265,56 +1487,28 @@ os_renameat(os_file_handle old_handle, const char *old_path,
CHECK_VALID_FILE_HANDLE(old_handle);
CHECK_VALID_FILE_HANDLE(new_handle);
return __WASI_ENOSYS;
}
__wasi_errno_t
os_unlinkat(os_file_handle handle, const char *path, bool is_dir)
{
CHECK_VALID_FILE_HANDLE(handle);
wchar_t absolute_path[PATH_MAX];
__wasi_errno_t error = get_absolute_filepath(handle->raw.handle, path,
absolute_path, PATH_MAX);
wchar_t old_absolute_path[PATH_MAX];
__wasi_errno_t error = get_absolute_filepath(
old_handle->raw.handle, old_path, old_absolute_path, PATH_MAX);
if (error != __WASI_ESUCCESS)
return error;
DWORD attributes = GetFileAttributesW(absolute_path);
wchar_t new_absolute_path[PATH_MAX];
error = get_absolute_filepath(new_handle->raw.handle, new_path,
new_absolute_path, PATH_MAX);
if (has_symlink_attribute(attributes)) {
// Override is_dir for symlinks. A symlink to a directory counts
// as a directory itself in Windows.
is_dir = has_directory_attribute(attributes);
}
int ret =
is_dir ? RemoveDirectoryW(absolute_path) : DeleteFileW(absolute_path);
if (error != __WASI_ESUCCESS)
return error;
int ret = MoveFileExW(old_absolute_path, new_absolute_path,
MOVEFILE_REPLACE_EXISTING);
if (ret == 0)
error = convert_windows_error_code(GetLastError());
return error;
}
__wasi_errno_t
os_lseek(os_file_handle handle, __wasi_filedelta_t offset,
__wasi_whence_t whence, __wasi_filesize_t *new_offset)
{
CHECK_VALID_FILE_HANDLE(handle);
return __WASI_ENOSYS;
}
__wasi_errno_t
os_fadvise(os_file_handle handle, __wasi_filesize_t offset,
__wasi_filesize_t length, __wasi_advice_t advice)
{
CHECK_VALID_FILE_HANDLE(handle);
return __WASI_ENOSYS;
}
__wasi_errno_t
os_isatty(os_file_handle handle)
{
@ -1364,10 +1558,115 @@ os_convert_stderr_handle(os_raw_file_handle raw_stderr)
return create_stdio_handle(raw_stderr, STD_ERROR_HANDLE);
}
__wasi_errno_t
os_unlinkat(os_file_handle handle, const char *path, bool is_dir)
{
CHECK_VALID_FILE_HANDLE(handle);
wchar_t absolute_path[PATH_MAX];
__wasi_errno_t error = get_absolute_filepath(handle->raw.handle, path,
absolute_path, PATH_MAX);
DWORD attributes = GetFileAttributesW(absolute_path);
if (attributes != INVALID_FILE_ATTRIBUTES
&& (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
// Override is_dir for symlinks. A symlink to a directory counts as a
// directory itself in Windows.
is_dir = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
if (error != __WASI_ESUCCESS)
return error;
int ret =
is_dir ? RemoveDirectoryW(absolute_path) : DeleteFileW(absolute_path);
if (ret == 0)
error = convert_windows_error_code(GetLastError());
return error;
}
__wasi_errno_t
os_lseek(os_file_handle handle, __wasi_filedelta_t offset,
__wasi_whence_t whence, __wasi_filesize_t *new_offset)
{
CHECK_VALID_FILE_HANDLE(handle);
DWORD sys_whence = 0;
switch (whence) {
case __WASI_WHENCE_SET:
sys_whence = FILE_BEGIN;
break;
case __WASI_WHENCE_END:
sys_whence = FILE_END;
break;
case __WASI_WHENCE_CUR:
sys_whence = FILE_CURRENT;
break;
default:
return __WASI_EINVAL;
}
LARGE_INTEGER distance_to_move = { .QuadPart = offset };
LARGE_INTEGER updated_offset = { .QuadPart = 0 };
int ret = SetFilePointerEx(handle->raw.handle, distance_to_move,
&updated_offset, sys_whence);
if (ret == 0)
return convert_windows_error_code(GetLastError());
*new_offset = (__wasi_filesize_t)updated_offset.QuadPart;
return __WASI_ESUCCESS;
}
__wasi_errno_t
os_fadvise(os_file_handle handle, __wasi_filesize_t offset,
__wasi_filesize_t length, __wasi_advice_t advice)
{
CHECK_VALID_FILE_HANDLE(handle);
// Advisory information can be safely ignored if not supported
switch (advice) {
case __WASI_ADVICE_DONTNEED:
case __WASI_ADVICE_NOREUSE:
case __WASI_ADVICE_NORMAL:
case __WASI_ADVICE_RANDOM:
case __WASI_ADVICE_SEQUENTIAL:
case __WASI_ADVICE_WILLNEED:
return __WASI_ESUCCESS;
default:
return __WASI_EINVAL;
}
}
__wasi_errno_t
os_fdopendir(os_file_handle handle, os_dir_stream *dir_stream)
{
return __WASI_ENOSYS;
CHECK_VALID_FILE_HANDLE(handle);
// Check the handle is a directory handle first
DWORD windows_filetype = GetFileType(handle->raw.handle);
__wasi_filetype_t filetype = __WASI_FILETYPE_UNKNOWN;
__wasi_errno_t error =
convert_windows_filetype(handle, windows_filetype, &filetype);
if (error != __WASI_ESUCCESS)
return error;
if (filetype != __WASI_FILETYPE_DIRECTORY)
return __WASI_ENOTDIR;
*dir_stream = BH_MALLOC(sizeof(windows_dir_stream));
if (*dir_stream == NULL)
return __WASI_ENOMEM;
init_dir_stream(*dir_stream, handle);
return error;
}
__wasi_errno_t
@ -1375,7 +1674,9 @@ os_rewinddir(os_dir_stream dir_stream)
{
CHECK_VALID_WIN_DIR_STREAM(dir_stream);
return __WASI_ENOSYS;
reset_dir_stream(dir_stream);
return __WASI_ESUCCESS;
}
__wasi_errno_t
@ -1383,7 +1684,25 @@ os_seekdir(os_dir_stream dir_stream, __wasi_dircookie_t position)
{
CHECK_VALID_WIN_DIR_STREAM(dir_stream);
return __WASI_ENOSYS;
if (dir_stream->cookie == position)
return __WASI_ESUCCESS;
if (dir_stream->cookie > position) {
reset_dir_stream(dir_stream);
}
while (dir_stream->cookie < position) {
__wasi_errno_t error = read_next_dir_entry(dir_stream, NULL);
if (error != __WASI_ESUCCESS)
return error;
// We've reached the end of the directory.
if (dir_stream->cookie == 0) {
break;
}
}
return __WASI_ESUCCESS;
}
__wasi_errno_t
@ -1392,7 +1711,23 @@ os_readdir(os_dir_stream dir_stream, __wasi_dirent_t *entry,
{
CHECK_VALID_WIN_DIR_STREAM(dir_stream);
return __WASI_ENOSYS;
FILE_ID_BOTH_DIR_INFO *file_id_both_dir_info = NULL;
__wasi_errno_t error =
read_next_dir_entry(dir_stream, &file_id_both_dir_info);
if (error != __WASI_ESUCCESS || file_id_both_dir_info == NULL)
return error;
entry->d_ino = (__wasi_inode_t)file_id_both_dir_info->FileId.QuadPart;
entry->d_namlen = (__wasi_dirnamlen_t)(file_id_both_dir_info->FileNameLength
/ (sizeof(wchar_t) / sizeof(char)));
entry->d_next = (__wasi_dircookie_t)dir_stream->cookie;
entry->d_type = get_disk_filetype(file_id_both_dir_info->FileAttributes);
*d_name = dir_stream->current_entry_name;
return __WASI_ESUCCESS;
}
__wasi_errno_t
@ -1400,7 +1735,19 @@ os_closedir(os_dir_stream dir_stream)
{
CHECK_VALID_WIN_DIR_STREAM(dir_stream);
return __WASI_ENOSYS;
bool success = CloseHandle(dir_stream->handle->raw.handle);
if (!success) {
DWORD win_error = GetLastError();
if (win_error = ERROR_INVALID_HANDLE)
BH_FREE(dir_stream);
return convert_windows_error_code(win_error);
}
BH_FREE(dir_stream);
return __WASI_ESUCCESS;
}
os_dir_stream

View File

@ -6,19 +6,31 @@
#include "platform_common.h"
#include "win_util.h"
// From 1601-01-01 to 1970-01-01 there are 134774 days.
static const uint64_t NT_to_UNIX_epoch_in_ns =
134774ull * 86400ull * 1000ull * 1000ull * 1000ull;
__wasi_timestamp_t
convert_filetime_to_wasi_timestamp(LPFILETIME filetime)
{
// From 1601-01-01 to 1970-01-01 there are 134774 days.
static const uint64_t NT_to_UNIX_epoch =
134774ull * 86400ull * 1000ull * 1000ull * 1000ull;
ULARGE_INTEGER temp = { .HighPart = filetime->dwHighDateTime,
.LowPart = filetime->dwLowDateTime };
// WASI timestamps are measured in nanoseconds whereas FILETIME structs are
// represented in terms 100-nanosecond intervals.
return (temp.QuadPart * 100ull) - NT_to_UNIX_epoch;
return (temp.QuadPart * 100ull) - NT_to_UNIX_epoch_in_ns;
}
FILETIME
convert_wasi_timestamp_to_filetime(__wasi_timestamp_t timestamp)
{
ULARGE_INTEGER temp = { .QuadPart =
(timestamp + NT_to_UNIX_epoch_in_ns) / 100ull };
FILETIME ret = { .dwLowDateTime = temp.LowPart,
.dwHighDateTime = temp.HighPart };
return ret;
}
__wasi_errno_t

View File

@ -12,6 +12,9 @@
__wasi_timestamp_t
convert_filetime_to_wasi_timestamp(LPFILETIME filetime);
FILETIME
convert_wasi_timestamp_to_filetime(__wasi_timestamp_t timestamp);
/* Convert a Windows error code to a WASI error code */
__wasi_errno_t
convert_windows_error_code(DWORD windows_error_code);

View File

@ -1,34 +1,6 @@
{
"WASI C tests": {
"fdopendir-with-access": "Not implemented",
"lseek": "Not implemented"
},
"WASI Rust tests": {
"dangling_symlink": "Not implemented",
"directory_seek": "Not implemented",
"dir_fd_op_failures": "Not implemented",
"fd_advise": "Not implemented",
"fd_fdstat_set_rights": "Not implemented",
"fd_filestat_set": "Not implemented",
"fd_flags_set": "Not implemented",
"fd_readdir": "Not implemented",
"file_allocate": "Not implemented",
"file_seek_tell": "Not implemented",
"file_truncation": "Not implemented",
"nofollow_errors": "Not implemented",
"path_exists": "Not implemented",
"path_filestat": "Not implemented",
"path_link": "Not implemented",
"path_open_preopen": "Not implemented",
"path_rename": "Not implemented",
"path_rename_dir_trailing_slashes": "Not implemented",
"path_symlink_trailing_slashes": "Not implemented",
"poll_oneoff_stdio": "Not implemented",
"readlink": "Not implemented (path_symlink)",
"symlink_create": "Not implemented",
"symlink_filestat": "Not implemented",
"symlink_loop": "Not implemented",
"truncation_rights": "Not implemented"
"poll_oneoff_stdio": "Not implemented"
},
"WASI threads proposal": {
"wasi_threads_exit_main_wasi_read": "Blocking ops not implemented",

View File

@ -41,6 +41,12 @@ readonly THREAD_INTERNAL_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-wasi-thread
readonly THREAD_STRESS_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-wasi-threads/stress-test/"
readonly LIB_SOCKET_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-socket/test/"
add_env_key_to_test_config_file() {
filepath="tests/$2/testsuite/$3.json"
modified_contents=$(jq ".env.$1 = 1" "$filepath")
echo "$modified_contents" > "$filepath"
}
run_aot_tests () {
local -n tests=$1
local -n excluded_tests=$2
@ -95,6 +101,15 @@ if [[ $MODE != "aot" ]];then
export TEST_RUNTIME_EXE="${IWASM_CMD}"
# Some of the WASI test assertions can be controlled via environment
# variables. The following ones are set on Windows so that the tests pass.
if [ "$PLATFORM" == "windows" ]; then
add_env_key_to_test_config_file NO_DANGLING_FILESYSTEM rust symlink_loop
add_env_key_to_test_config_file NO_DANGLING_FILESYSTEM rust dangling_symlink
add_env_key_to_test_config_file ERRNO_MODE_WINDOWS rust path_open_preopen
add_env_key_to_test_config_file NO_RENAME_DIR_TO_EMPTY_DIR rust path_rename
fi
TEST_OPTIONS="-r adapters/wasm-micro-runtime.py \
-t \
${C_TESTS} \