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.
This commit is contained in:
zoraaver 2023-10-25 01:01:11 +01:00 committed by GitHub
parent a874bf0ff8
commit 75208073c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 972 additions and 61 deletions

View File

@ -25,6 +25,7 @@
#include <stdint.h>
#include <malloc.h>
#include <process.h>
#include <winapifamily.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
@ -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

View File

@ -5,6 +5,7 @@
#include "platform_api_vmcore.h"
#include <winternl.h>
#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,
&current_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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 */