mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 15:05:19 +00:00
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:
parent
a874bf0ff8
commit
75208073c0
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
¤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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
21
core/shared/platform/windows/win_util.c
Normal file
21
core/shared/platform/windows/win_util.c
Normal 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;
|
||||
}
|
15
core/shared/platform/windows/win_util.h
Normal file
15
core/shared/platform/windows/win_util.h
Normal 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 */
|
Loading…
Reference in New Issue
Block a user