From 9bcfe6f792b1947c92002a2bddf62693bbf8cbf3 Mon Sep 17 00:00:00 2001 From: Jaromil Date: Tue, 17 Dec 2024 01:17:03 +0100 Subject: [PATCH] fix: add win32ports headers also remove overlapping tinycc/mingw32 headers shipped in tinycc/win32 --- build/win-native.mk | 4 +- build/win-wsl.mk | 6 +- lib/tinycc/win32/include/dirent.h | 135 ------ lib/tinycc/win32/include/sys/time.h | 69 --- lib/tinycc/win32/include/sys/unistd.h | 14 - lib/win32ports/dirent.h | 584 ++++++++++++++++++++++++++ lib/win32ports/strings.h | 184 ++++++++ lib/win32ports/sys/time.h | 98 +++++ lib/win32ports/sys/wait.h | 520 +++++++++++++++++++++++ lib/win32ports/unistd.h | 314 ++++++++++++++ 10 files changed, 1708 insertions(+), 220 deletions(-) delete mode 100644 lib/tinycc/win32/include/dirent.h delete mode 100644 lib/tinycc/win32/include/sys/time.h delete mode 100644 lib/tinycc/win32/include/sys/unistd.h create mode 100644 lib/win32ports/dirent.h create mode 100644 lib/win32ports/strings.h create mode 100644 lib/win32ports/sys/time.h create mode 100644 lib/win32ports/sys/wait.h create mode 100644 lib/win32ports/unistd.h diff --git a/build/win-native.mk b/build/win-native.mk index 2937557..177d40f 100755 --- a/build/win-native.mk +++ b/build/win-native.mk @@ -24,7 +24,8 @@ SOURCES += src/win-compat.o \ src/embed_libtcc1.a.o \ src/embed_include.o \ src/embed_contrib_headers.o \ - src/embed_tinycc_win32.o + src/embed_tinycc_win32.o \ + src/embed_win32ports.o all: embed cjit.exe @@ -35,6 +36,7 @@ embed: lib/tinycc/libtcc1.a bash build/embed-path.sh lib/tinycc/include bash build/embed-path.sh lib/tinycc/win32/include tinycc_win32 bash build/embed-path.sh lib/contrib_headers + bash build/embed-path.sh lib/win32ports @echo >> src/embedded.c @echo "return(true);" >> src/embedded.c @echo "}" >> src/embedded.c diff --git a/build/win-wsl.mk b/build/win-wsl.mk index 98e7eb0..86ed3fe 100644 --- a/build/win-wsl.mk +++ b/build/win-wsl.mk @@ -7,6 +7,8 @@ include build/init.mk cc := x86_64-w64-mingw32-gcc ar := x86_64-w64-mingw32-ar + +cflags := -Og -ggdb ${cflags_includes} cflags += -DCJIT_BUILD_WIN ldadd += -lrpcrt4 -lshlwapi @@ -20,7 +22,8 @@ SOURCES += src/win-compat.o \ src/embed_libtcc1.a.o \ src/embed_include.o \ src/embed_contrib_headers.o \ - src/embed_tinycc_win32.o + src/embed_tinycc_win32.o \ + src/embed_win32ports.o all: deps embed cjit.exe @@ -31,6 +34,7 @@ embed: lib/tinycc/libtcc1.a bash build/embed-path.sh lib/tinycc/include bash build/embed-path.sh lib/tinycc/win32/include tinycc_win32 bash build/embed-path.sh lib/contrib_headers + bash build/embed-path.sh lib/win32ports @echo "\nreturn(true);\n}\n" >> src/embedded.c @echo "\n#endif\n" >> src/embedded.h diff --git a/lib/tinycc/win32/include/dirent.h b/lib/tinycc/win32/include/dirent.h deleted file mode 100644 index cd31f59..0000000 --- a/lib/tinycc/win32/include/dirent.h +++ /dev/null @@ -1,135 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER within this package. - */ -/* All the headers include this file. */ -#include <_mingw.h> - -#ifndef __STRICT_ANSI__ - -#ifndef _DIRENT_H_ -#define _DIRENT_H_ - - -#pragma pack(push,_CRT_PACKING) - -#include - -#ifndef RC_INVOKED - -#ifdef __cplusplus -extern "C" { -#endif - - struct dirent - { - long d_ino; /* Always zero. */ - unsigned short d_reclen; /* Always zero. */ - unsigned short d_namlen; /* Length of name in d_name. */ - char* d_name; /* File name. */ - /* NOTE: The name in the dirent structure points to the name in the - * finddata_t structure in the DIR. */ - }; - - /* - * This is an internal data structure. Good programmers will not use it - * except as an argument to one of the functions below. - * dd_stat field is now int (was short in older versions). - */ - typedef struct - { - /* disk transfer area for this dir */ - struct _finddata_t dd_dta; - - /* dirent struct to return from dir (NOTE: this makes this thread - * safe as long as only one thread uses a particular DIR struct at - * a time) */ - struct dirent dd_dir; - - /* _findnext handle */ - long dd_handle; - - /* - * Status of search: - * 0 = not started yet (next entry to read is first entry) - * -1 = off the end - * positive = 0 based index of next entry - */ - int dd_stat; - - /* given path for dir with search pattern (struct is extended) */ - char dd_name[1]; - } DIR; - - DIR* __cdecl opendir (const char*); - struct dirent* __cdecl readdir (DIR*); - int __cdecl closedir (DIR*); - void __cdecl rewinddir (DIR*); - long __cdecl telldir (DIR*); - void __cdecl seekdir (DIR*, long); - - - /* wide char versions */ - - struct _wdirent - { - long d_ino; /* Always zero. */ - unsigned short d_reclen; /* Always zero. */ - unsigned short d_namlen; /* Length of name in d_name. */ - wchar_t* d_name; /* File name. */ - /* NOTE: The name in the dirent structure points to the name in the * wfinddata_t structure in the _WDIR. */ - }; - - /* - * This is an internal data structure. Good programmers will not use it - * except as an argument to one of the functions below. - */ - typedef struct - { - /* disk transfer area for this dir */ - struct _wfinddata_t dd_dta; - - /* dirent struct to return from dir (NOTE: this makes this thread - * safe as long as only one thread uses a particular DIR struct at - * a time) */ - struct _wdirent dd_dir; - - /* _findnext handle */ - long dd_handle; - - /* - * Status of search: - * 0 = not started yet (next entry to read is first entry) - * -1 = off the end - * positive = 0 based index of next entry - */ - int dd_stat; - - /* given path for dir with search pattern (struct is extended) */ - wchar_t dd_name[1]; - } _WDIR; - - - - _WDIR* __cdecl _wopendir (const wchar_t*); - struct _wdirent* __cdecl _wreaddir (_WDIR*); - int __cdecl _wclosedir (_WDIR*); - void __cdecl _wrewinddir (_WDIR*); - long __cdecl _wtelldir (_WDIR*); - void __cdecl _wseekdir (_WDIR*, long); - - -#ifdef __cplusplus -} -#endif - -#endif /* Not RC_INVOKED */ - -#pragma pack(pop) - -#endif /* Not _DIRENT_H_ */ - - -#endif /* Not __STRICT_ANSI__ */ - diff --git a/lib/tinycc/win32/include/sys/time.h b/lib/tinycc/win32/include/sys/time.h deleted file mode 100644 index 8ccab83..0000000 --- a/lib/tinycc/win32/include/sys/time.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER within this package. - */ - -#ifndef _SYS_TIME_H_ -#define _SYS_TIME_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __STRICT_ANSI__ -#ifndef _TIMEVAL_DEFINED /* also in winsock[2].h */ -#define _TIMEVAL_DEFINED -struct timeval { - long tv_sec; - long tv_usec; -}; -#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) -#define timercmp(tvp, uvp, cmp) \ - (((tvp)->tv_sec != (uvp)->tv_sec) ? \ - ((tvp)->tv_sec cmp (uvp)->tv_sec) : \ - ((tvp)->tv_usec cmp (uvp)->tv_usec)) -#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 -#endif /* _TIMEVAL_DEFINED */ - -#ifndef _TIMEZONE_DEFINED /* also in sys/time.h */ -#define _TIMEZONE_DEFINED -/* Provided for compatibility with code that assumes that - the presence of gettimeofday function implies a definition - of struct timezone. */ -struct timezone -{ - int tz_minuteswest; /* of Greenwich */ - int tz_dsttime; /* type of dst correction to apply */ -}; - - extern int __cdecl mingw_gettimeofday (struct timeval *p, struct timezone *z); - -#endif - -/* - Implementation as per: - The Open Group Base Specifications, Issue 6 - IEEE Std 1003.1, 2004 Edition - - The timezone pointer arg is ignored. Errors are ignored. -*/ -#ifndef _GETTIMEOFDAY_DEFINED -#define _GETTIMEOFDAY_DEFINED -int __cdecl gettimeofday(struct timeval *__restrict__, - void *__restrict__ /* tzp (unused) */); -#endif - -#endif /* __STRICT_ANSI__ */ - -#ifdef __cplusplus -} -#endif - -/* Adding timespec definition. */ -#include - - -#endif /* _SYS_TIME_H_ */ diff --git a/lib/tinycc/win32/include/sys/unistd.h b/lib/tinycc/win32/include/sys/unistd.h deleted file mode 100644 index 31006d3..0000000 --- a/lib/tinycc/win32/include/sys/unistd.h +++ /dev/null @@ -1,14 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER within this package. - */ -/* - * This file is part of the Mingw32 package. - * - * unistd.h maps (roughly) to io.h - */ -#ifndef __STRICT_ANSI__ -#include -#endif - diff --git a/lib/win32ports/dirent.h b/lib/win32ports/dirent.h new file mode 100644 index 0000000..de75def --- /dev/null +++ b/lib/win32ports/dirent.h @@ -0,0 +1,584 @@ +/* +MIT License +Copyright (c) 2019 win32ports +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once + +#ifndef __DIRENT_H_9DE6B42C_8D0C_4D31_A8EF_8E4C30E6C46A__ +#define __DIRENT_H_9DE6B42C_8D0C_4D31_A8EF_8E4C30E6C46A__ + +#ifndef _WIN32 + +#pragma message("this dirent.h implementation is for Windows only!") + +#else /* _WIN32 */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include +#include + +#include + +#include + +#ifdef _MSC_VER +#pragma comment(lib, "Shlwapi.lib") +#endif + +#ifndef NAME_MAX +#define NAME_MAX 260 +#endif /* NAME_MAX */ + +#ifndef DT_UNKNOWN +#define DT_UNKNOWN 0 +#endif /* DT_UNKNOWN */ + +#ifndef DT_FIFO +#define DT_FIFO 1 +#endif /* DT_FIFO */ + +#ifndef DT_CHR +#define DT_CHR 2 +#endif /* DT_CHR */ + +#ifndef DT_DIR +#define DT_DIR 4 +#endif /* DT_DIR */ + +#ifndef DT_BLK +#define DT_BLK 6 +#endif /* DT_BLK */ + +#ifndef DT_REG +#define DT_REG 8 +#endif /* DT_REF */ + +#ifndef DT_LNK +#define DT_LNK 10 +#endif /* DT_LNK */ + +#ifndef DT_SOCK +#define DT_SOCK 12 +#endif /* DT_SOCK */ + +#ifndef DT_WHT +#define DT_WHT 14 +#endif /* DT_WHT */ + +#ifndef _DIRENT_HAVE_D_NAMLEN +#define _DIRENT_HAVE_D_NAMLEN 1 +#endif /* _DIRENT_HAVE_D_NAMLEN */ + +#ifndef _DIRENT_HAVE_D_RECLEN +#define _DIRENT_HAVE_D_RECLEN 1 +#endif /* _DIRENT_HAVE_D_RECLEN */ + +#ifndef _DIRENT_HAVE_D_OFF +#define _DIRENT_HAVE_D_OFF 1 +#endif /* _DIRENT_HAVE_D_OFF */ + +#ifndef _DIRENT_HAVE_D_TYPE +#define _DIRENT_HAVE_D_TYPE 1 +#endif /* _DIRENT_HAVE_D_TYPE */ + +#ifndef NTFS_MAX_PATH +#define NTFS_MAX_PATH 32768 +#endif /* NTFS_MAX_PATH */ + +#ifndef FSCTL_GET_REPARSE_POINT +#define FSCTL_GET_REPARSE_POINT 0x900a8 +#endif /* FSCTL_GET_REPARSE_POINT */ + +#ifndef FILE_NAME_NORMALIZED +#define FILE_NAME_NORMALIZED 0 +#endif /* FILE_NAME_NORMALIZED */ + +typedef void* DIR; + +typedef struct ino_t +{ + unsigned long long serial; + unsigned char fileid[16]; +} __ino_t; + +struct dirent +{ + __ino_t d_ino; + off_t d_off; + unsigned short d_reclen; + unsigned char d_namelen; + unsigned char d_type; + char d_name[NAME_MAX]; +}; + +struct __dir +{ + struct dirent* entries; + intptr_t fd; + long int count; + long int index; +}; + +static int closedir(DIR* dirp) +{ + struct __dir* data = NULL; + if (!dirp) { + errno = EBADF; + return -1; + } + data = (struct __dir*) dirp; + CloseHandle((HANDLE)data->fd); + free(data->entries); + free(data); + return 0; +} + +static void __seterrno(int value) +{ +#ifdef _MSC_VER + _set_errno(value); +#else /* _MSC_VER */ + errno = value; +#endif /* _MSC_VER */ +} + +static int __islink(const wchar_t * name, char * buffer) +{ + DWORD io_result = 0; + DWORD bytes_returned = 0; + HANDLE hFile = CreateFileW(name, 0, 0, NULL, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0); + if (hFile == INVALID_HANDLE_VALUE) + return 0; + + io_result = DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, + buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytes_returned, NULL); + + CloseHandle(hFile); + + if (io_result == 0) + return 0; + + return ((REPARSE_GUID_DATA_BUFFER*)buffer)->ReparseTag == IO_REPARSE_TAG_SYMLINK; +} + +#pragma pack(push, 1) + +typedef struct dirent_FILE_ID_128 +{ + BYTE Identifier[16]; +} +dirent_FILE_ID_128; + +typedef struct _dirent_FILE_ID_INFO +{ + ULONGLONG VolumeSerialNumber; + dirent_FILE_ID_128 FileId; +} +dirent_FILE_ID_INFO; + +#pragma pack(pop) + +typedef enum dirent_FILE_INFO_BY_HANDLE_CLASS +{ dirent_FileIdInfo = 18 } +dirent_FILE_INFO_BY_HANDLE_CLASS; + +static __ino_t __inode(const wchar_t* name) +{ + __ino_t value = { 0 }; + BOOL result; + dirent_FILE_ID_INFO fileid; + BY_HANDLE_FILE_INFORMATION info; + typedef BOOL (__stdcall* pfnGetFileInformationByHandleEx)(HANDLE hFile, + dirent_FILE_INFO_BY_HANDLE_CLASS FileInformationClass, + LPVOID lpFileInformation, DWORD dwBufferSize); + + HANDLE hKernel32 = GetModuleHandleW(L"kernel32.dll"); + if (!hKernel32) + return value; + + pfnGetFileInformationByHandleEx fnGetFileInformationByHandleEx = (pfnGetFileInformationByHandleEx) GetProcAddress(hKernel32, "GetFileInformationByHandleEx"); + if (!fnGetFileInformationByHandleEx) + return value; + + HANDLE hFile = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); + if (hFile == INVALID_HANDLE_VALUE) + return value; + + result = fnGetFileInformationByHandleEx(hFile, dirent_FileIdInfo, &fileid, sizeof(fileid)); + if (result) + { + value.serial = fileid.VolumeSerialNumber; + memcpy(value.fileid, fileid.FileId.Identifier, 16); + } + else + { + result = GetFileInformationByHandle(hFile, &info); + if(result) + { + value.serial = info.dwVolumeSerialNumber; + memcpy(value.fileid + 8, &info.nFileIndexHigh, 4); + memcpy(value.fileid + 12, &info.nFileIndexLow, 4); + } + } + CloseHandle(hFile); + return value; +} + +static DIR* __internal_opendir(wchar_t* wname, int size) +{ + struct __dir* data = NULL; + struct dirent *tmp_entries = NULL; + static char default_char = '?'; + static wchar_t* prefix = L"\\\\?\\"; + static wchar_t* suffix = L"\\*.*"; + static int extra_prefix = 4; /* use prefix "\\?\" to handle long file names */ + static int extra_suffix = 4; /* use suffix "\*.*" to find everything */ + WIN32_FIND_DATAW w32fd = { 0 }; + HANDLE hFindFile = INVALID_HANDLE_VALUE; + static int grow_factor = 2; + char* buffer = NULL; + + BOOL relative = PathIsRelativeW(wname + extra_prefix); + + memcpy(wname + size - 1, suffix, sizeof(wchar_t) * extra_suffix); + wname[size + extra_suffix - 1] = 0; + + if (relative) { + wname += extra_prefix; + size -= extra_prefix; + } + hFindFile = FindFirstFileW(wname, &w32fd); + if (INVALID_HANDLE_VALUE == hFindFile) + { + __seterrno(ENOENT); + return NULL; + } + + data = (struct __dir*) malloc(sizeof(struct __dir)); + if (!data) + goto out_of_memory; + wname[size - 1] = 0; + data->fd = (intptr_t)CreateFileW(wname, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); + wname[size - 1] = L'\\'; + data->count = 16; + data->index = 0; + data->entries = (struct dirent*) malloc(sizeof(struct dirent) * data->count); + if (!data->entries) + goto out_of_memory; + buffer = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); + if (!buffer) + goto out_of_memory; + do + { + WideCharToMultiByte(CP_UTF8, 0, w32fd.cFileName, -1, data->entries[data->index].d_name, NAME_MAX, &default_char, NULL); + + memcpy(wname + size, w32fd.cFileName, sizeof(wchar_t) * NAME_MAX); + + if (((w32fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT) && __islink(wname, buffer)) + data->entries[data->index].d_type = DT_LNK; + else if ((w32fd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) == FILE_ATTRIBUTE_DEVICE) + data->entries[data->index].d_type = DT_CHR; + else if ((w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) + data->entries[data->index].d_type = DT_DIR; + else + data->entries[data->index].d_type = DT_REG; + + data->entries[data->index].d_ino = __inode(wname); + data->entries[data->index].d_reclen = sizeof(struct dirent); + data->entries[data->index].d_namelen = (unsigned char)wcslen(w32fd.cFileName); + data->entries[data->index].d_off = 0; + + if (++data->index == data->count) { + tmp_entries = (struct dirent*) realloc(data->entries, sizeof(struct dirent) * data->count * grow_factor); + if (!tmp_entries) + goto out_of_memory; + data->entries = tmp_entries; + data->count *= grow_factor; + } + } + while (FindNextFileW(hFindFile, &w32fd) != 0); + + free(buffer); + FindClose(hFindFile); + + data->count = data->index; + data->index = 0; + return (DIR*)data; +out_of_memory: + if (data) + { + if (INVALID_HANDLE_VALUE != (HANDLE)data->fd) + CloseHandle((HANDLE)data->fd); + free(data->entries); + } + free(buffer); + free(data); + if (INVALID_HANDLE_VALUE != hFindFile) + FindClose(hFindFile); + __seterrno(ENOMEM); + return NULL; +} + +static wchar_t* __get_buffer() +{ + wchar_t* name = malloc(sizeof(wchar_t) * (NTFS_MAX_PATH + NAME_MAX + 8)); + if (name) + memcpy(name, L"\\\\?\\", sizeof(wchar_t) * 4); + return name; +} + +static DIR* opendir(const char* name) +{ + DIR* dirp = NULL; + wchar_t* wname = __get_buffer(); + int size = 0; + if (!wname) + { + errno = ENOMEM; + return NULL; + } + size = MultiByteToWideChar(CP_UTF8, 0, name, -1, wname + 4, NTFS_MAX_PATH); + if (0 == size) + { + free(wname); + return NULL; + } + dirp = __internal_opendir(wname, size + 4); + free(wname); + return dirp; +} + +static DIR* _wopendir(const wchar_t* name) +{ + DIR* dirp = NULL; + wchar_t* wname = __get_buffer(); + int size = 0; + if (!wname) + { + errno = ENOMEM; + return NULL; + } + size = (int)wcslen(name); + if (size > NTFS_MAX_PATH) + { + free(wname); + return NULL; + } + memcpy(wname + 4, name, sizeof(wchar_t) * (size + 1)); + dirp = __internal_opendir(wname, size + 5); + free(wname); + return dirp; +} + +static DIR* fdopendir(intptr_t fd) +{ + DIR* dirp = NULL; + wchar_t* wname = __get_buffer(); + typedef DWORD (__stdcall * pfnGetFinalPathNameByHandleW)( + HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags); + + HANDLE hKernel32 = GetModuleHandleW(L"kernel32.dll"); + if (!hKernel32) + { + errno = EINVAL; + return NULL; + } + + pfnGetFinalPathNameByHandleW fnGetFinalPathNameByHandleW = (pfnGetFinalPathNameByHandleW) GetProcAddress(hKernel32, "GetFinalPathNameByHandleW"); + if (!fnGetFinalPathNameByHandleW) + { + errno = EINVAL; + return NULL; + } + + int size = 0; + if (!wname) + { + errno = ENOMEM; + return NULL; + } + size = fnGetFinalPathNameByHandleW((HANDLE) fd, wname + 4, NTFS_MAX_PATH, FILE_NAME_NORMALIZED); + if (0 == size) + { + free(wname); + errno = ENOTDIR; + return NULL; + } + dirp = __internal_opendir(wname, size + 5); + free(wname); + return dirp; +} + +static struct dirent* readdir(DIR* dirp) +{ + struct __dir* data = (struct __dir*) dirp; + if (!data) { + errno = EBADF; + return NULL; + } + if (data->index < data->count) + { + return &data->entries[data->index++]; + } + return NULL; +} + +static int readdir_r(DIR* dirp, struct dirent* entry, struct dirent**result) +{ + struct __dir* data = (struct __dir*) dirp; + if (!data) { + return EBADF; + } + if (data->index < data->count) + { + if (entry) + memcpy(entry, &data->entries[data->index++], sizeof(struct dirent)); + if (result) + *result = entry; + } + else if (result) + *result = NULL; + return 0; +} + +static void seekdir(DIR* dirp, long int offset) +{ + if (dirp) + { + struct __dir* data = (struct __dir*) dirp; + data->index = (offset < data->count) ? offset : data->index; + } +} + +static void rewinddir(DIR* dirp) +{ + seekdir(dirp, 0); +} + +static long int telldir(DIR* dirp) +{ + if (!dirp) { + errno = EBADF; + return -1; + } + return ((struct __dir*)dirp)->count; +} + +static intptr_t dirfd(DIR * dirp) +{ + if (!dirp) { + errno = EINVAL; + return -1; + } + return ((struct __dir*)dirp)->fd; +} + +static int scandir(const char* dirp, struct dirent*** namelist, + int (*filter)(const struct dirent*), + int (*compar)(const struct dirent**, const struct dirent**)) +{ + struct dirent ** entries = NULL, ** tmp_entries = NULL; + long int i = 0, index = 0, count = 16; + DIR * d = opendir(dirp); + struct __dir* data = (struct __dir*) d; + if (!data) { + closedir(d); + __seterrno(ENOENT); + return -1; + } + entries = (struct dirent**) malloc(sizeof(struct dirent*) * count); + if (!entries) + { + closedir(d); + __seterrno(ENOMEM); + return -1; + } + for (i = 0; i < data->count; ++i) + { + if (!filter || filter(&data->entries[i])) + { + entries[index] = (struct dirent*) malloc(sizeof(struct dirent)); + if (!entries[index]) + { + closedir(d); + for (i = 0; i < index; ++i) + free(entries[index]); + free(entries); + __seterrno(ENOMEM); + return -1; + } + memcpy(entries[index], &data->entries[i], sizeof(struct dirent)); + if (++index == count) + { + tmp_entries = (struct dirent**)realloc(entries, sizeof(struct dirent*) * count * 2); + if (!tmp_entries) + { + closedir(d); + for (i = 0; i < index; ++i) + free(entries[index - 1]); + free(entries); + __seterrno(ENOMEM); + return -1; + } + entries = tmp_entries; + count *= 2; + } + } + } + qsort(entries, index, sizeof(struct dirent*), compar); + entries[index] = NULL; + if (namelist) + *namelist = entries; + closedir(d); + return 0; +} + +int alphasort(const void* a, const void* b) +{ + struct dirent** dira = (struct dirent**)a, **dirb = (struct dirent**)b; + if (!dira || !dirb) + return 0; + return strcoll((*dira)->d_name, (*dirb)->d_name); +} + +static int __strverscmp(const char* s1, const char* s2) +{ + return alphasort(s1, s2); +} + +int versionsort(const void* a, const void* b) +{ + struct dirent** dira = (struct dirent**)a, ** dirb = (struct dirent**)b; + if (!dira || !dirb) + return 0; + return __strverscmp((*dira)->d_name, (*dirb)->d_name); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _WIN32 */ + +#endif /* __DIRENT_H_9DE6B42C_8D0C_4D31_A8EF_8E4C30E6C46A__ */ diff --git a/lib/win32ports/strings.h b/lib/win32ports/strings.h new file mode 100644 index 0000000..9efe540 --- /dev/null +++ b/lib/win32ports/strings.h @@ -0,0 +1,184 @@ +/* +MIT License +Copyright (c) 2019 win32ports +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once +#ifndef __STRINGS_H_868520A6_2F4E_4B49_AF4B_02B5A21CF6BB__ +#define __STRINGS_H_868520A6_2F4E_4B49_AF4B_02B5A21CF6BB__ + +#ifndef _WIN32 + +#pragma message("this strings.h implementation is for Windows only!") + +#else /* _WIN32 */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + + static int bcmp(const void * s1, const void * s2, size_t n) + { + return memcmp(s1, s2, n); + } + + static void bcopy(const void * src, void * dest, size_t n) + { + memcpy(dest, src, n); + } + + static void bzero(void * s, size_t n) + { + memset(s, 0, n); + } + + static void explicit_bzero(void * s, size_t n) + { + volatile char * vs = (volatile char *) s; + while (n) + { + *vs++ = 0; + n--; + } + } + + static char * index(const char * s, int c) + { + return strchr(s, c); + } + + static char * rindex(const char * s, int c) + { + return strrchr(s, c); + } + + static int ffs(int i) + { + int bit; + + if (0 == i) + return 0; + + for (bit = 1; !(i & 1); ++bit) + i >>= 1; + return bit; + } + + static int ffsl(long i) + { + int bit; + + if (0 == i) + return 0; + + for (bit = 1; !(i & 1); ++bit) + i >>= 1; + return bit; + } + + static int ffsll(long long i) + { + int bit; + + if (0 == i) + return 0; + + for (bit = 1; !(i & 1); ++bit) + i >>= 1; + return bit; + } + +#ifndef __MINGW32__ + + static int strcasecmp(const char * s1, const char * s2) + { + const unsigned char * u1 = (const unsigned char*) s1; + const unsigned char * u2 = (const unsigned char*) s2; + int result; + + while ((result = tolower(*u1) - tolower(*u2)) == 0 && *u1 != 0) + { + u1++; + u2++; + } + + return result; + } + + static int strncasecmp(const char * s1, const char * s2, size_t n) + { + const unsigned char * u1 = (const unsigned char*) s1; + const unsigned char * u2 = (const unsigned char*) s2; + int result; + + for (; n != 0; n--) + { + result = tolower(*u1) - tolower(*u2); + if (result) + return result; + if (*u1 == 0) + return 0; + } + return 0; + } + + static int strcasecmp_l(const char * s1, const char * s2, _locale_t loc) + { + const unsigned char * u1 = (const unsigned char*) s1; + const unsigned char * u2 = (const unsigned char*) s2; + int result; + + while ((result = _tolower_l(*u1, loc) - _tolower_l(*u2, loc)) == 0 && *u1 != 0) + { + u1++; + u2++; + } + + return result; + } + + static int strncasecmp_l(const char * s1, const char * s2, size_t n, _locale_t loc) + { + const unsigned char * u1 = (const unsigned char*) s1; + const unsigned char * u2 = (const unsigned char*) s2; + int result; + + for (; n != 0; n--) + { + result = _tolower_l(*u1, loc) - _tolower_l(*u2, loc); + if (result) + return result; + if (*u1 == 0) + return 0; + } + return 0; + } + + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _WIN32 */ + +#endif /* __STRINGS_H_868520A6_2F4E_4B49_AF4B_02B5A21CF6BB__ */ diff --git a/lib/win32ports/sys/time.h b/lib/win32ports/sys/time.h new file mode 100644 index 0000000..6eb8bb1 --- /dev/null +++ b/lib/win32ports/sys/time.h @@ -0,0 +1,98 @@ +/* +MIT License +Copyright (c) 2019 win32ports +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once + +#ifndef __SYS_TIME_H_D9C1BEC0_4C79_4302_8B29_322C4497B27F__ +#define __SYS_TIME_H_D9C1BEC0_4C79_4302_8B29_322C4497B27F__ + +#ifndef _WIN32 + +#pragma message("this sys/time.h implementation is for Windows only!") + +#else /* _WIN32 */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if !defined(_WINSOCK2API_) && !defined(_WINSOCKAPI_) +#include /* timeval */ +#endif /* !defined(_WINSOCK2API_) && !defined(_WINSOCKAPI_) */ + +#include + +struct timezone +{ + int tz_minuteswest; + int tz_dsttime; +}; + +static int gettimeofday(struct timeval *tp, struct timezone *tzp) +{ + typedef void (__stdcall * pfnGetSystemTimePreciseAsFileTime)(LPFILETIME lpSystemTimeAsFileTime); + HMODULE hKernel32 = NULL; + pfnGetSystemTimePreciseAsFileTime fnGetSystemTimePreciseAsFileTime = NULL; + FILETIME time; + hKernel32 = GetModuleHandleW(L"kernel32.dll"); +#if defined(__GNUC__) && (__GNUC__ == 8) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif + if (hKernel32) + fnGetSystemTimePreciseAsFileTime = (pfnGetSystemTimePreciseAsFileTime) GetProcAddress(hKernel32, "GetSystemTimePreciseAsFileTime"); +#if defined(__GNUC__) && (__GNUC__ == 8) +#pragma GCC diagnostic pop +#endif + + if (fnGetSystemTimePreciseAsFileTime) + fnGetSystemTimePreciseAsFileTime(&time); + else + GetSystemTimeAsFileTime(&time); + + uint64_t time64 = ((uint64_t)time.dwHighDateTime << 32) | time.dwLowDateTime; + time64 = (time64 / 10 - 11644473600ULL * 1000000ULL); + + if (tp) + { + tp->tv_sec = (long) (time64 / 1000000ULL); + tp->tv_usec = (long) (time64 % 1000000ULL); + } + if (tzp) + { + /* The use of the timezone structure is obsolete; the tz argument should normally be specified as NULL. */ + TIME_ZONE_INFORMATION tzi; + GetTimeZoneInformation(&tzi); + + tzp->tz_minuteswest = tzi.Bias; + tzp->tz_dsttime = 0; + } + + /* The gettimeofday() function returns 0 and no value is reserved to indicate an error. */ + return 0; +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _WIN32 */ + +#endif /* __SYS_TIME_H_D9C1BEC0_4C79_4302_8B29_322C4497B27F__ */ diff --git a/lib/win32ports/sys/wait.h b/lib/win32ports/sys/wait.h new file mode 100644 index 0000000..4649bb8 --- /dev/null +++ b/lib/win32ports/sys/wait.h @@ -0,0 +1,520 @@ +/* +MIT License + +Copyright (c) 2019 win32ports + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once + +#ifndef __SYS_WAIT_H_B07AB843_5FF0_4FCF_B6F0_8CB97D28F337__ +#define __SYS_WAIT_H_B07AB843_5FF0_4FCF_B6F0_8CB97D28F337__ + +#ifndef _WIN32 + +#pragma message("this sys/wait.h implementation is for Windows only!") + +#else /* _WIN32 */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef __GNUC__ +#include /* for timeval */ +#endif /* __GNUC__ */ + +#include +#include + +#ifndef _INC_WINDOWS + +typedef unsigned long DWORD; +typedef DWORD * LPDWORD; + +#ifdef _WIN64 + +typedef long long LONG_PTR; +typedef unsigned long long ULONG_PTR; + +#else /* _WIN64 */ + +typedef long LONG_PTR; +typedef unsigned long ULONG_PTR; + +#endif + +typedef long LONG; +typedef wchar_t WCHAR; +typedef int BOOL; +typedef void VOID; +typedef void * HANDLE; + +#ifndef MAX_PATH +#define MAX_PATH 260 +#endif /* MAX_PATH */ + +#ifndef WINAPI +#define WINAPI __stdcall +#endif /* WINAPI */ + +#ifndef DECLSPEC_DLLIMPORT +#ifdef _MSC_VER +#define DECLSPEC_DLLIMPORT __declspec(dllimport) +#else /* _MSC_VER */ +#define DECLSPEC_DLLIMPORT +#endif /* _MSC_VER */ +#endif /* DECLSPEC_DLLIMPORT */ + +#ifndef WINBASEAPI +#define WINBASEAPI DECLSPEC_DLLIMPORT +#endif /* WINBASEAPI */ + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1) +#endif /* INVALID_HANDLE_VALUE */ + +#ifndef SYNCHRONIZE +#define SYNCHRONIZE (0x00100000L) +#endif /* SYNCHRONIZE */ + +#ifndef PROCESS_QUERY_INFORMATION +#define PROCESS_QUERY_INFORMATION (0x0400) +#endif /* PROCESS_QUERY_INFORMATION */ + +#ifndef INFINITE +#define INFINITE 0xFFFFFFFF +#endif /* INFINITE */ + +#ifndef WAIT_OBJECT_0 +#define WAIT_OBJECT_0 0 +#endif /* WAIT_OBJECT_0 */ + +#ifndef WAIT_TIMEOUT +#define WAIT_TIMEOUT 258L +#endif /* WAIT_TIMEOUT */ + +/* +FIXME: causes FILETIME to conflict +#ifndef _FILETIME_ +#define _FILETIME_ + +typedef struct FILETIME { + DWORD dwLowDateTime; + DWORD dwHighDateTime; +} FILETIME, *PFILETIME, *LPFILETIME; + +#endif +*/ + +WINBASEAPI DWORD WINAPI GetCurrentProcessId(VOID); +WINBASEAPI BOOL WINAPI CloseHandle(HANDLE hObject); +WINBASEAPI HANDLE WINAPI OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId); +WINBASEAPI DWORD WINAPI WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); +WINBASEAPI BOOL WINAPI GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode); + +/* +FIXME: causes FILETIME to conflict +WINBASEAPI BOOL WINAPI GetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime); +*/ + +#endif /* _INC_WINDOWS */ + +#ifndef _WINSOCKAPI_ + +struct private_timeval { + long tv_sec; + long tv_usec; +}; + +#define timeval private_timeval + +#endif /* _WINSOCKAPI_ */ + +#ifndef _INC_TOOLHELP32 + +typedef struct tagPROCESSENTRY32W +{ + DWORD dwSize; + DWORD cntUsage; + DWORD th32ProcessID; + ULONG_PTR th32DefaultHeapID; + DWORD th32ModuleID; + DWORD cntThreads; + DWORD th32ParentProcessID; + LONG pcPriClassBase; + DWORD dwFlags; + WCHAR szExeFile[MAX_PATH]; +} PROCESSENTRY32W; +typedef PROCESSENTRY32W * PPROCESSENTRY32W; +typedef PROCESSENTRY32W * LPPROCESSENTRY32W; + +#ifndef TH32CS_SNAPPROCESS +#define TH32CS_SNAPPROCESS 2 +#endif /* TH32CS_SNAPPROCESS */ + +HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID); +BOOL WINAPI Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe); +BOOL WINAPI Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe); + +#endif /* _INC_TOOLHELP32 */ + +#ifndef WNOHANG +#define WNOHANG 1 +#endif /* WNOHANG */ + +#ifndef WUNTRACED +#define WUNTRACED 2 +#endif /* WUNTRACED */ + +#ifndef __WEXITSTATUS +#define __WEXITSTATUS(status) (((status) & 0xFF00) >> 8) +#endif /* __WEXITSTATUS */ + +#ifndef __WIFEXITED +#define __WIFEXITED(status) (__WTERMSIG(status) == 0) +#endif /* __WIFEXITED */ + +#ifndef __WTERMSIG +#define __WTERMSIG(status) ((status) & 0x7F) +#endif /* __WTERMSIG */ + +#ifndef __WIFSIGNALED +#define __WIFSIGNALED(status) (((signed char)(__WTERMSIG(status) + 1) >> 1) > 0) +#endif /* __WIFSIGNALED */ + +#ifndef __WIFSTOPPED +#define __WIFSTOPPED(status) (((status) & 0xFF) == 0x7F) +#endif /* __WIFSTOPPED */ + +#ifndef __WSTOPSIG +#define __WSTOPSIG(status) __WEXITSTATUS(status) +#endif /* __WSTOPSIG */ + +#ifndef __WCONTINUED +#define __WCONTINUED 8 +#endif /* __WCONTINUED */ + +#ifndef __WNOWAIT +#define __WNOWAIT 0x01000000 +#endif /* __WNOWAIT */ + +#ifndef WEXITSTATUS +#define WEXITSTATUS(status) __WEXITSTATUS(status) +#endif /* WEXITSTATUS */ + +#ifndef WIFEXITED +#define WIFEXITED(status) __WIFEXITED(status) +#endif /* WIFEXITED */ + +#ifndef WIFSIGNALED +#define WIFSIGNALED(status) __WIFSIGNALED(status) +#endif /* WIFSIGNALED */ + +#ifndef WTERMSIG +#define WTERMSIG(status) __WTERMSIG(status) +#endif /* WTERMSIG */ + +#ifndef WIFSTOPPED +#define WIFSTOPPED(status) __WIFSTOPPED(status) +#endif /* WIFSTOPPED */ + +#ifndef WSTOPSIG +#define WSTOPSIG(status) __WSTOPSIG(status) +#endif /* WSTOPSIG */ + +#if !defined(__pid_t_defined) && !defined(_PID_T_) && !defined(pid_t) +#define __pid_t_defined 1 +#define _PID_T_ +typedef int __pid_t; +typedef __pid_t pid_t; +#endif /* !defined(__pid_t_defined) && !defined(_PID_T_) && !defined(pid_t) */ + +#ifndef __id_t_defined +#define __id_t_defined 1 +typedef unsigned __id_t; +typedef __id_t id_t; +#endif /* __id_t_defined */ + +#ifndef __uid_t_defined +#define __uid_t_defined 1 +typedef unsigned __uid_t; +typedef __uid_t uid_t; +#endif /* __uid_t_defined */ + +#ifndef __siginfo_t_defined +#define __siginfo_t_defined 1 +typedef struct +{ + int si_signo; /* signal number */ + int si_code; /* signal code */ + int si_errno; /* if non-zero, errno associated with this signal, as defined in */ + pid_t si_pid; /* sending process ID */ + uid_t si_uid; /* real user ID of sending process */ + void * si_addr; /* address of faulting instruction */ + int si_status; /* exit value of signal */ + long si_band; /* band event of SIGPOLL */ +} +siginfo_t; +#endif /* __siginfo_t_defined */ + +struct rusage +{ + struct timeval ru_utime; /* user time used */ + struct timeval ru_stime; /* system time used */ +}; + +#ifdef _XOPEN_SOURCE + +#ifndef __W_CONTINUED +#define __W_CONTINUED 0xFFFF +#endif /* __W_CONTINUED */ + +#ifndef __WIFCONTINUED +#define __WIFCONTINUED(status) ((status) == __W_CONTINUED) +#endif /* __WIFCONTINUED */ + +#ifndef WIFCONTINUED +#define WIFCONTINUED(status) __WIFCONTINUED(status) +#endif /* WIFCONTINUED */ + +#ifndef WSTOPPED +#define WSTOPPED 2 +#endif /* WSTOPPED */ + +#ifndef WEXITED +#define WEXITED 4 +#endif /* WEXITED */ + +#ifndef WCONTINUED +#define WCONTINUED __WCONTINUED +#endif /* WCONTINUED */ + +#ifndef WNOWAIT +#define WNOWAIT __WNOWAIT +#endif /* WNOWAIT */ + +typedef enum +{ + P_ALL, + P_PID, + P_PGID +} +idtype_t; + +#endif /* _XOPEN_SOURCE */ + +static int __filter_anychild(PROCESSENTRY32W * pe, DWORD pid) +{ + return pe->th32ParentProcessID == GetCurrentProcessId(); +} + +static int __filter_pid(PROCESSENTRY32W * pe, DWORD pid) +{ + return pe->th32ProcessID == pid; +} + +/* +FIXME: causes FILETIME to conflict +static void __filetime2timeval(FILETIME time, struct timeval * out) +{ + unsigned long long value = time.dwHighDateTime; + value = (value << 32) | time.dwLowDateTime; + out->tv_sec = (long)(value / 1000000); + out->tv_usec = (long)(value % 1000000); +} +*/ + +static int __waitpid_internal(pid_t pid, int * status, int options, siginfo_t * infop, struct rusage * rusage) +{ + int saved_status = 0; + HANDLE hProcess = INVALID_HANDLE_VALUE, hSnapshot = INVALID_HANDLE_VALUE; + int (*filter)(PROCESSENTRY32W*, DWORD); + PROCESSENTRY32W pe; + DWORD wait_status = 0, exit_code = 0; + int nohang = WNOHANG == (WNOHANG & options); + options &= ~(WUNTRACED | __WNOWAIT | __WCONTINUED | WNOHANG); + if (options) + { + errno = -EINVAL; + return -1; + } + + if (pid == -1) + { + /* wait for any child */ + filter = __filter_anychild; + } + else if (pid < -1) + { + /* wait for any process from the group */ + abort(); /* not implemented */ + } + else if (pid == 0) + { + /* wait for any process from the current group */ + abort(); /* not implemented */ + } + else + { + /* wait for process with given pid */ + filter = __filter_pid; + } + + hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (INVALID_HANDLE_VALUE == hSnapshot) + { + errno = ECHILD; + return -1; + } + pe.dwSize = sizeof(pe); + if (!Process32FirstW(hSnapshot, &pe)) + { + CloseHandle(hSnapshot); + errno = ECHILD; + return -1; + } + do + { + if (filter(&pe, pid)) + { + hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, 0, pe.th32ProcessID); + if (INVALID_HANDLE_VALUE == hProcess) + { + CloseHandle(hSnapshot); + errno = ECHILD; + return -1; + } + break; + } + } + while (Process32NextW(hSnapshot, &pe)); + if (INVALID_HANDLE_VALUE == hProcess) + { + CloseHandle(hSnapshot); + errno = ECHILD; + return -1; + } + + wait_status = WaitForSingleObject(hProcess, nohang ? 0 : INFINITE); + + if (WAIT_OBJECT_0 == wait_status) + { + if (GetExitCodeProcess(hProcess, &exit_code)) + saved_status |= (exit_code & 0xFF) << 8; + } + else if (WAIT_TIMEOUT == wait_status && nohang) + { + return 0; + } + else + { + CloseHandle(hProcess); + CloseHandle(hSnapshot); + errno = ECHILD; + return -1; + } + if (rusage) + { + memset(rusage, 0, sizeof(*rusage)); + /* + FIXME: causes FILETIME to conflict + FILETIME creation_time, exit_time, kernel_time, user_time; + if (GetProcessTimes(hProcess, &creation_time, &exit_time, &kernel_time, &user_time)) + { + __filetime2timeval(kernel_time, &rusage->ru_stime); + __filetime2timeval(user_time, &rusage->ru_utime); + } + */ + } + if (infop) + { + memset(infop, 0, sizeof(*infop)); + } + + CloseHandle(hProcess); + CloseHandle(hSnapshot); + + if (status) + *status = saved_status; + + return pe.th32ParentProcessID; +} + +static int waitpid(pid_t pid, int * status, int options) +{ + return __waitpid_internal(pid, status, options, NULL, NULL); +} + +static int wait(int *status) +{ + return __waitpid_internal(-1, status, 0, NULL, NULL); +} + +#ifdef _XOPEN_SOURCE + +static int waitid(idtype_t idtype, id_t id, siginfo_t * infop, int options) +{ + pid_t pid; + switch (idtype) + { + case P_PID: pid = id; break; + case P_PGID: pid = -(pid_t)id; break; + case P_ALL: pid = 0; break; + default: errno = EINVAL; return -1; + } + return __waitpid_internal(pid, NULL, options, infop, NULL); +} + +static pid_t wait3(int * status, int options, struct rusage * rusage) +{ + return __waitpid_internal(-1, status, options, NULL, rusage); +} + +static pid_t wait4(pid_t pid, int * status, int options, struct rusage * rusage) +{ + return __waitpid_internal(pid, status, options, NULL, rusage); +} + +#endif /* _XOPEN_SOURCE */ + +#ifndef _INC_WINDOWS + +#undef WAIT_OBJECT_0 + +#undef FILETIME +#undef PFILETIME +#undef LPFILETIME + +#endif /* _INC_WINDOWS */ + +#ifndef _WINSOCKAPI_ + +#undef timeval + +#endif /* _WINSOCKAPI_ */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _WIN32 */ + +#endif /* __SYS_WAIT_H_B07AB843_5FF0_4FCF_B6F0_8CB97D28F337__ */ diff --git a/lib/win32ports/unistd.h b/lib/win32ports/unistd.h new file mode 100644 index 0000000..8c6fde0 --- /dev/null +++ b/lib/win32ports/unistd.h @@ -0,0 +1,314 @@ +/* +MIT License +Copyright (c) 2019 win32ports +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once + +#ifndef __UNISTD_H_17CD2BD1_839A_4E25_97C7_DE9544B8B59C__ +#define __UNISTD_H_17CD2BD1_839A_4E25_97C7_DE9544B8B59C__ + +#ifndef _WIN32 + +#pragma message("this unistd.h implementation is for Windows only!") + +#else /* _WIN32 */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef _INC_IO +#include /* _access() */ +#endif /* _INC_IO */ + +#ifndef _INC_DIRECT +#include /* _chdir() */ +#endif /* _INC_DIRECT */ + +#ifndef _INC_PROCESS +#include /* _execl() */ +#endif /* _INC_PROCESS */ + +#include /* */ + +#ifndef access +#define access _access +#endif /* access */ + +#ifndef R_OK +#define R_OK 04 +#endif /* R_OK */ + +#ifndef W_OK +#define W_OK 02 +#endif /* W_OK */ + +#ifndef X_OK +#define X_OK R_OK +#endif /* X_OK */ + +#ifndef F_OK +#define F_OK 00 +#endif /* F_OK */ + +#ifndef chdir +#define chdir _chdir +#endif /* chdir */ + +#ifndef close +#define close _close +#endif /* close */ + +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif /* STDIN_FILENO */ + +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif /* STDOUT_FILENO */ + +#ifndef STDERR_FILENO +#define STDERR_FILENO 2 +#endif /* STDERR_FILENO */ + +#ifndef dup +#define dup _dup +#endif /* dup */ + +#ifndef dup2 +#define dup2 _dup2 +#endif /* dup2 */ + +#ifndef execl +#define execl _execl +#endif /* execl */ + +#ifndef execle +#define execle _execle +#endif /* execle */ + +#ifndef execlp +#define execlp _execlp +#endif /* execlp */ + +#ifndef execp +#define execp _execp +#endif /* execp */ + +#ifndef execpe +#define execpe _execpe +#endif /* execpe */ + +#ifndef execpp +#define execpp _execpp +#endif /* execpp */ + +#ifndef rmdir +#define rmdir _rmdir +#endif /* rmdir */ + +#ifndef unlink +#define unlink _unlink +#endif /* unlink */ + +/* permission bits below must be defined in sys/stat.h, but MSVC lacks them */ + +#ifndef S_IRWXU +#define S_IRWXU 0700 +#endif /* S_IRWXU */ + +#ifndef S_IRUSR +#define S_IRUSR 0400 +#endif /* S_IRUSR */ + +#ifndef S_IWUSR +#define S_IWUSR 0200 +#endif /* S_IWUSR */ + +#ifndef S_IXUSR +#define S_IXUSR 0100 +#endif /* S_IXUSR */ + +#ifndef S_IRWXG +#define S_IRWXG 070 +#endif /* S_IRWXG */ + +#ifndef S_IRGRP +#define S_IRGRP 040 +#endif /* S_IRGRP */ + +#ifndef S_IWGRP +#define S_IWGRP 020 +#endif /* S_IWGRP */ + +#ifndef S_IXGRP +#define S_IXGRP 010 +#endif /* S_IXGRP */ + +#ifndef S_IRWXO +#define S_IRWXO 07 +#endif /* S_IRWXO */ + +#ifndef S_IROTH +#define S_IROTH 04 +#endif /* S_IROTH */ + +#ifndef S_IWOTH +#define S_IWOTH 02 +#endif /* S_IWOTH */ + +#ifndef S_IXOTH +#define S_IXOTH 01 +#endif /* S_IXOTH */ + +#ifndef S_ISUID +#define S_ISUID 04000 +#endif /* S_ISUID */ + +#ifndef S_ISGID +#define S_ISGID 02000 +#endif /* S_ISGID */ + +#ifndef S_ISVTX +#define S_ISVTX 01000 +#endif /* S_ISVTX */ + +#ifndef S_IRWXUGO +#define S_IRWXUGO 0777 +#endif /* S_IRWXUGO */ + +#ifndef S_IALLUGO +#define S_IALLUGO 0777 +#endif /* S_IALLUGO */ + +#ifndef S_IRUGO +#define S_IRUGO 0444 +#endif /* S_IRUGO */ + +#ifndef S_IWUGO +#define S_IWUGO 0222 +#endif /* S_IWUGO */ + +#ifndef S_IXUGO +#define S_IXUGO 0111 +#endif /* S_IXUGO */ + +#ifndef _S_IFMT +#define _S_IFMT 0xF000 +#endif /* _S_IFMT */ + +#ifndef _S_IFIFO +#define _S_IFIFO 0x1000 +#endif /* _S_IFIFO */ + +#ifndef _S_IFCHR +#define _S_IFCHR 0x2000 +#endif /* _S_IFCHR */ + +#ifndef _S_IFDIR +#define _S_IFDIR 0x4000 +#endif /* _S_IFDIR */ + +#ifndef _S_IFBLK +#define _S_IFBLK 0x6000 +#endif /* _S_IFBLK */ + +#ifndef _S_IFREG +#define _S_IFREG 0x8000 +#endif /* _S_IFREG */ + +#ifndef _S_IFLNK +#define _S_IFLNK 0xA000 +#endif /* _S_IFLNK */ + +#ifndef _S_IFSOCK +#define _S_IFSOCK 0xC000 +#endif /* _S_IFSOCK */ + +#ifndef S_IFMT +#define S_IFMT _S_IFMT +#endif /* S_IFMT */ + +#ifndef S_IFIFO +#define S_IFIFO _S_IFIFO +#endif /* S_IFIFO */ + +#ifndef S_IFCHR +#define S_IFCHR _S_IFCHR +#endif /* S_IFCHR */ + +#ifndef S_IFDIR +#define S_IFDIR _S_IFDIR +#endif /* S_IFDIR */ + +#ifndef S_IFBLK +#define S_IFBLK _S_IFBLK +#endif /* S_IFBLK */ + +#ifndef S_IFREG +#define S_IFREG _S_IFREG +#endif /* S_IFREG */ + +#ifndef S_IFLNK +#define S_IFLNK _S_IFLNK +#endif /* S_IFLNK */ + +#ifndef S_IFSOCK +#define S_IFSOCK _S_IFSOCK +#endif /* S_IFSOCK */ + +#ifndef S_ISTYPE +#define S_ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask)) +#endif /* S_ISTYPE */ + +#ifndef S_ISFIFO +#define S_ISFIFO(mode) S_ISTYPE(mode, S_IFIFO) +#endif /* S_ISFIFO */ + +#ifndef S_ISCHR +#define S_ISCHR(mode) S_ISTYPE(mode, S_IFCHR) +#endif /* S_ISCHR */ + +#ifndef S_ISDIR +#define S_ISDIR(mode) S_ISTYPE(mode, S_IFDIR) +#endif /* S_ISDIR */ + +#ifndef S_ISBLK +#define S_ISBLK(mode) S_ISTYPE(mode, S_IFBLK) +#endif /* S_ISBLK */ + +#ifndef S_ISREG +#define S_ISREG(mode) S_ISTYPE(mode, S_IFREG) +#endif /* S_ISREG */ + +#ifndef S_ISLNK +#define S_ISLNK(mode) S_ISTYPE(mode, S_IFLNK) +#endif /* S_ISLNK */ + +#ifndef S_ISSOCK +#define S_ISSOCK(mode) S_ISTYPE(mode, S_IFSOCK) +#endif /* S_ISSOCK */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _WIN32 */ + +#endif /* __UNISTD_H_17CD2BD1_839A_4E25_97C7_DE9544B8B59C__ */