From e1e6a01d6ae09f3d74155df84b8e1f41c01b3896 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Thu, 5 Oct 2023 12:24:39 +0200 Subject: Windows code rework --- src/lib/ndpi_main.c | 2 +- src/lib/third_party/include/dirent.h | 584 ----------- src/lib/third_party/include/windows/dirent.h | 584 +++++++++++ src/lib/third_party/include/windows/getopt.h | 136 +++ src/lib/third_party/src/windows/getopt.c | 972 +++++++++++++++++++ src/lib/third_party/src/windows/gettimeofday.c | 55 ++ windows/src/dirent.h | 1239 ------------------------ windows/src/getopt.c | 973 +------------------ windows/src/getopt.h | 137 +-- windows/src/win-gettimeofday.c | 56 +- 10 files changed, 1751 insertions(+), 2987 deletions(-) delete mode 100644 src/lib/third_party/include/dirent.h create mode 100644 src/lib/third_party/include/windows/dirent.h create mode 100644 src/lib/third_party/include/windows/getopt.h create mode 100644 src/lib/third_party/src/windows/getopt.c create mode 100644 src/lib/third_party/src/windows/gettimeofday.c delete mode 100644 windows/src/dirent.h mode change 100644 => 120000 windows/src/getopt.c mode change 100644 => 120000 windows/src/getopt.h mode change 100644 => 120000 windows/src/win-gettimeofday.c diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index f72bfdae6..0cc26233d 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -48,7 +48,7 @@ #include #include #else -#include "dirent.h" +#include "third_party/include/windows/dirent.h" #endif #ifndef TH_FIN diff --git a/src/lib/third_party/include/dirent.h b/src/lib/third_party/include/dirent.h deleted file mode 100644 index de75def2f..000000000 --- a/src/lib/third_party/include/dirent.h +++ /dev/null @@ -1,584 +0,0 @@ -/* -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/src/lib/third_party/include/windows/dirent.h b/src/lib/third_party/include/windows/dirent.h new file mode 100644 index 000000000..de75def2f --- /dev/null +++ b/src/lib/third_party/include/windows/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/src/lib/third_party/include/windows/getopt.h b/src/lib/third_party/include/windows/getopt.h new file mode 100644 index 000000000..5e33682de --- /dev/null +++ b/src/lib/third_party/include/windows/getopt.h @@ -0,0 +1,136 @@ +/* Getopt for Microsoft C +This code is a modification of the Free Software Foundation, Inc. +Getopt library for parsing command line argument the purpose was +to provide a Microsoft Visual C friendly derivative. This code +provides functionality for both Unicode and Multibyte builds. + +Date: 02/03/2011 - Ludvik Jerabek - Initial Release +Version: 1.0 +Comment: Supports getopt, getopt_long, and getopt_long_only +and POSIXLY_CORRECT environment flag +License: LGPL + +Revisions: + +02/03/2011 - Ludvik Jerabek - Initial Release +02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4 +07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs +08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception +08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB +02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file +08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi +10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features +06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable + +**DISCLAIMER** +THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE +EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT +APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY +DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY +USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST +PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON +YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE +EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +*/ +#ifndef __GETOPT_H_ + #define __GETOPT_H_ + + #ifdef _GETOPT_API + #undef _GETOPT_API + #endif + + #if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT) + #error "The preprocessor definitions of EXPORTS_GETOPT and STATIC_GETOPT can only be used individually" + #elif defined(STATIC_GETOPT) + #pragma message("Warning static builds of getopt violate the Lesser GNU Public License") + #define _GETOPT_API + #elif defined(EXPORTS_GETOPT) + #pragma message("Exporting getopt library") + #define _GETOPT_API __declspec(dllexport) + #else + #pragma message("Importing getopt library") + #define _GETOPT_API __declspec(dllimport) + #endif + + // Change behavior for C\C++ + #ifdef __cplusplus + #define _GETOPT_BEGIN_EXTERN_C extern "C" { + #define _GETOPT_END_EXTERN_C } + #define _GETOPT_THROW throw() + #else + #define _GETOPT_BEGIN_EXTERN_C + #define _GETOPT_END_EXTERN_C + #define _GETOPT_THROW + #endif + + // Standard GNU options + #define null_argument 0 /*Argument Null*/ + #define no_argument 0 /*Argument Switch Only*/ + #define required_argument 1 /*Argument Required*/ + #define optional_argument 2 /*Argument Optional*/ + + // Shorter Options + #define ARG_NULL 0 /*Argument Null*/ + #define ARG_NONE 0 /*Argument Switch Only*/ + #define ARG_REQ 1 /*Argument Required*/ + #define ARG_OPT 2 /*Argument Optional*/ + + #include + #include + +_GETOPT_BEGIN_EXTERN_C + + extern _GETOPT_API int optind; + extern _GETOPT_API int opterr; + extern _GETOPT_API int optopt; + + // Ansi + struct option_a + { + const char* name; + int has_arg; + int *flag; + int val; + }; + extern _GETOPT_API char *optarg_a; + extern _GETOPT_API int getopt_a(int argc, char *const *argv, const char *optstring) _GETOPT_THROW; + extern _GETOPT_API int getopt_long_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW; + extern _GETOPT_API int getopt_long_only_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW; + + // Unicode + struct option_w + { + const wchar_t* name; + int has_arg; + int *flag; + int val; + }; + extern _GETOPT_API wchar_t *optarg_w; + extern _GETOPT_API int getopt_w(int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW; + extern _GETOPT_API int getopt_long_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW; + extern _GETOPT_API int getopt_long_only_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW; + +_GETOPT_END_EXTERN_C + + #undef _GETOPT_BEGIN_EXTERN_C + #undef _GETOPT_END_EXTERN_C + #undef _GETOPT_THROW + #undef _GETOPT_API + + #ifdef _UNICODE + #define getopt getopt_w + #define getopt_long getopt_long_w + #define getopt_long_only getopt_long_only_w + #define option option_w + #define optarg optarg_w + #else + #define getopt getopt_a + #define getopt_long getopt_long_a + #define getopt_long_only getopt_long_only_a + #define option option_a + #define optarg optarg_a + #endif +#endif // __GETOPT_H_ diff --git a/src/lib/third_party/src/windows/getopt.c b/src/lib/third_party/src/windows/getopt.c new file mode 100644 index 000000000..ddd7104e0 --- /dev/null +++ b/src/lib/third_party/src/windows/getopt.c @@ -0,0 +1,972 @@ +/* Getopt for Microsoft C +This code is a modification of the Free Software Foundation, Inc. +Getopt library for parsing command line argument the purpose was +to provide a Microsoft Visual C friendly derivative. This code +provides functionality for both Unicode and Multibyte builds. + +Date: 02/03/2011 - Ludvik Jerabek - Initial Release +Version: 1.0 +Comment: Supports getopt, getopt_long, and getopt_long_only +and POSIXLY_CORRECT environment flag +License: LGPL + +Revisions: + +02/03/2011 - Ludvik Jerabek - Initial Release +02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4 +07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs +08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception +08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB +02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file +08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi +10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features +06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable + +**DISCLAIMER** +THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE +EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT +APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY +DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY +USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST +PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON +YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE +EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +*/ +#include +#include +#include +#include "getopt.h" + +#ifdef __cplusplus + #define _GETOPT_THROW throw() +#else + #define _GETOPT_THROW +#endif + +int optind = 1; +int opterr = 1; +int optopt = '?'; +enum ENUM_ORDERING { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER }; + +// +// +// Ansi structures and functions follow +// +// + +static struct _getopt_data_a +{ + int optind; + int opterr; + int optopt; + char *optarg; + int __initialized; + char *__nextchar; + enum ENUM_ORDERING __ordering; + int __posixly_correct; + int __first_nonopt; + int __last_nonopt; +} getopt_data_a; +char *optarg_a; + +static void exchange_a(char **argv, struct _getopt_data_a *d) +{ + int bottom = d->__first_nonopt; + int middle = d->__last_nonopt; + int top = d->optind; + char *tem; + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + int len = middle - bottom; + register int i; + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + top -= len; + } + else + { + int len = top - middle; + register int i; + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + bottom += len; + } + } + d->__first_nonopt += (d->optind - d->__last_nonopt); + d->__last_nonopt = d->optind; +} +static const char *_getopt_initialize_a (const char *optstring, struct _getopt_data_a *d, int posixly_correct) +{ + d->__first_nonopt = d->__last_nonopt = d->optind; + d->__nextchar = NULL; + d->__posixly_correct = posixly_correct | !!getenv("POSIXLY_CORRECT"); + if (optstring[0] == '-') + { + d->__ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + d->__ordering = REQUIRE_ORDER; + ++optstring; + } + else if (d->__posixly_correct) + d->__ordering = REQUIRE_ORDER; + else + d->__ordering = PERMUTE; + return optstring; +} +int _getopt_internal_r_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, struct _getopt_data_a *d, int posixly_correct) +{ + int print_errors = d->opterr; + if (argc < 1) + return -1; + d->optarg = NULL; + if (d->optind == 0 || !d->__initialized) + { + if (d->optind == 0) + d->optind = 1; + optstring = _getopt_initialize_a (optstring, d, posixly_correct); + d->__initialized = 1; + } + else if (optstring[0] == '-' || optstring[0] == '+') + optstring++; + if (optstring[0] == ':') + print_errors = 0; + if (d->__nextchar == NULL || *d->__nextchar == '\0') + { + if (d->__last_nonopt > d->optind) + d->__last_nonopt = d->optind; + if (d->__first_nonopt > d->optind) + d->__first_nonopt = d->optind; + if (d->__ordering == PERMUTE) + { + if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) + exchange_a ((char **) argv, d); + else if (d->__last_nonopt != d->optind) + d->__first_nonopt = d->optind; + while (d->optind < argc && (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')) + d->optind++; + d->__last_nonopt = d->optind; + } + if (d->optind != argc && !strcmp(argv[d->optind], "--")) + { + d->optind++; + if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) + exchange_a((char **) argv, d); + else if (d->__first_nonopt == d->__last_nonopt) + d->__first_nonopt = d->optind; + d->__last_nonopt = argc; + d->optind = argc; + } + if (d->optind == argc) + { + if (d->__first_nonopt != d->__last_nonopt) + d->optind = d->__first_nonopt; + return -1; + } + if ((argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')) + { + if (d->__ordering == REQUIRE_ORDER) + return -1; + d->optarg = argv[d->optind++]; + return 1; + } + d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == '-')); + } + if (longopts != NULL && (argv[d->optind][1] == '-' || (long_only && (argv[d->optind][2] || !strchr(optstring, argv[d->optind][1]))))) + { + char *nameend; + unsigned int namelen; + const struct option_a *p; + const struct option_a *pfound = NULL; + struct option_list + { + const struct option_a *p; + struct option_list *next; + } *ambig_list = NULL; + int exact = 0; + int indfound = -1; + int option_index; + for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++); + namelen = (unsigned int)(nameend - d->__nextchar); + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp(p->name, d->__nextchar, namelen)) + { + if (namelen == (unsigned int)strlen(p->name)) + { + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + pfound = p; + indfound = option_index; + } + else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) + { + struct option_list *newp = (struct option_list*)alloca(sizeof(*newp)); + newp->p = p; + newp->next = ambig_list; + ambig_list = newp; + } + } + if (ambig_list != NULL && !exact) + { + if (print_errors) + { + struct option_list first; + first.p = pfound; + first.next = ambig_list; + ambig_list = &first; + fprintf (stderr, "%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]); + do + { + fprintf (stderr, " '--%s'", ambig_list->p->name); + ambig_list = ambig_list->next; + } + while (ambig_list != NULL); + fputc ('\n', stderr); + } + d->__nextchar += strlen(d->__nextchar); + d->optind++; + d->optopt = 0; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + d->optind++; + if (*nameend) + { + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + { + if (argv[d->optind - 1][1] == '-') + { + fprintf(stderr, "%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name); + } + else + { + fprintf(stderr, "%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name); + } + } + d->__nextchar += strlen(d->__nextchar); + d->optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + { + fprintf(stderr,"%s: option '--%s' requires an argument\n",argv[0], pfound->name); + } + d->__nextchar += strlen(d->__nextchar); + d->optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + d->__nextchar += strlen(d->__nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + if (!long_only || argv[d->optind][1] == '-' || strchr(optstring, *d->__nextchar) == NULL) + { + if (print_errors) + { + if (argv[d->optind][1] == '-') + { + fprintf(stderr, "%s: unrecognized option '--%s'\n",argv[0], d->__nextchar); + } + else + { + fprintf(stderr, "%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar); + } + } + d->__nextchar = (char *)""; + d->optind++; + d->optopt = 0; + return '?'; + } + } + { + char c = *d->__nextchar++; + char *temp = (char*)strchr(optstring, c); + if (*d->__nextchar == '\0') + ++d->optind; + if (temp == NULL || c == ':' || c == ';') + { + if (print_errors) + { + fprintf(stderr, "%s: invalid option -- '%c'\n", argv[0], c); + } + d->optopt = c; + return '?'; + } + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option_a *p; + const struct option_a *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + if (longopts == NULL) + goto no_longs; + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + { + fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c); + } + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + d->optarg = argv[d->optind++]; + for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; nameend++); + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp(p->name, d->__nextchar, nameend - d->__nextchar)) + { + if ((unsigned int) (nameend - d->__nextchar) == strlen(p->name)) + { + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + pfound = p; + indfound = option_index; + } + else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) + ambig = 1; + } + if (ambig && !exact) + { + if (print_errors) + { + fprintf(stderr, "%s: option '-W %s' is ambiguous\n",argv[0], d->optarg); + } + d->__nextchar += strlen(d->__nextchar); + d->optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + { + fprintf(stderr, "%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name); + } + d->__nextchar += strlen(d->__nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + { + fprintf(stderr, "%s: option '-W %s' requires an argument\n",argv[0], pfound->name); + } + d->__nextchar += strlen(d->__nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + else + d->optarg = NULL; + d->__nextchar += strlen(d->__nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } +no_longs: + d->__nextchar = NULL; + return 'W'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else + d->optarg = NULL; + d->__nextchar = NULL; + } + else + { + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + { + fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c); + } + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + d->optarg = argv[d->optind++]; + d->__nextchar = NULL; + } + } + return c; + } +} +int _getopt_internal_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, int posixly_correct) +{ + int result; + getopt_data_a.optind = optind; + getopt_data_a.opterr = opterr; + result = _getopt_internal_r_a (argc, argv, optstring, longopts,longind, long_only, &getopt_data_a,posixly_correct); + optind = getopt_data_a.optind; + optarg_a = getopt_data_a.optarg; + optopt = getopt_data_a.optopt; + return result; +} +int getopt_a (int argc, char *const *argv, const char *optstring) _GETOPT_THROW +{ + return _getopt_internal_a (argc, argv, optstring, (const struct option_a *) 0, (int *) 0, 0, 0); +} +int getopt_long_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW +{ + return _getopt_internal_a (argc, argv, options, long_options, opt_index, 0, 0); +} +int getopt_long_only_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW +{ + return _getopt_internal_a (argc, argv, options, long_options, opt_index, 1, 0); +} +int _getopt_long_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d) +{ + return _getopt_internal_r_a (argc, argv, options, long_options, opt_index,0, d, 0); +} +int _getopt_long_only_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d) +{ + return _getopt_internal_r_a (argc, argv, options, long_options, opt_index, 1, d, 0); +} + +// +// +// Unicode Structures and Functions +// +// + +static struct _getopt_data_w +{ + int optind; + int opterr; + int optopt; + wchar_t *optarg; + int __initialized; + wchar_t *__nextchar; + enum ENUM_ORDERING __ordering; + int __posixly_correct; + int __first_nonopt; + int __last_nonopt; +} getopt_data_w; +wchar_t *optarg_w; + +static void exchange_w(wchar_t **argv, struct _getopt_data_w *d) +{ + int bottom = d->__first_nonopt; + int middle = d->__last_nonopt; + int top = d->optind; + wchar_t *tem; + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + int len = middle - bottom; + register int i; + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + top -= len; + } + else + { + int len = top - middle; + register int i; + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + bottom += len; + } + } + d->__first_nonopt += (d->optind - d->__last_nonopt); + d->__last_nonopt = d->optind; +} +static const wchar_t *_getopt_initialize_w (const wchar_t *optstring, struct _getopt_data_w *d, int posixly_correct) +{ + d->__first_nonopt = d->__last_nonopt = d->optind; + d->__nextchar = NULL; + d->__posixly_correct = posixly_correct | !!_wgetenv(L"POSIXLY_CORRECT"); + if (optstring[0] == L'-') + { + d->__ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == L'+') + { + d->__ordering = REQUIRE_ORDER; + ++optstring; + } + else if (d->__posixly_correct) + d->__ordering = REQUIRE_ORDER; + else + d->__ordering = PERMUTE; + return optstring; +} +int _getopt_internal_r_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, struct _getopt_data_w *d, int posixly_correct) +{ + int print_errors = d->opterr; + if (argc < 1) + return -1; + d->optarg = NULL; + if (d->optind == 0 || !d->__initialized) + { + if (d->optind == 0) + d->optind = 1; + optstring = _getopt_initialize_w (optstring, d, posixly_correct); + d->__initialized = 1; + } + else if (optstring[0] == L'-' || optstring[0] == L'+') + optstring++; + if (optstring[0] == L':') + print_errors = 0; + if (d->__nextchar == NULL || *d->__nextchar == L'\0') + { + if (d->__last_nonopt > d->optind) + d->__last_nonopt = d->optind; + if (d->__first_nonopt > d->optind) + d->__first_nonopt = d->optind; + if (d->__ordering == PERMUTE) + { + if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) + exchange_w((wchar_t **) argv, d); + else if (d->__last_nonopt != d->optind) + d->__first_nonopt = d->optind; + while (d->optind < argc && (argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0')) + d->optind++; + d->__last_nonopt = d->optind; + } + if (d->optind != argc && !wcscmp(argv[d->optind], L"--")) + { + d->optind++; + if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) + exchange_w((wchar_t **) argv, d); + else if (d->__first_nonopt == d->__last_nonopt) + d->__first_nonopt = d->optind; + d->__last_nonopt = argc; + d->optind = argc; + } + if (d->optind == argc) + { + if (d->__first_nonopt != d->__last_nonopt) + d->optind = d->__first_nonopt; + return -1; + } + if ((argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0')) + { + if (d->__ordering == REQUIRE_ORDER) + return -1; + d->optarg = argv[d->optind++]; + return 1; + } + d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == L'-')); + } + if (longopts != NULL && (argv[d->optind][1] == L'-' || (long_only && (argv[d->optind][2] || !wcschr(optstring, argv[d->optind][1]))))) + { + wchar_t *nameend; + unsigned int namelen; + const struct option_w *p; + const struct option_w *pfound = NULL; + struct option_list + { + const struct option_w *p; + struct option_list *next; + } *ambig_list = NULL; + int exact = 0; + int indfound = -1; + int option_index; + for (nameend = d->__nextchar; *nameend && *nameend != L'='; nameend++); + namelen = (unsigned int)(nameend - d->__nextchar); + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!wcsncmp(p->name, d->__nextchar, namelen)) + { + if (namelen == (unsigned int)wcslen(p->name)) + { + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + pfound = p; + indfound = option_index; + } + else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) + { + struct option_list *newp = (struct option_list*)alloca(sizeof(*newp)); + newp->p = p; + newp->next = ambig_list; + ambig_list = newp; + } + } + if (ambig_list != NULL && !exact) + { + if (print_errors) + { + struct option_list first; + first.p = pfound; + first.next = ambig_list; + ambig_list = &first; + fwprintf(stderr, L"%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]); + do + { + fwprintf (stderr, L" '--%s'", ambig_list->p->name); + ambig_list = ambig_list->next; + } + while (ambig_list != NULL); + fputwc (L'\n', stderr); + } + d->__nextchar += wcslen(d->__nextchar); + d->optind++; + d->optopt = 0; + return L'?'; + } + if (pfound != NULL) + { + option_index = indfound; + d->optind++; + if (*nameend) + { + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + { + if (argv[d->optind - 1][1] == L'-') + { + fwprintf(stderr, L"%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name); + } + else + { + fwprintf(stderr, L"%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name); + } + } + d->__nextchar += wcslen(d->__nextchar); + d->optopt = pfound->val; + return L'?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + { + fwprintf(stderr,L"%s: option '--%s' requires an argument\n",argv[0], pfound->name); + } + d->__nextchar += wcslen(d->__nextchar); + d->optopt = pfound->val; + return optstring[0] == L':' ? L':' : L'?'; + } + } + d->__nextchar += wcslen(d->__nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + if (!long_only || argv[d->optind][1] == L'-' || wcschr(optstring, *d->__nextchar) == NULL) + { + if (print_errors) + { + if (argv[d->optind][1] == L'-') + { + fwprintf(stderr, L"%s: unrecognized option '--%s'\n",argv[0], d->__nextchar); + } + else + { + fwprintf(stderr, L"%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar); + } + } + d->__nextchar = (wchar_t *)L""; + d->optind++; + d->optopt = 0; + return L'?'; + } + } + { + wchar_t c = *d->__nextchar++; + wchar_t *temp = (wchar_t*)wcschr(optstring, c); + if (*d->__nextchar == L'\0') + ++d->optind; + if (temp == NULL || c == L':' || c == L';') + { + if (print_errors) + { + fwprintf(stderr, L"%s: invalid option -- '%c'\n", argv[0], c); + } + d->optopt = c; + return L'?'; + } + if (temp[0] == L'W' && temp[1] == L';') + { + wchar_t *nameend; + const struct option_w *p; + const struct option_w *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + if (longopts == NULL) + goto no_longs; + if (*d->__nextchar != L'\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + { + fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c); + } + d->optopt = c; + if (optstring[0] == L':') + c = L':'; + else + c = L'?'; + return c; + } + else + d->optarg = argv[d->optind++]; + for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != L'='; nameend++); + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!wcsncmp(p->name, d->__nextchar, nameend - d->__nextchar)) + { + if ((unsigned int) (nameend - d->__nextchar) == wcslen(p->name)) + { + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + pfound = p; + indfound = option_index; + } + else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) + ambig = 1; + } + if (ambig && !exact) + { + if (print_errors) + { + fwprintf(stderr, L"%s: option '-W %s' is ambiguous\n",argv[0], d->optarg); + } + d->__nextchar += wcslen(d->__nextchar); + d->optind++; + return L'?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + { + fwprintf(stderr, L"%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name); + } + d->__nextchar += wcslen(d->__nextchar); + return L'?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + { + fwprintf(stderr, L"%s: option '-W %s' requires an argument\n",argv[0], pfound->name); + } + d->__nextchar += wcslen(d->__nextchar); + return optstring[0] == L':' ? L':' : L'?'; + } + } + else + d->optarg = NULL; + d->__nextchar += wcslen(d->__nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } +no_longs: + d->__nextchar = NULL; + return L'W'; + } + if (temp[1] == L':') + { + if (temp[2] == L':') + { + if (*d->__nextchar != L'\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else + d->optarg = NULL; + d->__nextchar = NULL; + } + else + { + if (*d->__nextchar != L'\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + { + fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c); + } + d->optopt = c; + if (optstring[0] == L':') + c = L':'; + else + c = L'?'; + } + else + d->optarg = argv[d->optind++]; + d->__nextchar = NULL; + } + } + return c; + } +} +int _getopt_internal_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, int posixly_correct) +{ + int result; + getopt_data_w.optind = optind; + getopt_data_w.opterr = opterr; + result = _getopt_internal_r_w (argc, argv, optstring, longopts,longind, long_only, &getopt_data_w,posixly_correct); + optind = getopt_data_w.optind; + optarg_w = getopt_data_w.optarg; + optopt = getopt_data_w.optopt; + return result; +} +int getopt_w (int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW +{ + return _getopt_internal_w (argc, argv, optstring, (const struct option_w *) 0, (int *) 0, 0, 0); +} +int getopt_long_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW +{ + return _getopt_internal_w (argc, argv, options, long_options, opt_index, 0, 0); +} +int getopt_long_only_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW +{ + return _getopt_internal_w (argc, argv, options, long_options, opt_index, 1, 0); +} +int _getopt_long_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d) +{ + return _getopt_internal_r_w (argc, argv, options, long_options, opt_index,0, d, 0); +} +int _getopt_long_only_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d) +{ + return _getopt_internal_r_w (argc, argv, options, long_options, opt_index, 1, d, 0); +} \ No newline at end of file diff --git a/src/lib/third_party/src/windows/gettimeofday.c b/src/lib/third_party/src/windows/gettimeofday.c new file mode 100644 index 000000000..c921b3325 --- /dev/null +++ b/src/lib/third_party/src/windows/gettimeofday.c @@ -0,0 +1,55 @@ +/* +* Author: Ugo Varetto - ugovaretto@gmail.com +* This code is distributed under the terms of the Apache Software License version 2.0 +* https://opensource.org/licenses/Apache-2.0 +*/ + +#include +#include + +#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) +#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 +#else +#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL +#endif + +struct timezone +{ + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + FILETIME ft; + unsigned __int64 tmpres = 0; + static int tzflag = 0; + + if (NULL != tv) + { + GetSystemTimeAsFileTime(&ft); + + tmpres |= ft.dwHighDateTime; + tmpres <<= 32; + tmpres |= ft.dwLowDateTime; + + tmpres /= 10; /*convert into microseconds*/ + /*converting file time to unix epoch*/ + tmpres -= DELTA_EPOCH_IN_MICROSECS; + tv->tv_sec = (long)(tmpres / 1000000UL); + tv->tv_usec = (long)(tmpres % 1000000UL); + } + + if (NULL != tz) + { + if (!tzflag) + { + _tzset(); + tzflag++; + } + tz->tz_minuteswest = _timezone / 60; + tz->tz_dsttime = _daylight; + } + + return 0; +} diff --git a/windows/src/dirent.h b/windows/src/dirent.h deleted file mode 100644 index fd1e81354..000000000 --- a/windows/src/dirent.h +++ /dev/null @@ -1,1239 +0,0 @@ -/* - * Dirent interface for Microsoft Visual Studio - * - * Copyright (C) 1998-2019 Toni Ronkko - * This file is part of dirent. Dirent may be freely distributed - * under the MIT license. For all details and documentation, see - * https://github.com/tronkko/dirent - */ -#ifndef DIRENT_H -#define DIRENT_H - -/* Hide warnings about unreferenced local functions */ -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wunused-function" -#elif defined(_MSC_VER) -# pragma warning(disable:4505) -#elif defined(__GNUC__) -# pragma GCC diagnostic ignored "-Wunused-function" -#endif - -/* - * Include windows.h without Windows Sockets 1.1 to prevent conflicts with - * Windows Sockets 2.0. - */ -#ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Indicates that d_type field is available in dirent structure */ -#define _DIRENT_HAVE_D_TYPE - -/* Indicates that d_namlen field is available in dirent structure */ -#define _DIRENT_HAVE_D_NAMLEN - -/* Entries missing from MSVC 6.0 */ -#if !defined(FILE_ATTRIBUTE_DEVICE) -# define FILE_ATTRIBUTE_DEVICE 0x40 -#endif - -/* File type and permission flags for stat(), general mask */ -#if !defined(S_IFMT) -# define S_IFMT _S_IFMT -#endif - -/* Directory bit */ -#if !defined(S_IFDIR) -# define S_IFDIR _S_IFDIR -#endif - -/* Character device bit */ -#if !defined(S_IFCHR) -# define S_IFCHR _S_IFCHR -#endif - -/* Pipe bit */ -#if !defined(S_IFFIFO) -# define S_IFFIFO _S_IFFIFO -#endif - -/* Regular file bit */ -#if !defined(S_IFREG) -# define S_IFREG _S_IFREG -#endif - -/* Read permission */ -#if !defined(S_IREAD) -# define S_IREAD _S_IREAD -#endif - -/* Write permission */ -#if !defined(S_IWRITE) -# define S_IWRITE _S_IWRITE -#endif - -/* Execute permission */ -#if !defined(S_IEXEC) -# define S_IEXEC _S_IEXEC -#endif - -/* Pipe */ -#if !defined(S_IFIFO) -# define S_IFIFO _S_IFIFO -#endif - -/* Block device */ -#if !defined(S_IFBLK) -# define S_IFBLK 0 -#endif - -/* - * Symbolic link. Be ware that S_IFLNK value and S_ISLNK() macro are only - * usable with dirent - they do not work with stat() function call! - */ -#if !defined(S_IFLNK) -# define S_IFLNK (_S_IFDIR | _S_IFREG) -#endif - -/* Socket */ -#if !defined(S_IFSOCK) -# define S_IFSOCK 0 -#endif - -/* Read user permission */ -#if !defined(S_IRUSR) -# define S_IRUSR S_IREAD -#endif - -/* Write user permission */ -#if !defined(S_IWUSR) -# define S_IWUSR S_IWRITE -#endif - -/* Execute user permission */ -#if !defined(S_IXUSR) -# define S_IXUSR 0 -#endif - -/* User full permissions */ -#if !defined(S_IRWXU) -# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) -#endif - -/* Read group permission */ -#if !defined(S_IRGRP) -# define S_IRGRP 0 -#endif - -/* Write group permission */ -#if !defined(S_IWGRP) -# define S_IWGRP 0 -#endif - -/* Execute group permission */ -#if !defined(S_IXGRP) -# define S_IXGRP 0 -#endif - -/* Group full permissions */ -#if !defined(S_IRWXG) -# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) -#endif - -/* Read others permission */ -#if !defined(S_IROTH) -# define S_IROTH 0 -#endif - -/* Write others permission */ -#if !defined(S_IWOTH) -# define S_IWOTH 0 -#endif - -/* Execute others permission */ -#if !defined(S_IXOTH) -# define S_IXOTH 0 -#endif - -/* Other full permissions */ -#if !defined(S_IRWXO) -# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) -#endif - -/* Maximum length of file name */ -#if !defined(PATH_MAX) -# define PATH_MAX MAX_PATH -#endif -#if !defined(FILENAME_MAX) -# define FILENAME_MAX MAX_PATH -#endif -#if !defined(NAME_MAX) -# define NAME_MAX FILENAME_MAX -#endif - -/* File type flags for d_type */ -#define DT_UNKNOWN 0 -#define DT_REG S_IFREG -#define DT_DIR S_IFDIR -#define DT_FIFO S_IFIFO -#define DT_SOCK S_IFSOCK -#define DT_CHR S_IFCHR -#define DT_BLK S_IFBLK -#define DT_LNK S_IFLNK - -/* Macros for converting between st_mode and d_type */ -#define IFTODT(mode) ((mode) & S_IFMT) -#define DTTOIF(type) (type) - -/* - * File type macros. Note that block devices and sockets cannot be - * distinguished on Windows, and the macros S_ISBLK and S_ISSOCK are only - * defined for compatibility. These macros should always return false on - * Windows. - */ -#if !defined(S_ISFIFO) -# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) -#endif -#if !defined(S_ISDIR) -# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) -#endif -#if !defined(S_ISREG) -# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) -#endif -#if !defined(S_ISLNK) -# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) -#endif -#if !defined(S_ISSOCK) -# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) -#endif -#if !defined(S_ISCHR) -# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) -#endif -#if !defined(S_ISBLK) -# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) -#endif - -/* Return the exact length of the file name without zero terminator */ -#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) - -/* Return the maximum size of a file name */ -#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1) - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Wide-character version */ -struct _wdirent { - /* Always zero */ - long d_ino; - - /* Position of next file in a directory stream */ - long d_off; - - /* Structure size */ - unsigned short d_reclen; - - /* Length of name without \0 */ - size_t d_namlen; - - /* File type */ - int d_type; - - /* File name */ - wchar_t d_name[PATH_MAX+1]; -}; -typedef struct _wdirent _wdirent; - -struct _WDIR { - /* Current directory entry */ - struct _wdirent ent; - - /* Private file data */ - WIN32_FIND_DATAW data; - - /* True if data is valid */ - int cached; - - /* True if next entry is invalid */ - int invalid; - - /* Win32 search handle */ - HANDLE handle; - - /* Initial directory name */ - wchar_t *patt; -}; -typedef struct _WDIR _WDIR; - -/* Multi-byte character version */ -struct dirent { - /* Always zero */ - long d_ino; - - /* Position of next file in a directory stream */ - long d_off; - - /* Structure size */ - unsigned short d_reclen; - - /* Length of name without \0 */ - size_t d_namlen; - - /* File type */ - int d_type; - - /* File name */ - char d_name[PATH_MAX+1]; -}; -typedef struct dirent dirent; - -struct DIR { - struct dirent ent; - struct _WDIR *wdirp; -}; -typedef struct DIR DIR; - - -/* Dirent functions */ -static DIR *opendir(const char *dirname); -static _WDIR *_wopendir(const wchar_t *dirname); - -static struct dirent *readdir(DIR *dirp); -static struct _wdirent *_wreaddir(_WDIR *dirp); - -static int readdir_r( - DIR *dirp, struct dirent *entry, struct dirent **result); -static int _wreaddir_r( - _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); - -static int closedir(DIR *dirp); -static int _wclosedir(_WDIR *dirp); - -static void rewinddir(DIR *dirp); -static void _wrewinddir(_WDIR *dirp); - -static long telldir(DIR *dirp); -static long _wtelldir(_WDIR *dirp); - -static void seekdir(DIR *dirp, long loc); -static void _wseekdir(_WDIR *dirp, long loc); - -static int scandir(const char *dirname, struct dirent ***namelist, - int (*filter)(const struct dirent*), - int (*compare)(const struct dirent**, const struct dirent**)); - -static int alphasort(const struct dirent **a, const struct dirent **b); - -static int versionsort(const struct dirent **a, const struct dirent **b); - -static int strverscmp(const char *a, const char *b); - -/* For compatibility with Symbian */ -#define wdirent _wdirent -#define WDIR _WDIR -#define wopendir _wopendir -#define wreaddir _wreaddir -#define wclosedir _wclosedir -#define wrewinddir _wrewinddir -#define wtelldir _wtelldir -#define wseekdir _wseekdir - -/* Compatibility with older Microsoft compilers and non-Microsoft compilers */ -#if !defined(_MSC_VER) || _MSC_VER < 1400 -# define wcstombs_s dirent_wcstombs_s -# define mbstowcs_s dirent_mbstowcs_s -#endif - -/* Optimize dirent_set_errno() away on modern Microsoft compilers */ -#if defined(_MSC_VER) && _MSC_VER >= 1400 -# define dirent_set_errno _set_errno -#endif - - -/* Internal utility functions */ -static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); -static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); -static long dirent_hash(WIN32_FIND_DATAW *datap); - -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static int dirent_mbstowcs_s( - size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords, - const char *mbstr, size_t count); -#endif - -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static int dirent_wcstombs_s( - size_t *pReturnValue, char *mbstr, size_t sizeInBytes, - const wchar_t *wcstr, size_t count); -#endif - -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static void dirent_set_errno(int error); -#endif - - -/* - * Open directory stream DIRNAME for read and return a pointer to the - * internal working area that is used to retrieve individual directory - * entries. - */ -static _WDIR * -_wopendir(const wchar_t *dirname) -{ - wchar_t *p; - - /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno(ENOENT); - return NULL; - } - - /* Allocate new _WDIR structure */ - _WDIR *dirp = (_WDIR*) malloc(sizeof(struct _WDIR)); - if (!dirp) - return NULL; - - /* Reset _WDIR structure */ - dirp->handle = INVALID_HANDLE_VALUE; - dirp->patt = NULL; - dirp->cached = 0; - dirp->invalid = 0; - - /* - * Compute the length of full path plus zero terminator - * - * Note that on WinRT there's no way to convert relative paths - * into absolute paths, so just assume it is an absolute path. - */ -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - /* Desktop */ - DWORD n = GetFullPathNameW(dirname, 0, NULL, NULL); -#else - /* WinRT */ - size_t n = wcslen(dirname); -#endif - - /* Allocate room for absolute directory name and search pattern */ - dirp->patt = (wchar_t*) malloc(sizeof(wchar_t) * n + 16); - if (dirp->patt == NULL) - goto exit_closedir; - - /* - * Convert relative directory name to an absolute one. This - * allows rewinddir() to function correctly even when current - * working directory is changed between opendir() and rewinddir(). - * - * Note that on WinRT there's no way to convert relative paths - * into absolute paths, so just assume it is an absolute path. - */ -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - /* Desktop */ - n = GetFullPathNameW(dirname, n, dirp->patt, NULL); - if (n <= 0) - goto exit_closedir; -#else - /* WinRT */ - wcsncpy_s(dirp->patt, n+1, dirname, n); -#endif - - /* Append search pattern \* to the directory name */ - p = dirp->patt + n; - switch (p[-1]) { - case '\\': - case '/': - case ':': - /* Directory ends in path separator, e.g. c:\temp\ */ - /*NOP*/; - break; - - default: - /* Directory name doesn't end in path separator */ - *p++ = '\\'; - } - *p++ = '*'; - *p = '\0'; - - /* Open directory stream and retrieve the first entry */ - if (!dirent_first(dirp)) - goto exit_closedir; - - /* Success */ - return dirp; - - /* Failure */ -exit_closedir: - _wclosedir(dirp); - return NULL; -} - -/* - * Read next directory entry. - * - * Returns pointer to static directory entry which may be overwritten by - * subsequent calls to _wreaddir(). - */ -static struct _wdirent * -_wreaddir(_WDIR *dirp) -{ - /* - * Read directory entry to buffer. We can safely ignore the return - * value as entry will be set to NULL in case of error. - */ - struct _wdirent *entry; - (void) _wreaddir_r(dirp, &dirp->ent, &entry); - - /* Return pointer to statically allocated directory entry */ - return entry; -} - -/* - * Read next directory entry. - * - * Returns zero on success. If end of directory stream is reached, then sets - * result to NULL and returns zero. - */ -static int -_wreaddir_r( - _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result) -{ - /* Validate directory handle */ - if (!dirp || dirp->handle == INVALID_HANDLE_VALUE || !dirp->patt) { - dirent_set_errno(EBADF); - *result = NULL; - return -1; - } - - /* Read next directory entry */ - WIN32_FIND_DATAW *datap = dirent_next(dirp); - if (!datap) { - /* Return NULL to indicate end of directory */ - *result = NULL; - return /*OK*/0; - } - - /* - * Copy file name as wide-character string. If the file name is too - * long to fit in to the destination buffer, then truncate file name - * to PATH_MAX characters and zero-terminate the buffer. - */ - size_t i = 0; - while (i < PATH_MAX && datap->cFileName[i] != 0) { - entry->d_name[i] = datap->cFileName[i]; - i++; - } - entry->d_name[i] = 0; - - /* Length of file name excluding zero terminator */ - entry->d_namlen = i; - - /* Determine file type */ - DWORD attr = datap->dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) - entry->d_type = DT_CHR; - else if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) - entry->d_type = DT_LNK; - else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) - entry->d_type = DT_DIR; - else - entry->d_type = DT_REG; - - /* Read the next directory entry to cache */ - datap = dirent_next(dirp); - if (datap) { - /* Compute 31-bit hash of the next directory entry */ - entry->d_off = dirent_hash(datap); - - /* Push the next directory entry back to cache */ - dirp->cached = 1; - } else { - /* End of directory stream */ - entry->d_off = (long) ((~0UL) >> 1); - } - - /* Reset other fields */ - entry->d_ino = 0; - entry->d_reclen = sizeof(struct _wdirent); - - /* Set result address */ - *result = entry; - return /*OK*/0; -} - -/* - * Close directory stream opened by opendir() function. This invalidates the - * DIR structure as well as any directory entry read previously by - * _wreaddir(). - */ -static int -_wclosedir(_WDIR *dirp) -{ - if (!dirp) { - dirent_set_errno(EBADF); - return /*failure*/-1; - } - - /* - * Release search handle if we have one. Being able to handle - * partially initialized _WDIR structure allows us to use this - * function to handle errors occuring within _wopendir. - */ - if (dirp->handle != INVALID_HANDLE_VALUE) { - FindClose(dirp->handle); - } - - /* - * Release search pattern. Note that we don't need to care if - * dirp->patt is NULL or not: function free is guaranteed to act - * appropriately. - */ - free(dirp->patt); - - /* Release directory structure */ - free(dirp); - return /*success*/0; -} - -/* - * Rewind directory stream such that _wreaddir() returns the very first - * file name again. - */ -static void _wrewinddir(_WDIR* dirp) -{ - /* Check directory pointer */ - if (!dirp || dirp->handle == INVALID_HANDLE_VALUE || !dirp->patt) - return; - - /* Release existing search handle */ - FindClose(dirp->handle); - - /* Open new search handle */ - dirent_first(dirp); -} - -/* Get first directory entry */ -static WIN32_FIND_DATAW * -dirent_first(_WDIR *dirp) -{ - /* Open directory and retrieve the first entry */ - dirp->handle = FindFirstFileExW( - dirp->patt, FindExInfoStandard, &dirp->data, - FindExSearchNameMatch, NULL, 0); - if (dirp->handle == INVALID_HANDLE_VALUE) - goto error; - - /* A directory entry is now waiting in memory */ - dirp->cached = 1; - return &dirp->data; - -error: - /* Failed to open directory: no directory entry in memory */ - dirp->cached = 0; - dirp->invalid = 1; - - /* Set error code */ - DWORD errorcode = GetLastError(); - switch (errorcode) { - case ERROR_ACCESS_DENIED: - /* No read access to directory */ - dirent_set_errno(EACCES); - break; - - case ERROR_DIRECTORY: - /* Directory name is invalid */ - dirent_set_errno(ENOTDIR); - break; - - case ERROR_PATH_NOT_FOUND: - default: - /* Cannot find the file */ - dirent_set_errno(ENOENT); - } - return NULL; -} - -/* Get next directory entry */ -static WIN32_FIND_DATAW * -dirent_next(_WDIR *dirp) -{ - /* Return NULL if seek position was invalid */ - if (dirp->invalid) - return NULL; - - /* Is the next directory entry already in cache? */ - if (dirp->cached) { - /* Yes, a valid directory entry found in memory */ - dirp->cached = 0; - return &dirp->data; - } - - /* Read the next directory entry from stream */ - if (FindNextFileW(dirp->handle, &dirp->data) == FALSE) { - /* End of directory stream */ - return NULL; - } - - /* Success */ - return &dirp->data; -} - -/* - * Compute 31-bit hash of file name. - * - * See djb2 at http://www.cse.yorku.ca/~oz/hash.html - */ -static long -dirent_hash(WIN32_FIND_DATAW *datap) -{ - unsigned long hash = 5381; - unsigned long c; - const wchar_t *p = datap->cFileName; - const wchar_t *e = p + MAX_PATH; - while (p != e && (c = *p++) != 0) { - hash = (hash << 5) + hash + c; - } - - return (long) (hash & ((~0UL) >> 1)); -} - -/* Open directory stream using plain old C-string */ -static DIR *opendir(const char *dirname) -{ - /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno(ENOENT); - return NULL; - } - - /* Allocate memory for DIR structure */ - struct DIR *dirp = (DIR*) malloc(sizeof(struct DIR)); - if (!dirp) - return NULL; - - /* Convert directory name to wide-character string */ - wchar_t wname[PATH_MAX + 1]; - size_t n; - int error = mbstowcs_s(&n, wname, PATH_MAX + 1, dirname, PATH_MAX+1); - if (error) - goto exit_failure; - - /* Open directory stream using wide-character name */ - dirp->wdirp = _wopendir(wname); - if (!dirp->wdirp) - goto exit_failure; - - /* Success */ - return dirp; - - /* Failure */ -exit_failure: - free(dirp); - return NULL; -} - -/* Read next directory entry */ -static struct dirent * -readdir(DIR *dirp) -{ - /* - * Read directory entry to buffer. We can safely ignore the return - * value as entry will be set to NULL in case of error. - */ - struct dirent *entry; - (void) readdir_r(dirp, &dirp->ent, &entry); - - /* Return pointer to statically allocated directory entry */ - return entry; -} - -/* - * Read next directory entry into called-allocated buffer. - * - * Returns zero on success. If the end of directory stream is reached, then - * sets result to NULL and returns zero. - */ -static int -readdir_r( - DIR *dirp, struct dirent *entry, struct dirent **result) -{ - /* Read next directory entry */ - WIN32_FIND_DATAW *datap = dirent_next(dirp->wdirp); - if (!datap) { - /* No more directory entries */ - *result = NULL; - return /*OK*/0; - } - - /* Attempt to convert file name to multi-byte string */ - size_t n; - int error = wcstombs_s( - &n, entry->d_name, PATH_MAX + 1, - datap->cFileName, PATH_MAX + 1); - - /* - * If the file name cannot be represented by a multi-byte string, then - * attempt to use old 8+3 file name. This allows the program to - * access files although file names may seem unfamiliar to the user. - * - * Be ware that the code below cannot come up with a short file name - * unless the file system provides one. At least VirtualBox shared - * folders fail to do this. - */ - if (error && datap->cAlternateFileName[0] != '\0') { - error = wcstombs_s( - &n, entry->d_name, PATH_MAX + 1, - datap->cAlternateFileName, PATH_MAX + 1); - } - - if (!error) { - /* Length of file name excluding zero terminator */ - entry->d_namlen = n - 1; - - /* Determine file type */ - DWORD attr = datap->dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) - entry->d_type = DT_CHR; - else if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) - entry->d_type = DT_LNK; - else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) - entry->d_type = DT_DIR; - else - entry->d_type = DT_REG; - - /* Get offset of next file */ - datap = dirent_next(dirp->wdirp); - if (datap) { - /* Compute 31-bit hash of the next directory entry */ - entry->d_off = dirent_hash(datap); - - /* Push the next directory entry back to cache */ - dirp->wdirp->cached = 1; - } else { - /* End of directory stream */ - entry->d_off = (long) ((~0UL) >> 1); - } - - /* Reset fields */ - entry->d_ino = 0; - entry->d_reclen = sizeof(struct dirent); - } else { - /* - * Cannot convert file name to multi-byte string so construct - * an erroneous directory entry and return that. Note that - * we cannot return NULL as that would stop the processing - * of directory entries completely. - */ - entry->d_name[0] = '?'; - entry->d_name[1] = '\0'; - entry->d_namlen = 1; - entry->d_type = DT_UNKNOWN; - entry->d_ino = 0; - entry->d_off = -1; - entry->d_reclen = 0; - } - - /* Return pointer to directory entry */ - *result = entry; - return /*OK*/0; -} - -/* Close directory stream */ -static int -closedir(DIR *dirp) -{ - int ok; - - if (!dirp) - goto exit_failure; - - /* Close wide-character directory stream */ - ok = _wclosedir(dirp->wdirp); - dirp->wdirp = NULL; - - /* Release multi-byte character version */ - free(dirp); - return ok; - -exit_failure: - /* Invalid directory stream */ - dirent_set_errno(EBADF); - return /*failure*/-1; -} - -/* Rewind directory stream to beginning */ -static void -rewinddir(DIR *dirp) -{ - if (!dirp) - return; - - /* Rewind wide-character string directory stream */ - _wrewinddir(dirp->wdirp); -} - -/* Get position of directory stream */ -static long -_wtelldir(_WDIR *dirp) -{ - if (!dirp || dirp->handle == INVALID_HANDLE_VALUE) { - dirent_set_errno(EBADF); - return /*failure*/-1; - } - - /* Read next file entry */ - WIN32_FIND_DATAW *datap = dirent_next(dirp); - if (!datap) { - /* End of directory stream */ - return (long) ((~0UL) >> 1); - } - - /* Store file entry to cache for readdir() */ - dirp->cached = 1; - - /* Return the 31-bit hash code to be used as stream position */ - return dirent_hash(datap); -} - -/* Get position of directory stream */ -static long -telldir(DIR *dirp) -{ - if (!dirp) { - dirent_set_errno(EBADF); - return -1; - } - - return _wtelldir(dirp->wdirp); -} - -/* Seek directory stream to offset */ -static void -_wseekdir(_WDIR *dirp, long loc) -{ - if (!dirp) - return; - - /* Directory must be open */ - if (dirp->handle == INVALID_HANDLE_VALUE) - goto exit_failure; - - /* Ensure that seek position is valid */ - if (loc < 0) - goto exit_failure; - - /* Restart directory stream from the beginning */ - FindClose(dirp->handle); - if (!dirent_first(dirp)) - goto exit_failure; - - /* Reset invalid flag so that we can read from the stream again */ - dirp->invalid = 0; - - /* - * Read directory entries from the beginning until the hash matches a - * file name. Be ware that hash code is only 31 bits longs and - * duplicates are possible: the hash code cannot return the position - * with 100.00% accuracy! Moreover, the method is slow for large - * directories. - */ - long hash; - do { - /* Read next directory entry */ - WIN32_FIND_DATAW *datap = dirent_next(dirp); - if (!datap) { - /* - * End of directory stream was reached before finding - * the requested location. Perhaps the file in - * question was deleted or moved out of the directory. - */ - goto exit_failure; - } - - /* Does the file name match the hash? */ - hash = dirent_hash(datap); - } while (hash != loc); - - /* - * File name matches the hash! Push the directory entry back to cache - * from where next readdir() will return it. - */ - dirp->cached = 1; - dirp->invalid = 0; - return; - -exit_failure: - /* Ensure that readdir will return NULL */ - dirp->invalid = 1; -} - -/* Seek directory stream to offset */ -static void -seekdir(DIR *dirp, long loc) -{ - if (!dirp) - return; - - _wseekdir(dirp->wdirp, loc); -} - -/* Scan directory for entries */ -static int -scandir( - const char *dirname, struct dirent ***namelist, - int (*filter)(const struct dirent*), - int (*compare)(const struct dirent**, const struct dirent**)) -{ - int result; - - /* Open directory stream */ - DIR *dir = opendir(dirname); - if (!dir) { - /* Cannot open directory */ - return /*Error*/ -1; - } - - /* Read directory entries to memory */ - struct dirent *tmp = NULL; - struct dirent **files = NULL; - size_t size = 0; - size_t allocated = 0; - while (1) { - /* Allocate room for a temporary directory entry */ - if (!tmp) { - tmp = (struct dirent*) malloc(sizeof(struct dirent)); - if (!tmp) - goto exit_failure; - } - - /* Read directory entry to temporary area */ - struct dirent *entry; - if (readdir_r(dir, tmp, &entry) != /*OK*/0) - goto exit_failure; - - /* Stop if we already read the last directory entry */ - if (entry == NULL) - goto exit_success; - - /* Determine whether to include the entry in results */ - if (filter && !filter(tmp)) - continue; - - /* Enlarge pointer table to make room for another pointer */ - if (size >= allocated) { - /* Compute number of entries in the new table */ - size_t num_entries = size * 2 + 16; - - /* Allocate new pointer table or enlarge existing */ - void *p = realloc(files, sizeof(void*) * num_entries); - if (!p) - goto exit_failure; - - /* Got the memory */ - files = (dirent**) p; - allocated = num_entries; - } - - /* Store the temporary entry to ptr table */ - files[size++] = tmp; - tmp = NULL; - } - -exit_failure: - /* Release allocated entries */ - for (size_t i = 0; i < size; i++) { - free(files[i]); - } - - /* Release the pointer table */ - free(files); - files = NULL; - - /* Exit with error code */ - result = /*error*/ -1; - goto exit_status; - -exit_success: - /* Sort directory entries */ - if (size > 1 && compare) { - qsort(files, size, sizeof(void*), - (int (*) (const void*, const void*)) compare); - } - - /* Pass pointer table to caller */ - if (namelist) - *namelist = files; - - /* Return the number of directory entries read */ - result = (int) size; - -exit_status: - /* Release temporary directory entry, if we had one */ - free(tmp); - - /* Close directory stream */ - closedir(dir); - return result; -} - -/* Alphabetical sorting */ -static int -alphasort(const struct dirent **a, const struct dirent **b) -{ - return strcoll((*a)->d_name, (*b)->d_name); -} - -/* Sort versions */ -static int -versionsort(const struct dirent **a, const struct dirent **b) -{ - return strverscmp((*a)->d_name, (*b)->d_name); -} - -/* Compare strings */ -static int -strverscmp(const char *a, const char *b) -{ - size_t i = 0; - size_t j; - - /* Find first difference */ - while (a[i] == b[i]) { - if (a[i] == '\0') { - /* No difference */ - return 0; - } - ++i; - } - - /* Count backwards and find the leftmost digit */ - j = i; - while (j > 0 && isdigit(a[j-1])) { - --j; - } - - /* Determine mode of comparison */ - if (a[j] == '0' || b[j] == '0') { - /* Find the next non-zero digit */ - while (a[j] == '0' && a[j] == b[j]) { - j++; - } - - /* String with more digits is smaller, e.g 002 < 01 */ - if (isdigit(a[j])) { - if (!isdigit(b[j])) { - return -1; - } - } else if (isdigit(b[j])) { - return 1; - } - } else if (isdigit(a[j]) && isdigit(b[j])) { - /* Numeric comparison */ - size_t k1 = j; - size_t k2 = j; - - /* Compute number of digits in each string */ - while (isdigit(a[k1])) { - k1++; - } - while (isdigit(b[k2])) { - k2++; - } - - /* Number with more digits is bigger, e.g 999 < 1000 */ - if (k1 < k2) - return -1; - else if (k1 > k2) - return 1; - } - - /* Alphabetical comparison */ - return (int) ((unsigned char) a[i]) - ((unsigned char) b[i]); -} - -/* Convert multi-byte string to wide character string */ -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static int -dirent_mbstowcs_s( - size_t *pReturnValue, wchar_t *wcstr, - size_t sizeInWords, const char *mbstr, size_t count) -{ - /* Older Visual Studio or non-Microsoft compiler */ - size_t n = mbstowcs(wcstr, mbstr, sizeInWords); - if (wcstr && n >= count) - return /*error*/ 1; - - /* Zero-terminate output buffer */ - if (wcstr && sizeInWords) { - if (n >= sizeInWords) - n = sizeInWords - 1; - wcstr[n] = 0; - } - - /* Length of multi-byte string with zero terminator */ - if (pReturnValue) { - *pReturnValue = n + 1; - } - - /* Success */ - return 0; -} -#endif - -/* Convert wide-character string to multi-byte string */ -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static int -dirent_wcstombs_s( - size_t *pReturnValue, char *mbstr, - size_t sizeInBytes, const wchar_t *wcstr, size_t count) -{ - /* Older Visual Studio or non-Microsoft compiler */ - size_t n = wcstombs(mbstr, wcstr, sizeInBytes); - if (mbstr && n >= count) - return /*error*/1; - - /* Zero-terminate output buffer */ - if (mbstr && sizeInBytes) { - if (n >= sizeInBytes) { - n = sizeInBytes - 1; - } - mbstr[n] = '\0'; - } - - /* Length of resulting multi-bytes string WITH zero-terminator */ - if (pReturnValue) { - *pReturnValue = n + 1; - } - - /* Success */ - return 0; -} -#endif - -/* Set errno variable */ -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static void -dirent_set_errno(int error) -{ - /* Non-Microsoft compiler or older Microsoft compiler */ - errno = error; -} -#endif - -#ifdef __cplusplus -} -#endif -#endif /*DIRENT_H*/ diff --git a/windows/src/getopt.c b/windows/src/getopt.c deleted file mode 100644 index ddd7104e0..000000000 --- a/windows/src/getopt.c +++ /dev/null @@ -1,972 +0,0 @@ -/* Getopt for Microsoft C -This code is a modification of the Free Software Foundation, Inc. -Getopt library for parsing command line argument the purpose was -to provide a Microsoft Visual C friendly derivative. This code -provides functionality for both Unicode and Multibyte builds. - -Date: 02/03/2011 - Ludvik Jerabek - Initial Release -Version: 1.0 -Comment: Supports getopt, getopt_long, and getopt_long_only -and POSIXLY_CORRECT environment flag -License: LGPL - -Revisions: - -02/03/2011 - Ludvik Jerabek - Initial Release -02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4 -07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs -08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception -08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB -02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file -08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi -10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features -06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable - -**DISCLAIMER** -THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, -EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE -EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT -APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY -DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY -USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST -PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON -YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE -EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -*/ -#include -#include -#include -#include "getopt.h" - -#ifdef __cplusplus - #define _GETOPT_THROW throw() -#else - #define _GETOPT_THROW -#endif - -int optind = 1; -int opterr = 1; -int optopt = '?'; -enum ENUM_ORDERING { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER }; - -// -// -// Ansi structures and functions follow -// -// - -static struct _getopt_data_a -{ - int optind; - int opterr; - int optopt; - char *optarg; - int __initialized; - char *__nextchar; - enum ENUM_ORDERING __ordering; - int __posixly_correct; - int __first_nonopt; - int __last_nonopt; -} getopt_data_a; -char *optarg_a; - -static void exchange_a(char **argv, struct _getopt_data_a *d) -{ - int bottom = d->__first_nonopt; - int middle = d->__last_nonopt; - int top = d->optind; - char *tem; - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - int len = middle - bottom; - register int i; - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - } - top -= len; - } - else - { - int len = top - middle; - register int i; - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - } - bottom += len; - } - } - d->__first_nonopt += (d->optind - d->__last_nonopt); - d->__last_nonopt = d->optind; -} -static const char *_getopt_initialize_a (const char *optstring, struct _getopt_data_a *d, int posixly_correct) -{ - d->__first_nonopt = d->__last_nonopt = d->optind; - d->__nextchar = NULL; - d->__posixly_correct = posixly_correct | !!getenv("POSIXLY_CORRECT"); - if (optstring[0] == '-') - { - d->__ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - d->__ordering = REQUIRE_ORDER; - ++optstring; - } - else if (d->__posixly_correct) - d->__ordering = REQUIRE_ORDER; - else - d->__ordering = PERMUTE; - return optstring; -} -int _getopt_internal_r_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, struct _getopt_data_a *d, int posixly_correct) -{ - int print_errors = d->opterr; - if (argc < 1) - return -1; - d->optarg = NULL; - if (d->optind == 0 || !d->__initialized) - { - if (d->optind == 0) - d->optind = 1; - optstring = _getopt_initialize_a (optstring, d, posixly_correct); - d->__initialized = 1; - } - else if (optstring[0] == '-' || optstring[0] == '+') - optstring++; - if (optstring[0] == ':') - print_errors = 0; - if (d->__nextchar == NULL || *d->__nextchar == '\0') - { - if (d->__last_nonopt > d->optind) - d->__last_nonopt = d->optind; - if (d->__first_nonopt > d->optind) - d->__first_nonopt = d->optind; - if (d->__ordering == PERMUTE) - { - if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) - exchange_a ((char **) argv, d); - else if (d->__last_nonopt != d->optind) - d->__first_nonopt = d->optind; - while (d->optind < argc && (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')) - d->optind++; - d->__last_nonopt = d->optind; - } - if (d->optind != argc && !strcmp(argv[d->optind], "--")) - { - d->optind++; - if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) - exchange_a((char **) argv, d); - else if (d->__first_nonopt == d->__last_nonopt) - d->__first_nonopt = d->optind; - d->__last_nonopt = argc; - d->optind = argc; - } - if (d->optind == argc) - { - if (d->__first_nonopt != d->__last_nonopt) - d->optind = d->__first_nonopt; - return -1; - } - if ((argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')) - { - if (d->__ordering == REQUIRE_ORDER) - return -1; - d->optarg = argv[d->optind++]; - return 1; - } - d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == '-')); - } - if (longopts != NULL && (argv[d->optind][1] == '-' || (long_only && (argv[d->optind][2] || !strchr(optstring, argv[d->optind][1]))))) - { - char *nameend; - unsigned int namelen; - const struct option_a *p; - const struct option_a *pfound = NULL; - struct option_list - { - const struct option_a *p; - struct option_list *next; - } *ambig_list = NULL; - int exact = 0; - int indfound = -1; - int option_index; - for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++); - namelen = (unsigned int)(nameend - d->__nextchar); - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp(p->name, d->__nextchar, namelen)) - { - if (namelen == (unsigned int)strlen(p->name)) - { - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - pfound = p; - indfound = option_index; - } - else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) - { - struct option_list *newp = (struct option_list*)alloca(sizeof(*newp)); - newp->p = p; - newp->next = ambig_list; - ambig_list = newp; - } - } - if (ambig_list != NULL && !exact) - { - if (print_errors) - { - struct option_list first; - first.p = pfound; - first.next = ambig_list; - ambig_list = &first; - fprintf (stderr, "%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]); - do - { - fprintf (stderr, " '--%s'", ambig_list->p->name); - ambig_list = ambig_list->next; - } - while (ambig_list != NULL); - fputc ('\n', stderr); - } - d->__nextchar += strlen(d->__nextchar); - d->optind++; - d->optopt = 0; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - d->optind++; - if (*nameend) - { - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { - if (argv[d->optind - 1][1] == '-') - { - fprintf(stderr, "%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name); - } - else - { - fprintf(stderr, "%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name); - } - } - d->__nextchar += strlen(d->__nextchar); - d->optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { - fprintf(stderr,"%s: option '--%s' requires an argument\n",argv[0], pfound->name); - } - d->__nextchar += strlen(d->__nextchar); - d->optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - d->__nextchar += strlen(d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - if (!long_only || argv[d->optind][1] == '-' || strchr(optstring, *d->__nextchar) == NULL) - { - if (print_errors) - { - if (argv[d->optind][1] == '-') - { - fprintf(stderr, "%s: unrecognized option '--%s'\n",argv[0], d->__nextchar); - } - else - { - fprintf(stderr, "%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar); - } - } - d->__nextchar = (char *)""; - d->optind++; - d->optopt = 0; - return '?'; - } - } - { - char c = *d->__nextchar++; - char *temp = (char*)strchr(optstring, c); - if (*d->__nextchar == '\0') - ++d->optind; - if (temp == NULL || c == ':' || c == ';') - { - if (print_errors) - { - fprintf(stderr, "%s: invalid option -- '%c'\n", argv[0], c); - } - d->optopt = c; - return '?'; - } - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option_a *p; - const struct option_a *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - if (longopts == NULL) - goto no_longs; - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { - fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c); - } - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - d->optarg = argv[d->optind++]; - for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; nameend++); - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp(p->name, d->__nextchar, nameend - d->__nextchar)) - { - if ((unsigned int) (nameend - d->__nextchar) == strlen(p->name)) - { - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - pfound = p; - indfound = option_index; - } - else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) - ambig = 1; - } - if (ambig && !exact) - { - if (print_errors) - { - fprintf(stderr, "%s: option '-W %s' is ambiguous\n",argv[0], d->optarg); - } - d->__nextchar += strlen(d->__nextchar); - d->optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { - fprintf(stderr, "%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name); - } - d->__nextchar += strlen(d->__nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { - fprintf(stderr, "%s: option '-W %s' requires an argument\n",argv[0], pfound->name); - } - d->__nextchar += strlen(d->__nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - else - d->optarg = NULL; - d->__nextchar += strlen(d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } -no_longs: - d->__nextchar = NULL; - return 'W'; - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else - d->optarg = NULL; - d->__nextchar = NULL; - } - else - { - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { - fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c); - } - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - d->optarg = argv[d->optind++]; - d->__nextchar = NULL; - } - } - return c; - } -} -int _getopt_internal_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, int posixly_correct) -{ - int result; - getopt_data_a.optind = optind; - getopt_data_a.opterr = opterr; - result = _getopt_internal_r_a (argc, argv, optstring, longopts,longind, long_only, &getopt_data_a,posixly_correct); - optind = getopt_data_a.optind; - optarg_a = getopt_data_a.optarg; - optopt = getopt_data_a.optopt; - return result; -} -int getopt_a (int argc, char *const *argv, const char *optstring) _GETOPT_THROW -{ - return _getopt_internal_a (argc, argv, optstring, (const struct option_a *) 0, (int *) 0, 0, 0); -} -int getopt_long_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW -{ - return _getopt_internal_a (argc, argv, options, long_options, opt_index, 0, 0); -} -int getopt_long_only_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW -{ - return _getopt_internal_a (argc, argv, options, long_options, opt_index, 1, 0); -} -int _getopt_long_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d) -{ - return _getopt_internal_r_a (argc, argv, options, long_options, opt_index,0, d, 0); -} -int _getopt_long_only_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d) -{ - return _getopt_internal_r_a (argc, argv, options, long_options, opt_index, 1, d, 0); -} - -// -// -// Unicode Structures and Functions -// -// - -static struct _getopt_data_w -{ - int optind; - int opterr; - int optopt; - wchar_t *optarg; - int __initialized; - wchar_t *__nextchar; - enum ENUM_ORDERING __ordering; - int __posixly_correct; - int __first_nonopt; - int __last_nonopt; -} getopt_data_w; -wchar_t *optarg_w; - -static void exchange_w(wchar_t **argv, struct _getopt_data_w *d) -{ - int bottom = d->__first_nonopt; - int middle = d->__last_nonopt; - int top = d->optind; - wchar_t *tem; - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - int len = middle - bottom; - register int i; - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - } - top -= len; - } - else - { - int len = top - middle; - register int i; - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - } - bottom += len; - } - } - d->__first_nonopt += (d->optind - d->__last_nonopt); - d->__last_nonopt = d->optind; -} -static const wchar_t *_getopt_initialize_w (const wchar_t *optstring, struct _getopt_data_w *d, int posixly_correct) -{ - d->__first_nonopt = d->__last_nonopt = d->optind; - d->__nextchar = NULL; - d->__posixly_correct = posixly_correct | !!_wgetenv(L"POSIXLY_CORRECT"); - if (optstring[0] == L'-') - { - d->__ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == L'+') - { - d->__ordering = REQUIRE_ORDER; - ++optstring; - } - else if (d->__posixly_correct) - d->__ordering = REQUIRE_ORDER; - else - d->__ordering = PERMUTE; - return optstring; -} -int _getopt_internal_r_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, struct _getopt_data_w *d, int posixly_correct) -{ - int print_errors = d->opterr; - if (argc < 1) - return -1; - d->optarg = NULL; - if (d->optind == 0 || !d->__initialized) - { - if (d->optind == 0) - d->optind = 1; - optstring = _getopt_initialize_w (optstring, d, posixly_correct); - d->__initialized = 1; - } - else if (optstring[0] == L'-' || optstring[0] == L'+') - optstring++; - if (optstring[0] == L':') - print_errors = 0; - if (d->__nextchar == NULL || *d->__nextchar == L'\0') - { - if (d->__last_nonopt > d->optind) - d->__last_nonopt = d->optind; - if (d->__first_nonopt > d->optind) - d->__first_nonopt = d->optind; - if (d->__ordering == PERMUTE) - { - if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) - exchange_w((wchar_t **) argv, d); - else if (d->__last_nonopt != d->optind) - d->__first_nonopt = d->optind; - while (d->optind < argc && (argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0')) - d->optind++; - d->__last_nonopt = d->optind; - } - if (d->optind != argc && !wcscmp(argv[d->optind], L"--")) - { - d->optind++; - if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) - exchange_w((wchar_t **) argv, d); - else if (d->__first_nonopt == d->__last_nonopt) - d->__first_nonopt = d->optind; - d->__last_nonopt = argc; - d->optind = argc; - } - if (d->optind == argc) - { - if (d->__first_nonopt != d->__last_nonopt) - d->optind = d->__first_nonopt; - return -1; - } - if ((argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0')) - { - if (d->__ordering == REQUIRE_ORDER) - return -1; - d->optarg = argv[d->optind++]; - return 1; - } - d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == L'-')); - } - if (longopts != NULL && (argv[d->optind][1] == L'-' || (long_only && (argv[d->optind][2] || !wcschr(optstring, argv[d->optind][1]))))) - { - wchar_t *nameend; - unsigned int namelen; - const struct option_w *p; - const struct option_w *pfound = NULL; - struct option_list - { - const struct option_w *p; - struct option_list *next; - } *ambig_list = NULL; - int exact = 0; - int indfound = -1; - int option_index; - for (nameend = d->__nextchar; *nameend && *nameend != L'='; nameend++); - namelen = (unsigned int)(nameend - d->__nextchar); - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!wcsncmp(p->name, d->__nextchar, namelen)) - { - if (namelen == (unsigned int)wcslen(p->name)) - { - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - pfound = p; - indfound = option_index; - } - else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) - { - struct option_list *newp = (struct option_list*)alloca(sizeof(*newp)); - newp->p = p; - newp->next = ambig_list; - ambig_list = newp; - } - } - if (ambig_list != NULL && !exact) - { - if (print_errors) - { - struct option_list first; - first.p = pfound; - first.next = ambig_list; - ambig_list = &first; - fwprintf(stderr, L"%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]); - do - { - fwprintf (stderr, L" '--%s'", ambig_list->p->name); - ambig_list = ambig_list->next; - } - while (ambig_list != NULL); - fputwc (L'\n', stderr); - } - d->__nextchar += wcslen(d->__nextchar); - d->optind++; - d->optopt = 0; - return L'?'; - } - if (pfound != NULL) - { - option_index = indfound; - d->optind++; - if (*nameend) - { - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { - if (argv[d->optind - 1][1] == L'-') - { - fwprintf(stderr, L"%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name); - } - else - { - fwprintf(stderr, L"%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name); - } - } - d->__nextchar += wcslen(d->__nextchar); - d->optopt = pfound->val; - return L'?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { - fwprintf(stderr,L"%s: option '--%s' requires an argument\n",argv[0], pfound->name); - } - d->__nextchar += wcslen(d->__nextchar); - d->optopt = pfound->val; - return optstring[0] == L':' ? L':' : L'?'; - } - } - d->__nextchar += wcslen(d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - if (!long_only || argv[d->optind][1] == L'-' || wcschr(optstring, *d->__nextchar) == NULL) - { - if (print_errors) - { - if (argv[d->optind][1] == L'-') - { - fwprintf(stderr, L"%s: unrecognized option '--%s'\n",argv[0], d->__nextchar); - } - else - { - fwprintf(stderr, L"%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar); - } - } - d->__nextchar = (wchar_t *)L""; - d->optind++; - d->optopt = 0; - return L'?'; - } - } - { - wchar_t c = *d->__nextchar++; - wchar_t *temp = (wchar_t*)wcschr(optstring, c); - if (*d->__nextchar == L'\0') - ++d->optind; - if (temp == NULL || c == L':' || c == L';') - { - if (print_errors) - { - fwprintf(stderr, L"%s: invalid option -- '%c'\n", argv[0], c); - } - d->optopt = c; - return L'?'; - } - if (temp[0] == L'W' && temp[1] == L';') - { - wchar_t *nameend; - const struct option_w *p; - const struct option_w *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - if (longopts == NULL) - goto no_longs; - if (*d->__nextchar != L'\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { - fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c); - } - d->optopt = c; - if (optstring[0] == L':') - c = L':'; - else - c = L'?'; - return c; - } - else - d->optarg = argv[d->optind++]; - for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != L'='; nameend++); - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!wcsncmp(p->name, d->__nextchar, nameend - d->__nextchar)) - { - if ((unsigned int) (nameend - d->__nextchar) == wcslen(p->name)) - { - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - pfound = p; - indfound = option_index; - } - else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) - ambig = 1; - } - if (ambig && !exact) - { - if (print_errors) - { - fwprintf(stderr, L"%s: option '-W %s' is ambiguous\n",argv[0], d->optarg); - } - d->__nextchar += wcslen(d->__nextchar); - d->optind++; - return L'?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { - fwprintf(stderr, L"%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name); - } - d->__nextchar += wcslen(d->__nextchar); - return L'?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { - fwprintf(stderr, L"%s: option '-W %s' requires an argument\n",argv[0], pfound->name); - } - d->__nextchar += wcslen(d->__nextchar); - return optstring[0] == L':' ? L':' : L'?'; - } - } - else - d->optarg = NULL; - d->__nextchar += wcslen(d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } -no_longs: - d->__nextchar = NULL; - return L'W'; - } - if (temp[1] == L':') - { - if (temp[2] == L':') - { - if (*d->__nextchar != L'\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else - d->optarg = NULL; - d->__nextchar = NULL; - } - else - { - if (*d->__nextchar != L'\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { - fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c); - } - d->optopt = c; - if (optstring[0] == L':') - c = L':'; - else - c = L'?'; - } - else - d->optarg = argv[d->optind++]; - d->__nextchar = NULL; - } - } - return c; - } -} -int _getopt_internal_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, int posixly_correct) -{ - int result; - getopt_data_w.optind = optind; - getopt_data_w.opterr = opterr; - result = _getopt_internal_r_w (argc, argv, optstring, longopts,longind, long_only, &getopt_data_w,posixly_correct); - optind = getopt_data_w.optind; - optarg_w = getopt_data_w.optarg; - optopt = getopt_data_w.optopt; - return result; -} -int getopt_w (int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW -{ - return _getopt_internal_w (argc, argv, optstring, (const struct option_w *) 0, (int *) 0, 0, 0); -} -int getopt_long_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW -{ - return _getopt_internal_w (argc, argv, options, long_options, opt_index, 0, 0); -} -int getopt_long_only_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW -{ - return _getopt_internal_w (argc, argv, options, long_options, opt_index, 1, 0); -} -int _getopt_long_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d) -{ - return _getopt_internal_r_w (argc, argv, options, long_options, opt_index,0, d, 0); -} -int _getopt_long_only_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d) -{ - return _getopt_internal_r_w (argc, argv, options, long_options, opt_index, 1, d, 0); -} \ No newline at end of file diff --git a/windows/src/getopt.c b/windows/src/getopt.c new file mode 120000 index 000000000..d70905d9c --- /dev/null +++ b/windows/src/getopt.c @@ -0,0 +1 @@ +../../src/lib/third_party/src/windows/getopt.c \ No newline at end of file diff --git a/windows/src/getopt.h b/windows/src/getopt.h deleted file mode 100644 index 5e33682de..000000000 --- a/windows/src/getopt.h +++ /dev/null @@ -1,136 +0,0 @@ -/* Getopt for Microsoft C -This code is a modification of the Free Software Foundation, Inc. -Getopt library for parsing command line argument the purpose was -to provide a Microsoft Visual C friendly derivative. This code -provides functionality for both Unicode and Multibyte builds. - -Date: 02/03/2011 - Ludvik Jerabek - Initial Release -Version: 1.0 -Comment: Supports getopt, getopt_long, and getopt_long_only -and POSIXLY_CORRECT environment flag -License: LGPL - -Revisions: - -02/03/2011 - Ludvik Jerabek - Initial Release -02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4 -07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs -08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception -08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB -02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file -08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi -10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features -06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable - -**DISCLAIMER** -THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, -EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE -EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT -APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY -DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY -USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST -PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON -YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE -EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -*/ -#ifndef __GETOPT_H_ - #define __GETOPT_H_ - - #ifdef _GETOPT_API - #undef _GETOPT_API - #endif - - #if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT) - #error "The preprocessor definitions of EXPORTS_GETOPT and STATIC_GETOPT can only be used individually" - #elif defined(STATIC_GETOPT) - #pragma message("Warning static builds of getopt violate the Lesser GNU Public License") - #define _GETOPT_API - #elif defined(EXPORTS_GETOPT) - #pragma message("Exporting getopt library") - #define _GETOPT_API __declspec(dllexport) - #else - #pragma message("Importing getopt library") - #define _GETOPT_API __declspec(dllimport) - #endif - - // Change behavior for C\C++ - #ifdef __cplusplus - #define _GETOPT_BEGIN_EXTERN_C extern "C" { - #define _GETOPT_END_EXTERN_C } - #define _GETOPT_THROW throw() - #else - #define _GETOPT_BEGIN_EXTERN_C - #define _GETOPT_END_EXTERN_C - #define _GETOPT_THROW - #endif - - // Standard GNU options - #define null_argument 0 /*Argument Null*/ - #define no_argument 0 /*Argument Switch Only*/ - #define required_argument 1 /*Argument Required*/ - #define optional_argument 2 /*Argument Optional*/ - - // Shorter Options - #define ARG_NULL 0 /*Argument Null*/ - #define ARG_NONE 0 /*Argument Switch Only*/ - #define ARG_REQ 1 /*Argument Required*/ - #define ARG_OPT 2 /*Argument Optional*/ - - #include - #include - -_GETOPT_BEGIN_EXTERN_C - - extern _GETOPT_API int optind; - extern _GETOPT_API int opterr; - extern _GETOPT_API int optopt; - - // Ansi - struct option_a - { - const char* name; - int has_arg; - int *flag; - int val; - }; - extern _GETOPT_API char *optarg_a; - extern _GETOPT_API int getopt_a(int argc, char *const *argv, const char *optstring) _GETOPT_THROW; - extern _GETOPT_API int getopt_long_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW; - extern _GETOPT_API int getopt_long_only_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW; - - // Unicode - struct option_w - { - const wchar_t* name; - int has_arg; - int *flag; - int val; - }; - extern _GETOPT_API wchar_t *optarg_w; - extern _GETOPT_API int getopt_w(int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW; - extern _GETOPT_API int getopt_long_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW; - extern _GETOPT_API int getopt_long_only_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW; - -_GETOPT_END_EXTERN_C - - #undef _GETOPT_BEGIN_EXTERN_C - #undef _GETOPT_END_EXTERN_C - #undef _GETOPT_THROW - #undef _GETOPT_API - - #ifdef _UNICODE - #define getopt getopt_w - #define getopt_long getopt_long_w - #define getopt_long_only getopt_long_only_w - #define option option_w - #define optarg optarg_w - #else - #define getopt getopt_a - #define getopt_long getopt_long_a - #define getopt_long_only getopt_long_only_a - #define option option_a - #define optarg optarg_a - #endif -#endif // __GETOPT_H_ diff --git a/windows/src/getopt.h b/windows/src/getopt.h new file mode 120000 index 000000000..7ace9a428 --- /dev/null +++ b/windows/src/getopt.h @@ -0,0 +1 @@ +../../src/lib/third_party/include/windows/getopt.h \ No newline at end of file diff --git a/windows/src/win-gettimeofday.c b/windows/src/win-gettimeofday.c deleted file mode 100644 index c921b3325..000000000 --- a/windows/src/win-gettimeofday.c +++ /dev/null @@ -1,55 +0,0 @@ -/* -* Author: Ugo Varetto - ugovaretto@gmail.com -* This code is distributed under the terms of the Apache Software License version 2.0 -* https://opensource.org/licenses/Apache-2.0 -*/ - -#include -#include - -#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 -#else -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL -#endif - -struct timezone -{ - int tz_minuteswest; /* minutes W of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; - -int gettimeofday(struct timeval *tv, struct timezone *tz) -{ - FILETIME ft; - unsigned __int64 tmpres = 0; - static int tzflag = 0; - - if (NULL != tv) - { - GetSystemTimeAsFileTime(&ft); - - tmpres |= ft.dwHighDateTime; - tmpres <<= 32; - tmpres |= ft.dwLowDateTime; - - tmpres /= 10; /*convert into microseconds*/ - /*converting file time to unix epoch*/ - tmpres -= DELTA_EPOCH_IN_MICROSECS; - tv->tv_sec = (long)(tmpres / 1000000UL); - tv->tv_usec = (long)(tmpres % 1000000UL); - } - - if (NULL != tz) - { - if (!tzflag) - { - _tzset(); - tzflag++; - } - tz->tz_minuteswest = _timezone / 60; - tz->tz_dsttime = _daylight; - } - - return 0; -} diff --git a/windows/src/win-gettimeofday.c b/windows/src/win-gettimeofday.c new file mode 120000 index 000000000..c545b3933 --- /dev/null +++ b/windows/src/win-gettimeofday.c @@ -0,0 +1 @@ +../../src/lib/third_party/src/windows/gettimeofday.c \ No newline at end of file -- cgit v1.2.3