summaryrefslogtreecommitdiff
path: root/src/sys-dirent.h
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2021-02-05 12:39:25 -0500
committerGlenn Strauss <gstrauss@gluelogic.com>2023-05-03 23:11:34 -0400
commitd7bbd70bd10e429c18df273dd060006a69a91d1e (patch)
treec56167e09c96919abbf8d03e3eabf78a11d76490 /src/sys-dirent.h
parent8e8938a359019c9aa1f2413c0419cd5124d33840 (diff)
downloadlighttpd-git-d7bbd70bd10e429c18df273dd060006a69a91d1e.tar.gz
[multiple] _WIN32 Find*File() sys-dirent.h
_WIN32 FindFirstFile(), FindNextFile(), FindClose()
Diffstat (limited to 'src/sys-dirent.h')
-rw-r--r--src/sys-dirent.h187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/sys-dirent.h b/src/sys-dirent.h
new file mode 100644
index 00000000..213112e7
--- /dev/null
+++ b/src/sys-dirent.h
@@ -0,0 +1,187 @@
+/*
+ * sys-dirent.h - <sys/dirent.h> wrapper (selected functions; not complete)
+ *
+ * Copyright(c) 2021 Glenn Strauss gstrauss()gluelogic.com All rights reserved
+ * License: BSD 3-clause (same as lighttpd)
+ */
+#ifndef INCLUDED_SYS_DIRENT_H
+#define INCLUDED_SYS_DIRENT_H
+#include "first.h"
+
+#include <sys/types.h>
+#ifndef _WIN32
+#include <dirent.h>
+#endif
+
+
+#ifdef _WIN32
+
+#include <windows.h>
+#include <direct.h>
+#include <stdlib.h>
+#include <stringapiset.h>
+
+/*#include <stdlib.h>*/ /* _MAX_PATH */
+/* Windows C Runtime supports path lengths up to 32768 characters in length (_MAX_PATH)
+ * https://docs.microsoft.com/en-us/cpp/c-runtime-library/path-field-limits?view=msvc-160
+ *
+ * Impose a shorter limit (4k) since using stack below (char path[PATH_MAX+1])
+ */
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+#ifndef DT_UNKNOWN
+#define DT_UNKNOWN 0
+#endif
+#ifndef DT_FIFO
+#define DT_FIFO 1
+#endif
+#ifndef DT_CHR
+#define DT_CHR 2
+#endif
+#ifndef DT_DIR
+#define DT_DIR 4
+#endif
+#ifndef DT_BLK
+#define DT_BLK 6
+#endif
+#ifndef DT_REG
+#define DT_REG 8
+#endif
+#ifndef DT_LNK
+#define DT_LNK 10
+#endif
+#ifndef DT_SOCK
+#define DT_SOCK 12
+#endif
+#ifndef DT_WHT
+#define DT_WHT 14
+#endif
+#ifndef _DIRENT_HAVE_D_NAMLEN
+#define _DIRENT_HAVE_D_NAMLEN 1
+#endif
+#ifndef _DIRENT_HAVE_D_TYPE
+#define _DIRENT_HAVE_D_TYPE 1
+#endif
+#ifndef DTTOIF
+#define DTTOIF(d_type) (((mode_t)(d_type)) << 12)
+#endif
+/* minimal implementation to walk directory */
+struct dirent {
+ char *d_name;
+ uint8_t d_type;
+ uint16_t d_namlen;
+};
+struct DIR {
+ int first;
+ int last_error;
+ HANDLE hFind;
+ struct dirent de;
+ WIN32_FIND_DATAW ffd;
+ char fnUTF8[260*4+1]; /* <stdio.h> FILENAME_MAX 260 */
+};
+typedef struct DIR DIR;
+
+static inline int
+closedir (DIR * const dirp);
+static inline int
+closedir (DIR * const dirp)
+{
+ if (!dirp) {
+ errno = EBADF;
+ return -1;
+ }
+ FindClose(dirp->hFind);
+ free(dirp);
+ return 0;
+}
+
+static inline DIR *
+opendir (const char *name);
+static inline DIR *
+opendir (const char *name)
+{
+ WCHAR wbuf[4096];
+ int wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, name, -1,
+ wbuf, (sizeof(wbuf)/sizeof(*wbuf))-2);
+ if (wlen < 2) return NULL;
+ --wlen;
+ if (wbuf[wlen-1] != '/' && wbuf[wlen-1] != '\\') wbuf[wlen++] = '\\';
+ wbuf[wlen] = '*';
+ wbuf[wlen+1] = '\0';
+ DIR * const dirp = calloc(1, sizeof(DIR));
+ if (NULL == dirp) return NULL;
+ dirp->first = 1;
+ dirp->hFind = FindFirstFileExW(wbuf, FindExInfoBasic, &dirp->ffd,
+ FindExSearchNameMatch, NULL,
+ FIND_FIRST_EX_LARGE_FETCH);
+ if (INVALID_HANDLE_VALUE == dirp->hFind) {
+ if (GetLastError() != ERROR_FILE_NOT_FOUND) {
+ free(dirp);
+ return NULL;
+ }
+ dirp->last_error = ERROR_NO_MORE_FILES;
+ } /* else dirp->last_error = 0 */
+ return dirp;
+}
+
+static inline struct dirent *
+readdir (DIR * const dirp);
+static inline struct dirent *
+readdir (DIR * const dirp)
+{
+ struct dirent * const de = &dirp->de;
+ WIN32_FIND_DATAW * const ffd = &dirp->ffd;
+
+ do {
+ if (!dirp->first) {
+ if (0 == FindNextFileW(dirp->hFind, ffd))
+ dirp->last_error = GetLastError();
+ }
+ else
+ dirp->first = 0;
+
+ if (dirp->last_error)
+ return NULL;
+
+ const int dsz =
+ WideCharToMultiByte(CP_UTF8, 0, ffd->cFileName, -1,
+ dirp->fnUTF8, sizeof(dirp->fnUTF8), NULL, NULL);
+ if (dsz > 0 && dsz <= UINT16_MAX) { /*(dsz includes '\0' here)*/
+ de->d_namlen = (uint16_t)(dsz-1);
+ de->d_name = dirp->fnUTF8;
+ if ((ffd->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+ == FILE_ATTRIBUTE_REPARSE_POINT)
+ de->d_type = DT_LNK;
+ /* XXX: incomplete; need to check for IO_REPARSE_TAG_SYMLINK */
+ else if ((ffd->dwFileAttributes & FILE_ATTRIBUTE_DEVICE)
+ == FILE_ATTRIBUTE_DEVICE)
+ de->d_type = DT_CHR;
+ else if ((ffd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ == FILE_ATTRIBUTE_DIRECTORY)
+ de->d_type = DT_DIR;
+ else
+ de->d_type = DT_REG;
+ }
+ else /*(ignore excessively long names)*/
+ de->d_namlen = 0;
+
+ } while (0 == de->d_namlen);
+
+ return de;
+}
+
+#endif /* _WIN32 */
+
+
+#ifndef _D_EXACT_NAMLEN
+#ifdef _DIRENT_HAVE_D_NAMLEN
+#define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
+#else
+#define _D_EXACT_NAMLEN(d) (strlen ((d)->d_name))
+#endif
+#endif
+
+
+#endif