aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Deri <deri@ntop.org>2023-10-05 11:05:14 +0200
committerLuca Deri <deri@ntop.org>2023-10-05 11:05:14 +0200
commit3881d162f7bb6b1b6a27ddfd5f1617fd7406fbfe (patch)
tree4fe431ca19785ed5fb5778601da67d231446617b
parent36112a645b36a225abf45cf29f4cf1f68d2c27f6 (diff)
Windows compilation fixes
-rw-r--r--src/lib/ndpi_main.c2
-rw-r--r--src/lib/third_party/include/dirent.h584
2 files changed, 586 insertions, 0 deletions
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index 37222a884..f72bfdae6 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -47,6 +47,8 @@
#ifndef WIN32
#include <unistd.h>
#include <dirent.h>
+#else
+#include "dirent.h"
#endif
#ifndef TH_FIN
diff --git a/src/lib/third_party/include/dirent.h b/src/lib/third_party/include/dirent.h
new file mode 100644
index 000000000..de75def2f
--- /dev/null
+++ b/src/lib/third_party/include/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 <sys/types.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <Windows.h>
+
+#include <Shlwapi.h>
+
+#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__ */