From 75208073c028f860e2539dd40c826437f8161891 Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Wed, 25 Oct 2023 01:01:11 +0100 Subject: [PATCH] Partial windows filesystem implementation (#2657) Implement the necessary os_ filesystem functions to enable successful WASI initialization on Windows. Some small changes were also required to the sockets implementation to use the new windows_handle type. The remaining functions will be implemented in a future PR. --- .../platform/windows/platform_internal.h | 39 +- core/shared/platform/windows/win_clock.c | 33 +- core/shared/platform/windows/win_file.c | 751 +++++++++++++++++- core/shared/platform/windows/win_socket.c | 174 +++- core/shared/platform/windows/win_util.c | 21 + core/shared/platform/windows/win_util.h | 15 + 6 files changed, 972 insertions(+), 61 deletions(-) create mode 100644 core/shared/platform/windows/win_util.c create mode 100644 core/shared/platform/windows/win_util.h diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index 88ebfec72..9d1937a40 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -82,8 +83,6 @@ typedef struct korp_cond { struct os_thread_wait_node *thread_wait_list_end; } korp_cond; -#define bh_socket_t SOCKET - unsigned os_getpagesize(); void * @@ -137,14 +136,46 @@ bh_atomic_thread_fence(int mem_order); #define os_atomic_thread_fence bh_atomic_thread_fence -typedef HANDLE os_file_handle; -typedef void *os_dir_stream; +typedef enum windows_handle_type { + windows_handle_type_socket, + windows_handle_type_file +} windows_handle_type; + +typedef enum windows_access_mode { + windows_access_mode_read = 1 << 0, + windows_access_mode_write = 1 << 1 +} windows_access_mode; + +typedef struct windows_handle { + windows_handle_type type; + windows_access_mode access_mode; + union { + HANDLE handle; + SOCKET socket; + } raw; +} windows_handle; + +typedef struct windows_dir_stream { + // Enough space for the wide filename and the info struct itself + char info_buf[PATH_MAX * sizeof(wchar_t) + sizeof(FILE_ID_BOTH_DIR_INFO)]; + char current_entry_name[PATH_MAX]; + // An offset into info_buf to read the next entry from + DWORD cursor; + int cookie; + windows_handle *handle; +} windows_dir_stream; + +typedef windows_handle *os_file_handle; +typedef windows_dir_stream *os_dir_stream; + #if WASM_ENABLE_UVWASI != 1 typedef HANDLE os_raw_file_handle; #else typedef uint32_t os_raw_file_handle; #endif +#define bh_socket_t windows_handle * + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/windows/win_clock.c b/core/shared/platform/windows/win_clock.c index 4e1a5e89c..919debcd5 100644 --- a/core/shared/platform/windows/win_clock.c +++ b/core/shared/platform/windows/win_clock.c @@ -5,6 +5,7 @@ #include "platform_api_vmcore.h" #include +#include "win_util.h" #define NANOSECONDS_PER_SECOND 1000000000ULL #define NANOSECONDS_PER_TICK 100 @@ -22,20 +23,6 @@ calculate_monotonic_clock_frequency(uint64 *out_frequency) } } -// The implementation below derives from the following source: -// https://github.com/WasmEdge/WasmEdge/blob/b70f48c42922ce5ee7730054b6ac0b1615176285/lib/host/wasi/win.h#L210 -static uint64 -filetime_to_wasi_timestamp(FILETIME filetime) -{ - static const uint64 ntto_unix_epoch = - 134774ULL * 86400ULL * NANOSECONDS_PER_SECOND; - - ULARGE_INTEGER temp = { .LowPart = filetime.dwLowDateTime, - .HighPart = filetime.dwHighDateTime }; - - return (temp.QuadPart * 100ull) - ntto_unix_epoch; -} - static int get_performance_counter_value(uint64 *out_counter) { @@ -67,9 +54,9 @@ os_clock_res_get(bh_clock_id_t clock_id, uint64 *resolution) case BH_CLOCK_ID_PROCESS_CPUTIME_ID: case BH_CLOCK_ID_THREAD_CPUTIME_ID: { - PULONG maximum_time; - PULONG minimum_time; - PULONG current_time; + ULONG maximum_time; + ULONG minimum_time; + ULONG current_time; NTSTATUS status = NtQueryTimerResolution(&maximum_time, &minimum_time, ¤t_time); @@ -94,9 +81,9 @@ os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time) #if NTDDI_VERSION >= NTDDI_WIN8 GetSystemTimePreciseAsFileTime(&sys_now); #else - GetSystemTimeAsFileTime(&SysNow); + GetSystemTimeAsFileTime(&sys_now); #endif - *time = filetime_to_wasi_timestamp(sys_now); + *time = convert_filetime_to_wasi_timestamp(&sys_now); return BHT_OK; } case BH_CLOCK_ID_MONOTONIC: @@ -131,8 +118,8 @@ os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time) &exit_time, &kernel_time, &user_time)) { return BHT_ERROR; } - *time = filetime_to_wasi_timestamp(kernel_time) - + filetime_to_wasi_timestamp(user_time); + *time = convert_filetime_to_wasi_timestamp(&kernel_time) + + convert_filetime_to_wasi_timestamp(&user_time); return BHT_OK; } @@ -148,8 +135,8 @@ os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time) return BHT_ERROR; } - *time = filetime_to_wasi_timestamp(kernel_time) - + filetime_to_wasi_timestamp(user_time); + *time = convert_filetime_to_wasi_timestamp(&kernel_time) + + convert_filetime_to_wasi_timestamp(&user_time); return BHT_OK; } diff --git a/core/shared/platform/windows/win_file.c b/core/shared/platform/windows/win_file.c index 73b22cf32..5120e9a82 100644 --- a/core/shared/platform/windows/win_file.c +++ b/core/shared/platform/windows/win_file.c @@ -4,30 +4,586 @@ */ #include "platform_api_extension.h" -#include "platform_internal.h" +#include "libc_errno.h" +#include "win_util.h" + +#define CHECK_VALID_HANDLE_WITH_RETURN_VALUE(win_handle, ret) \ + do { \ + if ((win_handle) == NULL \ + || ((win_handle)->type == windows_handle_type_socket \ + && (win_handle)->raw.socket == INVALID_SOCKET) \ + || ((win_handle)->type == windows_handle_type_file \ + && (win_handle)->raw.handle == INVALID_HANDLE_VALUE)) \ + return (ret); \ + \ + } while (0) + +#define CHECK_VALID_HANDLE(win_handle) \ + CHECK_VALID_HANDLE_WITH_RETURN_VALUE(win_handle, __WASI_EBADF) + +#define CHECK_VALID_FILE_HANDLE(win_handle) \ + do { \ + if ((win_handle) == NULL) \ + return __WASI_EBADF; \ + \ + if ((win_handle)->type == windows_handle_type_socket) \ + return __WASI_EINVAL; \ + \ + if (((win_handle)->type == windows_handle_type_file \ + && (win_handle)->raw.handle == INVALID_HANDLE_VALUE)) \ + return __WASI_EBADF; \ + \ + } while (0) + +#define CHECK_VALID_WIN_DIR_STREAM(win_dir_stream) \ + do { \ + if ((win_dir_stream) == NULL) \ + return __WASI_EINVAL; \ + CHECK_VALID_FILE_HANDLE((win_dir_stream)->handle); \ + } while (0) + +static __wasi_errno_t +convert_winsock_error_code(int error_code) +{ + switch (error_code) { + case WSASYSNOTREADY: + case WSAEWOULDBLOCK: + return __WASI_EAGAIN; + case WSAVERNOTSUPPORTED: + return __WASI_ENOTSUP; + case WSAEINPROGRESS: + return __WASI_EINPROGRESS; + case WSAEPROCLIM: + return __WASI_EBUSY; + case WSAEFAULT: + return __WASI_EFAULT; + case WSAENETDOWN: + return __WASI_ENETDOWN; + case WSAENOTSOCK: + return __WASI_ENOTSOCK; + case WSAEINTR: + return __WASI_EINTR; + case WSAEAFNOSUPPORT: + return __WASI_EAFNOSUPPORT; + case WSAEMFILE: + return __WASI_ENFILE; + case WSAEINVAL: + return __WASI_EINVAL; + case WSAENOBUFS: + return __WASI_ENOBUFS; + case WSAEPROTONOSUPPORT: + return __WASI_EPROTONOSUPPORT; + case WSAEPROTOTYPE: + return __WASI_EPROTOTYPE; + case WSAESOCKTNOSUPPORT: + return __WASI_ENOTSUP; + case WSAEINVALIDPROCTABLE: + case WSAEINVALIDPROVIDER: + case WSAEPROVIDERFAILEDINIT: + case WSANOTINITIALISED: + default: + return __WASI_EINVAL; + } +} + +// Convert a Windows error code to a WASI error code +static __wasi_errno_t +convert_windows_error_code(DWORD windows_error_code) +{ + switch (windows_error_code) { + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_HANDLE: + case ERROR_NEGATIVE_SEEK: + return __WASI_EINVAL; + case ERROR_SHARING_VIOLATION: + case ERROR_PIPE_BUSY: + return __WASI_EBUSY; + case ERROR_ACCESS_DENIED: + return __WASI_EACCES; + case ERROR_ALREADY_EXISTS: + case ERROR_FILE_EXISTS: + return __WASI_EEXIST; + case ERROR_NO_MORE_FILES: + case ERROR_FILE_NOT_FOUND: + case ERROR_INVALID_NAME: + return __WASI_ENOENT; + case ERROR_PRIVILEGE_NOT_HELD: + return __WASI_EPERM; + case ERROR_NOT_ENOUGH_MEMORY: + return __WASI_ENOMEM; + case ERROR_NOACCESS: + return __WASI_EFAULT; + case ERROR_DIR_NOT_EMPTY: + return __WASI_ENOTEMPTY; + case ERROR_DIRECTORY: + return __WASI_ENOTDIR; + case ERROR_IO_PENDING: + case ERROR_INSUFFICIENT_BUFFER: + case ERROR_INVALID_FLAGS: + case ERROR_NO_UNICODE_TRANSLATION: + default: + return __WASI_ENOSYS; + } +} + +static __wasi_filetype_t +get_disk_filetype(DWORD attribute) +{ + if (attribute == INVALID_FILE_ATTRIBUTES) + return __WASI_FILETYPE_UNKNOWN; + if (attribute & FILE_ATTRIBUTE_REPARSE_POINT) + return __WASI_FILETYPE_SYMBOLIC_LINK; + if (attribute & FILE_ATTRIBUTE_DIRECTORY) + return __WASI_FILETYPE_DIRECTORY; + + return __WASI_FILETYPE_REGULAR_FILE; +} + +static __wasi_filetype_t +get_socket_filetype(SOCKET socket) +{ + char socket_type = 0; + int size = sizeof(socket_type); + + if (getsockopt(socket, SOL_SOCKET, SO_TYPE, &socket_type, &size) == 0) { + switch (socket_type) { + case SOCK_STREAM: + return __WASI_FILETYPE_SOCKET_STREAM; + case SOCK_DGRAM: + return __WASI_FILETYPE_SOCKET_DGRAM; + } + } + return __WASI_FILETYPE_UNKNOWN; +} + +static __wasi_errno_t +convert_windows_filetype(os_file_handle handle, DWORD filetype, + __wasi_filetype_t *out_filetype) +{ + __wasi_errno_t error = __WASI_ESUCCESS; + + switch (filetype) { + case FILE_TYPE_DISK: + FILE_ATTRIBUTE_TAG_INFO file_info; + + bool success = GetFileInformationByHandleEx( + handle->raw.handle, FileAttributeTagInfo, &file_info, + sizeof(file_info)); + + if (!success + || file_info.FileAttributes == INVALID_FILE_ATTRIBUTES) { + error = convert_windows_error_code(GetLastError()); + break; + } + + *out_filetype = get_disk_filetype(file_info.FileAttributes); + break; + case FILE_TYPE_CHAR: + *out_filetype = __WASI_FILETYPE_CHARACTER_DEVICE; + break; + case FILE_TYPE_PIPE: + if (handle->type == windows_handle_type_socket) + *out_filetype = get_socket_filetype(handle->raw.socket); + else + *out_filetype = __WASI_FILETYPE_BLOCK_DEVICE; + + break; + case FILE_TYPE_REMOTE: + case FILE_TYPE_UNKNOWN: + default: + *out_filetype = __WASI_FILETYPE_UNKNOWN; + } + + return error; +} + +// Converts the input string to a wchar string. +static __wasi_errno_t +convert_to_wchar(const char *str, wchar_t *buf, size_t buf_size) +{ + int converted_chars = + MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, (int)buf_size); + + if (converted_chars == 0) + return convert_windows_error_code(GetLastError()); + + return __WASI_ESUCCESS; +} + +// Get the filepath for a handle. The size of the buffer should be specified in +// terms of wchar. +static __wasi_errno_t +get_handle_filepath(HANDLE handle, wchar_t *buf, DWORD buf_size) +{ + DWORD bufsize_in_chars = buf_size * (sizeof(wchar_t) / sizeof(char)); + DWORD size = GetFinalPathNameByHandleW( + handle, buf, bufsize_in_chars, FILE_NAME_NORMALIZED | VOLUME_NAME_NONE); + + if (size > bufsize_in_chars) + return __WASI_ENAMETOOLONG; + + if (size == 0) + return convert_windows_error_code(GetLastError()); + + return __WASI_ESUCCESS; +} + +static void +init_dir_stream(os_dir_stream dir_stream, os_file_handle handle) +{ + dir_stream->cursor = 0; + dir_stream->handle = handle; + 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 +read_next_dir_entry(os_dir_stream dir_stream, FILE_ID_BOTH_DIR_INFO **out_entry) +{ + FILE_INFO_BY_HANDLE_CLASS file_info_class; + + if (dir_stream->cookie == 0) + file_info_class = FileIdBothDirectoryRestartInfo; + else + file_info_class = FileIdBothDirectoryInfo; + + if (dir_stream->cursor == 0 + && !GetFileInformationByHandleEx(dir_stream->handle->raw.handle, + file_info_class, dir_stream->info_buf, + sizeof(dir_stream->info_buf))) { + if (out_entry != NULL) + *out_entry = NULL; + DWORD win_error = GetLastError(); + // We've reached the end of the directory - return success + if (win_error == ERROR_NO_MORE_FILES) { + dir_stream->cookie = 0; + dir_stream->cursor = 0; + return __WASI_ESUCCESS; + } + + return convert_windows_error_code(win_error); + } + + FILE_ID_BOTH_DIR_INFO *current_info = + (FILE_ID_BOTH_DIR_INFO *)(dir_stream->info_buf + dir_stream->cursor); + + if (current_info->NextEntryOffset == 0) + dir_stream->cursor = 0; + else + dir_stream->cursor += current_info->NextEntryOffset; + + ++dir_stream->cookie; + + if (out_entry != NULL) + *out_entry = current_info; + else + return __WASI_ESUCCESS; + + // Convert and copy over the wchar filename into the entry_name buf + int ret = WideCharToMultiByte( + CP_UTF8, 0, current_info->FileName, + current_info->FileNameLength / (sizeof(wchar_t) / sizeof(char)), + dir_stream->current_entry_name, sizeof(dir_stream->current_entry_name), + NULL, NULL); + + if (ret == 0) + return convert_windows_error_code(GetLastError()); + + return __WASI_ESUCCESS; +} + +static HANDLE +create_handle(wchar_t *path, bool is_dir, bool follow_symlink, bool readonly) +{ + CREATEFILE2_EXTENDED_PARAMETERS create_params; + + create_params.dwSize = sizeof(create_params); + create_params.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + create_params.dwSecurityQosFlags = 0; + create_params.dwFileFlags = 0; + create_params.lpSecurityAttributes = NULL; + create_params.hTemplateFile = NULL; + + if (is_dir) { + create_params.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; + create_params.dwFileFlags |= FILE_FLAG_BACKUP_SEMANTICS; + } + + if (!follow_symlink) + create_params.dwFileFlags |= FILE_FLAG_OPEN_REPARSE_POINT; + + DWORD desired_access = GENERIC_READ; + + if (!readonly) { + desired_access |= GENERIC_WRITE; + create_params.dwFileAttributes |= FILE_ATTRIBUTE_READONLY; + } + + return CreateFile2(path, desired_access, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + OPEN_EXISTING, &create_params); +} + +#if WINAPI_PARTITION_DESKTOP +// Modifies the given path in place and replaces it with the filename component +// (including the extension) of the path. +static __wasi_errno_t +extract_filename_from_path(wchar_t *path, size_t buf_size) +{ + wchar_t extension[256]; + wchar_t filename[256]; + __wasi_errno_t error = __WASI_ESUCCESS; + + // Get the filename from the fullpath. + errno_t ret = + _wsplitpath_s(path, NULL, 0, NULL, 0, filename, 256, extension, 256); + if (ret != 0) { + error = convert_errno(ret); + return error; + } + + ret = wcscat_s(filename, 256, extension); + + if (ret != 0) { + error = convert_errno(ret); + return error; + } + + ret = wcscpy_s(path, buf_size, filename); + + if (ret != 0) + error = convert_errno(ret); + + return error; +} + +static __wasi_errno_t +get_handle_to_parent_directory(HANDLE handle, HANDLE *out_dir_handle) +{ + wchar_t path[PATH_MAX]; + __wasi_errno_t error = get_handle_filepath(handle, path, PATH_MAX); + + if (error != __WASI_ESUCCESS) + return error; + + wchar_t parent_dir_path[PATH_MAX]; + errno_t ret = wcscpy_s(parent_dir_path, PATH_MAX, path); + + if (ret != 0) { + error = convert_errno(ret); + return error; + } + + ret = wcscat_s(parent_dir_path, PATH_MAX, L"/.."); + + if (ret != 0) { + error = convert_errno(ret); + return error; + } + + HANDLE dir_handle = create_handle(parent_dir_path, true, true, true); + + if (dir_handle == INVALID_HANDLE_VALUE) { + error = convert_windows_error_code(GetLastError()); + return error; + } + + *out_dir_handle = dir_handle; + return error; +} + +// The easiest way to get all the necessary file information for files is to +// open a handle to the parent directory and iterate through the entries via +// FileIdBothDirectoryInfo. Other file information classes are only +// available on desktop. +static __wasi_errno_t +get_disk_file_information(HANDLE handle, __wasi_filestat_t *buf) +{ + __wasi_errno_t error = __WASI_ESUCCESS; + HANDLE raw_dir_handle = INVALID_HANDLE_VALUE; + + wchar_t path[PATH_MAX] = L"."; + + if (buf->st_filetype != __WASI_FILETYPE_DIRECTORY) { + error = get_handle_filepath(handle, path, PATH_MAX); + + if (error != __WASI_ESUCCESS) + goto fail; + + error = get_handle_to_parent_directory(handle, &raw_dir_handle); + + if (error != __WASI_ESUCCESS) + goto fail; + + error = extract_filename_from_path(path, PATH_MAX); + + if (error != __WASI_ESUCCESS) + goto fail; + } + else { + raw_dir_handle = handle; + } + + windows_handle dir_handle = { .access_mode = windows_access_mode_read, + .raw = { .handle = raw_dir_handle }, + .type = windows_handle_type_file }; + windows_dir_stream dir_stream; + init_dir_stream(&dir_stream, &dir_handle); + + do { + 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) + goto fail; + + const DWORD filename_length = file_id_both_dir_info->FileNameLength + / (sizeof(wchar_t) / sizeof(char)); + + if (wcsncmp(file_id_both_dir_info->FileName, path, filename_length) + == 0) { + buf->st_ino = + (__wasi_inode_t)(file_id_both_dir_info->FileId.QuadPart); + buf->st_atim = convert_filetime_to_wasi_timestamp( + (LPFILETIME)&file_id_both_dir_info->LastAccessTime.QuadPart); + buf->st_mtim = convert_filetime_to_wasi_timestamp( + (LPFILETIME)&file_id_both_dir_info->LastWriteTime.QuadPart); + buf->st_ctim = convert_filetime_to_wasi_timestamp( + (LPFILETIME)&file_id_both_dir_info->ChangeTime.QuadPart); + buf->st_size = + (__wasi_filesize_t)(file_id_both_dir_info->EndOfFile.QuadPart); + + break; + } + } while (dir_stream.cookie != 0); + + FILE_STANDARD_INFO file_standard_info; + + bool success = GetFileInformationByHandleEx(handle, FileStandardInfo, + &file_standard_info, + sizeof(file_standard_info)); + + if (!success) { + error = convert_windows_error_code(GetLastError()); + goto fail; + } + + buf->st_nlink = (__wasi_linkcount_t)file_standard_info.NumberOfLinks; +fail: + if (buf->st_filetype != __WASI_FILETYPE_DIRECTORY + && raw_dir_handle != INVALID_HANDLE_VALUE) + CloseHandle(raw_dir_handle); + + return error; +} + +#else + +static __wasi_errno_t +get_disk_file_information(HANDLE handle, __wasi_filestat_t *buf) +{ + __wasi_errno_t error = __WASI_ESUCCESS; + FILE_BASIC_INFO file_basic_info; + + int ret = GetFileInformationByHandleEx( + handle, FileBasicInfo, &file_basic_info, sizeof(file_basic_info)); + + if (ret == 0) { + error = convert_windows_error_code(GetLastError()); + return error; + } + + buf->st_atim = convert_filetime_to_wasi_timestamp( + (LPFILETIME)&file_basic_info.LastAccessTime.QuadPart); + buf->st_mtim = convert_filetime_to_wasi_timestamp( + (LPFILETIME)&file_basic_info.LastWriteTime.QuadPart); + buf->st_ctim = convert_filetime_to_wasi_timestamp( + (LPFILETIME)&file_basic_info.ChangeTime.QuadPart); + + BY_HANDLE_FILE_INFORMATION file_info; + ret = GetFileInformationByHandle(handle, &file_info); + + if (ret == 0) { + error = convert_windows_error_code(GetLastError()); + return error; + } + + ULARGE_INTEGER file_size = { .LowPart = file_info.nFileSizeLow, + .HighPart = file_info.nFileSizeHigh }; + buf->st_size = (__wasi_filesize_t)(file_size.QuadPart); + + ULARGE_INTEGER file_id = { .LowPart = file_info.nFileIndexLow, + .HighPart = file_info.nFileIndexHigh }; + buf->st_ino = (__wasi_inode_t)(file_id.QuadPart); + + buf->st_dev = (__wasi_device_t)file_info.dwVolumeSerialNumber; + buf->st_nlink = (__wasi_linkcount_t)file_info.nNumberOfLinks; + + return error; +} + +#endif /* end of !WINAPI_PARTITION_DESKTOP */ + +static __wasi_errno_t +get_file_information(os_file_handle handle, __wasi_filestat_t *buf) +{ + __wasi_errno_t error = __WASI_ESUCCESS; + + DWORD windows_filetype = GetFileType(handle->raw.handle); + error = + convert_windows_filetype(handle, windows_filetype, &buf->st_filetype); + + if (error != __WASI_ESUCCESS) + return error; + + buf->st_dev = 0; + + if (windows_filetype != FILE_TYPE_DISK) { + buf->st_atim = 0; + buf->st_ctim = 0; + buf->st_mtim = 0; + buf->st_nlink = 0; + buf->st_size = 0; + buf->st_ino = 0; + + return error; + } + + return get_disk_file_information(handle->raw.handle, buf); +} __wasi_errno_t os_fstat(os_file_handle handle, struct __wasi_filestat_t *buf) { - return __WASI_ENOSYS; + CHECK_VALID_HANDLE(handle); + + return get_file_information(handle, buf); } __wasi_errno_t os_fstatat(os_file_handle handle, const char *path, struct __wasi_filestat_t *buf, __wasi_lookupflags_t lookup_flags) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_file_get_fdflags(os_file_handle handle, __wasi_fdflags_t *flags) { + CHECK_VALID_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_file_set_fdflags(os_file_handle handle, __wasi_fdflags_t flags) { + CHECK_VALID_HANDLE(handle); + return __WASI_ENOSYS; } @@ -35,52 +591,117 @@ __wasi_errno_t os_file_get_access_mode(os_file_handle handle, wasi_libc_file_access_mode *access_mode) { - return __WASI_ENOSYS; + CHECK_VALID_HANDLE(handle); + + if ((handle->access_mode & windows_access_mode_read) != 0 + && (handle->access_mode & windows_access_mode_write) != 0) + *access_mode = WASI_LIBC_ACCESS_MODE_READ_WRITE; + else if ((handle->access_mode & windows_access_mode_write) != 0) + *access_mode = WASI_LIBC_ACCESS_MODE_WRITE_ONLY; + else + *access_mode = WASI_LIBC_ACCESS_MODE_READ_ONLY; + + return __WASI_ESUCCESS; } __wasi_errno_t os_fdatasync(os_file_handle handle) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_fsync(os_file_handle handle) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_open_preopendir(const char *path, os_file_handle *out) { - return __WASI_ENOSYS; + *out = NULL; + + wchar_t wpath[PATH_MAX]; + __wasi_errno_t error = convert_to_wchar(path, wpath, PATH_MAX); + + if (error != __WASI_ESUCCESS) + return error; + + HANDLE dir_handle = create_handle(wpath, true, true, true); + + if (dir_handle == INVALID_HANDLE_VALUE) + return convert_windows_error_code(GetLastError()); + + *out = BH_MALLOC(sizeof(windows_handle)); + + if (*out == NULL) { + CloseHandle(dir_handle); + return __WASI_ENOMEM; + } + + (*out)->type = windows_handle_type_file; + (*out)->raw.handle = dir_handle; + (*out)->access_mode = windows_access_mode_read; + + return error; } __wasi_errno_t os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags, __wasi_fdflags_t fs_flags, __wasi_lookupflags_t lookup_flags, - wasi_libc_file_access_mode read_write_mode, os_file_handle *out) + wasi_libc_file_access_mode access_mode, os_file_handle *out) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_close(os_file_handle handle, bool is_stdio) { - return __WASI_ENOSYS; + CHECK_VALID_HANDLE(handle); + + // We don't own the underlying raw handle so just free the handle and return + // success. + if (is_stdio) { + BH_FREE(handle); + return __WASI_ESUCCESS; + } + + switch (handle->type) { + case windows_handle_type_file: + bool success = CloseHandle(handle->raw.handle); + + if (!success) + return convert_windows_error_code(GetLastError()); + + break; + case windows_handle_type_socket: + int ret = closesocket(handle->raw.socket); + + if (ret != 0) + return convert_winsock_error_code(WSAGetLastError()); + + break; + default: + assert(false && "unreachable"); + } + + BH_FREE(handle); + + return __WASI_ESUCCESS; } __wasi_errno_t os_preadv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, __wasi_filesize_t offset, size_t *nread) { - return __WASI_ENOSYS; -} + CHECK_VALID_FILE_HANDLE(handle); -__wasi_errno_t -os_pwritev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, - __wasi_filesize_t offset, size_t *nwritten) -{ return __WASI_ENOSYS; } @@ -88,6 +709,17 @@ __wasi_errno_t os_readv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, size_t *nread) { + CHECK_VALID_HANDLE(handle); + + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_pwritev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nwritten) +{ + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -95,6 +727,8 @@ __wasi_errno_t os_writev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, size_t *nwritten) { + CHECK_VALID_HANDLE(handle); + return __WASI_ENOSYS; } @@ -102,12 +736,16 @@ __wasi_errno_t os_fallocate(os_file_handle handle, __wasi_filesize_t offset, __wasi_filesize_t length) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_ftruncate(os_file_handle handle, __wasi_filesize_t size) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -115,6 +753,8 @@ __wasi_errno_t os_futimens(os_file_handle handle, __wasi_timestamp_t access_time, __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -124,6 +764,8 @@ os_utimensat(os_file_handle handle, const char *path, __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags, __wasi_lookupflags_t lookup_flags) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -131,6 +773,8 @@ __wasi_errno_t os_readlinkat(os_file_handle handle, const char *path, char *buf, size_t bufsize, size_t *nread) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -139,18 +783,25 @@ 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) { + CHECK_VALID_FILE_HANDLE(from_handle); + CHECK_VALID_FILE_HANDLE(to_handle); + return __WASI_ENOSYS; } __wasi_errno_t os_symlinkat(const char *old_path, os_file_handle handle, const char *new_path) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } __wasi_errno_t os_mkdirat(os_file_handle handle, const char *path) { + CHECK_VALID_FILE_HANDLE(handle); + return __WASI_ENOSYS; } @@ -158,12 +809,17 @@ __wasi_errno_t os_renameat(os_file_handle old_handle, const char *old_path, os_file_handle new_handle, const char *new_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); + return __WASI_ENOSYS; } @@ -171,6 +827,8 @@ __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; } @@ -178,31 +836,57 @@ __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) { - return __WASI_ENOSYS; + CHECK_VALID_HANDLE(handle); + + DWORD console_mode; + return GetConsoleMode(handle->raw.handle, &console_mode) ? __WASI_ESUCCESS + : __WASI_ENOTTY; +} + +static os_file_handle +create_stdio_handle(HANDLE raw_stdio_handle, DWORD stdio) +{ + os_file_handle stdio_handle = BH_MALLOC(sizeof(windows_handle)); + + if (stdio_handle == NULL) + return NULL; + + stdio_handle->type = windows_handle_type_file; + stdio_handle->access_mode = + windows_access_mode_read | windows_access_mode_write; + + if (raw_stdio_handle == INVALID_HANDLE_VALUE) + raw_stdio_handle = GetStdHandle(stdio); + + stdio_handle->raw.handle = raw_stdio_handle; + + return stdio_handle; } os_file_handle os_convert_stdin_handle(os_raw_file_handle raw_stdin) { - return INVALID_HANDLE_VALUE; + return create_stdio_handle(raw_stdin, STD_INPUT_HANDLE); } os_file_handle os_convert_stdout_handle(os_raw_file_handle raw_stdout) { - return INVALID_HANDLE_VALUE; + return create_stdio_handle(raw_stdout, STD_OUTPUT_HANDLE); } os_file_handle os_convert_stderr_handle(os_raw_file_handle raw_stderr) { - return INVALID_HANDLE_VALUE; + return create_stdio_handle(raw_stderr, STD_ERROR_HANDLE); } __wasi_errno_t @@ -214,12 +898,16 @@ os_fdopendir(os_file_handle handle, os_dir_stream *dir_stream) __wasi_errno_t os_rewinddir(os_dir_stream dir_stream) { + CHECK_VALID_WIN_DIR_STREAM(dir_stream); + return __WASI_ENOSYS; } __wasi_errno_t os_seekdir(os_dir_stream dir_stream, __wasi_dircookie_t position) { + CHECK_VALID_WIN_DIR_STREAM(dir_stream); + return __WASI_ENOSYS; } @@ -227,12 +915,16 @@ __wasi_errno_t os_readdir(os_dir_stream dir_stream, __wasi_dirent_t *entry, const char **d_name) { + CHECK_VALID_WIN_DIR_STREAM(dir_stream); + return __WASI_ENOSYS; } __wasi_errno_t os_closedir(os_dir_stream dir_stream) { + CHECK_VALID_WIN_DIR_STREAM(dir_stream); + return __WASI_ENOSYS; } @@ -245,23 +937,42 @@ os_get_invalid_dir_stream() bool os_is_dir_stream_valid(os_dir_stream *dir_stream) { - return false; + assert(dir_stream != NULL); + + if (((*dir_stream) == NULL) || ((*dir_stream)->handle == NULL) + || ((*dir_stream)->handle->type != windows_handle_type_file) + || ((*dir_stream)->handle->raw.handle == INVALID_HANDLE_VALUE)) + return false; + + return true; } os_file_handle os_get_invalid_handle() { - return INVALID_HANDLE_VALUE; + return NULL; } bool os_is_handle_valid(os_file_handle *handle) { - return false; + assert(handle != NULL); + + CHECK_VALID_HANDLE_WITH_RETURN_VALUE(*handle, false); + + return true; } char * os_realpath(const char *path, char *resolved_path) { - return NULL; + resolved_path = _fullpath(resolved_path, path, PATH_MAX); + + // Check the file/directory actually exists + DWORD attributes = GetFileAttributesA(resolved_path); + + if (attributes == INVALID_FILE_ATTRIBUTES) + return NULL; + + return resolved_path; } \ No newline at end of file diff --git a/core/shared/platform/windows/win_socket.c b/core/shared/platform/windows/win_socket.c index f0428269c..d82cd724b 100644 --- a/core/shared/platform/windows/win_socket.c +++ b/core/shared/platform/windows/win_socket.c @@ -11,6 +11,22 @@ static bool is_winsock_inited = false; +#define CHECK_VALID_SOCKET_HANDLE(win_handle) \ + do { \ + if ((win_handle) == NULL) { \ + errno = EBADF; \ + return BHT_ERROR; \ + } \ + if ((win_handle)->type != windows_handle_type_socket) { \ + errno = ENOTSOCK; \ + return BHT_ERROR; \ + } \ + if ((win_handle)->raw.socket == INVALID_SOCKET) { \ + errno = EBADF; \ + return BHT_ERROR; \ + } \ + } while (0) + int init_winsock() { @@ -45,6 +61,16 @@ os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp) return BHT_ERROR; } + *(sock) = BH_MALLOC(sizeof(windows_handle)); + + if ((*sock) == NULL) { + errno = ENOMEM; + return BHT_ERROR; + } + + (*sock)->type = windows_handle_type_socket; + (*sock)->access_mode = windows_access_mode_read | windows_access_mode_write; + if (is_ipv4) { af = AF_INET; } @@ -54,18 +80,24 @@ os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp) } if (is_tcp) { - *sock = socket(af, SOCK_STREAM, IPPROTO_TCP); + (*sock)->raw.socket = socket(af, SOCK_STREAM, IPPROTO_TCP); } else { - *sock = socket(af, SOCK_DGRAM, 0); + (*sock)->raw.socket = socket(af, SOCK_DGRAM, 0); } - return (*sock == -1) ? BHT_ERROR : BHT_OK; + if ((*sock)->raw.socket == INVALID_SOCKET) { + BH_FREE(*sock); + return BHT_ERROR; + } + + return BHT_OK; } int os_socket_bind(bh_socket_t socket, const char *host, int *port) { + CHECK_VALID_SOCKET_HANDLE(socket); struct sockaddr_in addr; int socklen, ret; @@ -76,13 +108,13 @@ os_socket_bind(bh_socket_t socket, const char *host, int *port) addr.sin_port = htons(*port); addr.sin_family = AF_INET; - ret = bind(socket, (struct sockaddr *)&addr, sizeof(addr)); + ret = bind(socket->raw.socket, (struct sockaddr *)&addr, sizeof(addr)); if (ret < 0) { goto fail; } socklen = sizeof(addr); - if (getsockname(socket, (void *)&addr, &socklen) == -1) { + if (getsockname(socket->raw.socket, (void *)&addr, &socklen) == -1) { os_printf("getsockname failed with error %d\n", WSAGetLastError()); goto fail; } @@ -98,10 +130,12 @@ fail: int os_socket_settimeout(bh_socket_t socket, uint64 timeout_us) { + CHECK_VALID_SOCKET_HANDLE(socket); + DWORD tv = (DWORD)(timeout_us / 1000UL); - if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, - sizeof(tv)) + if (setsockopt(socket->raw.socket, SOL_SOCKET, SO_RCVTIMEO, + (const char *)&tv, sizeof(tv)) != 0) { return BHT_ERROR; } @@ -112,7 +146,9 @@ os_socket_settimeout(bh_socket_t socket, uint64 timeout_us) int os_socket_listen(bh_socket_t socket, int max_client) { - if (listen(socket, max_client) != 0) { + CHECK_VALID_SOCKET_HANDLE(socket); + + if (listen(socket->raw.socket, max_client) != 0) { os_printf("socket listen failed with error %d\n", WSAGetLastError()); return BHT_ERROR; } @@ -124,12 +160,25 @@ int os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr, unsigned int *addrlen) { + CHECK_VALID_SOCKET_HANDLE(server_sock); + struct sockaddr addr_tmp; unsigned int len = sizeof(struct sockaddr); - *sock = accept(server_sock, (struct sockaddr *)&addr_tmp, &len); + *sock = BH_MALLOC(sizeof(windows_handle)); - if (*sock < 0) { + if (*sock == NULL) { + errno = ENOMEM; + return BHT_ERROR; + } + + (*sock)->type = windows_handle_type_socket; + (*sock)->access_mode = windows_access_mode_read | windows_access_mode_write; + (*sock)->raw.socket = + accept(server_sock->raw.socket, (struct sockaddr *)&addr_tmp, &len); + + if ((*sock)->raw.socket == INVALID_SOCKET) { + BH_FREE(*sock); os_printf("socket accept failed with error %d\n", WSAGetLastError()); return BHT_ERROR; } @@ -140,13 +189,17 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr, int os_socket_recv(bh_socket_t socket, void *buf, unsigned int len) { - return recv(socket, buf, len, 0); + CHECK_VALID_SOCKET_HANDLE(socket); + + return recv(socket->raw.socket, buf, len, 0); } int os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags, bh_sockaddr_t *src_addr) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -155,13 +208,17 @@ os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags, int os_socket_send(bh_socket_t socket, const void *buf, unsigned int len) { - return send(socket, buf, len, 0); + CHECK_VALID_SOCKET_HANDLE(socket); + + return send(socket->raw.socket, buf, len, 0); } int os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len, int flags, const bh_sockaddr_t *dest_addr) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -170,14 +227,21 @@ os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len, int os_socket_close(bh_socket_t socket) { - closesocket(socket); + CHECK_VALID_SOCKET_HANDLE(socket); + + closesocket(socket->raw.socket); + + BH_FREE(socket); + return BHT_OK; } int os_socket_shutdown(bh_socket_t socket) { - shutdown(socket, SD_BOTH); + CHECK_VALID_SOCKET_HANDLE(socket); + + shutdown(socket->raw.socket, SD_BOTH); return BHT_OK; } @@ -209,6 +273,8 @@ os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out) int os_socket_connect(bh_socket_t socket, const char *addr, int port) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -228,6 +294,8 @@ os_socket_addr_resolve(const char *host, const char *service, int os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -236,6 +304,8 @@ os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr) int os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -244,6 +314,8 @@ os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us) int os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -252,6 +324,8 @@ os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us) int os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -260,6 +334,8 @@ os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us) int os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -268,6 +344,8 @@ os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us) int os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -276,6 +354,8 @@ os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr) int os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -284,6 +364,8 @@ os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz) int os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -292,6 +374,8 @@ os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz) int os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -300,6 +384,8 @@ os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz) int os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -308,6 +394,8 @@ os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz) int os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -316,6 +404,8 @@ os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled) int os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -324,6 +414,8 @@ os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled) int os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -332,6 +424,8 @@ os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled) int os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -340,6 +434,8 @@ os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled) int os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -348,6 +444,8 @@ os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled) int os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -356,6 +454,8 @@ os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled) int os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -364,6 +464,8 @@ os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s) int os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -372,6 +474,8 @@ os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s) int os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -380,6 +484,8 @@ os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled) int os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -388,6 +494,8 @@ os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled) int os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -396,6 +504,8 @@ os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled) int os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -404,6 +514,8 @@ os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled) int os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -412,6 +524,8 @@ os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s) int os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -420,6 +534,8 @@ os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s) int os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -428,6 +544,8 @@ os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s) int os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -436,6 +554,8 @@ os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s) int os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -444,6 +564,8 @@ os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled) int os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -452,6 +574,8 @@ os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled) int os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -460,6 +584,8 @@ os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled) int os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -470,6 +596,8 @@ os_socket_set_ip_add_membership(bh_socket_t socket, bh_ip_addr_buffer_t *imr_multiaddr, uint32_t imr_interface, bool is_ipv6) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -480,6 +608,8 @@ os_socket_set_ip_drop_membership(bh_socket_t socket, bh_ip_addr_buffer_t *imr_multiaddr, uint32_t imr_interface, bool is_ipv6) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -488,6 +618,8 @@ os_socket_set_ip_drop_membership(bh_socket_t socket, int os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -496,6 +628,8 @@ os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s) int os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -504,6 +638,8 @@ os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s) int os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -512,6 +648,8 @@ os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s) int os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -520,6 +658,8 @@ os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s) int os_socket_set_ipv6_only(bh_socket_t socket, bool option) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -528,6 +668,8 @@ os_socket_set_ipv6_only(bh_socket_t socket, bool option) int os_socket_get_ipv6_only(bh_socket_t socket, bool *option) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -536,6 +678,8 @@ os_socket_get_ipv6_only(bh_socket_t socket, bool *option) int os_socket_set_broadcast(bh_socket_t socket, bool is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; @@ -544,6 +688,8 @@ os_socket_set_broadcast(bh_socket_t socket, bool is_enabled) int os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled) { + CHECK_VALID_SOCKET_HANDLE(socket); + errno = ENOSYS; return BHT_ERROR; } diff --git a/core/shared/platform/windows/win_util.c b/core/shared/platform/windows/win_util.c new file mode 100644 index 000000000..fc01706eb --- /dev/null +++ b/core/shared/platform/windows/win_util.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "win_util.h" + +__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; +} \ No newline at end of file diff --git a/core/shared/platform/windows/win_util.h b/core/shared/platform/windows/win_util.h new file mode 100644 index 000000000..10b199f14 --- /dev/null +++ b/core/shared/platform/windows/win_util.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2023 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _WIN_UTIL_H +#define _WIN_UTIL_H + +#include "platform_wasi.h" +#include "windows.h" + +__wasi_timestamp_t +convert_filetime_to_wasi_timestamp(LPFILETIME filetime); + +#endif /* end of _WIN_UTIL_H */ \ No newline at end of file