diff options
author | Glenn Strauss <gstrauss@gluelogic.com> | 2021-02-05 12:39:25 -0500 |
---|---|---|
committer | Glenn Strauss <gstrauss@gluelogic.com> | 2023-05-03 23:11:34 -0400 |
commit | d7bbd70bd10e429c18df273dd060006a69a91d1e (patch) | |
tree | c56167e09c96919abbf8d03e3eabf78a11d76490 /src/sys-dirent.h | |
parent | 8e8938a359019c9aa1f2413c0419cd5124d33840 (diff) | |
download | lighttpd-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.h | 187 |
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 |