X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fwin32_replacements.c;h=4e9df0aee8a5a538676176fd74a3d20819222513;hb=af1a9f0d89f9d4428776238a561a6a5b6900f2d4;hp=d16936ceec299415b5b4b72b66dcb80ac112ffdf;hpb=66abeba083ec882f4fac6a2d6a8ce3eef61be442;p=wimlib diff --git a/src/win32_replacements.c b/src/win32_replacements.c index d16936ce..4e9df0ae 100644 --- a/src/win32_replacements.c +++ b/src/win32_replacements.c @@ -28,12 +28,14 @@ # include "config.h" #endif +#include #include #include /* for PathMatchSpecW() */ #include "wimlib/win32_common.h" #include "wimlib/assert.h" #include "wimlib/file_io.h" +#include "wimlib/glob.h" #include "wimlib/error.h" #include "wimlib/util.h" @@ -279,7 +281,6 @@ win32_get_file_and_vol_ids(const wchar_t *path, u64 *ino_ret, u64 *dev_ret) *dev_ret = file_info.dwVolumeSerialNumber; ret = 0; } -out_close_handle: err = GetLastError(); CloseHandle(h); SetLastError(err); @@ -288,5 +289,109 @@ out: return ret; } +/* Replacement for glob() in Windows native builds that operates on wide + * characters. */ +int +win32_wglob(const wchar_t *pattern, int flags, + int (*errfunc)(const wchar_t *epath, int eerrno), + glob_t *pglob) +{ + WIN32_FIND_DATAW dat; + DWORD err; + HANDLE hFind; + int ret; + size_t nspaces; + + const wchar_t *backslash, *end_slash; + size_t prefix_len; + + backslash = wcsrchr(pattern, L'\\'); + end_slash = wcsrchr(pattern, L'/'); + + if (backslash > end_slash) + end_slash = backslash; + + if (end_slash) + prefix_len = end_slash - pattern + 1; + else + prefix_len = 0; + + /* This function does not support all functionality of the POSIX glob(), + * so make sure the parameters are consistent with supported + * functionality. */ + wimlib_assert(errfunc == NULL); + wimlib_assert((flags & GLOB_ERR) == GLOB_ERR); + wimlib_assert((flags & ~(GLOB_NOSORT | GLOB_ERR)) == 0); + + hFind = FindFirstFileW(pattern, &dat); + if (hFind == INVALID_HANDLE_VALUE) { + err = GetLastError(); + if (err == ERROR_FILE_NOT_FOUND) { + errno = 0; + return GLOB_NOMATCH; + } else { + /* The other possible error codes for FindFirstFile() + * are undocumented. */ + errno = EIO; + return GLOB_ABORTED; + } + } + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + nspaces = 0; + do { + wchar_t *path; + if (pglob->gl_pathc == nspaces) { + size_t new_nspaces; + wchar_t **pathv; + + new_nspaces = nspaces * 2 + 1; + pathv = REALLOC(pglob->gl_pathv, + new_nspaces * sizeof(pglob->gl_pathv[0])); + if (!pathv) + goto oom; + pglob->gl_pathv = pathv; + nspaces = new_nspaces; + } + size_t filename_len = wcslen(dat.cFileName); + size_t len_needed = prefix_len + filename_len; + + path = MALLOC((len_needed + 1) * sizeof(wchar_t)); + if (!path) + goto oom; + + wmemcpy(path, pattern, prefix_len); + wmemcpy(path + prefix_len, dat.cFileName, filename_len + 1); + pglob->gl_pathv[pglob->gl_pathc++] = path; + } while (FindNextFileW(hFind, &dat)); + err = GetLastError(); + CloseHandle(hFind); + if (err == ERROR_NO_MORE_FILES) { + errno = 0; + return 0; + } else { + /* Other possible error codes for FindNextFile() are + * undocumented */ + errno = EIO; + ret = GLOB_ABORTED; + goto fail_globfree; + } +oom: + CloseHandle(hFind); + errno = ENOMEM; + ret = GLOB_NOSPACE; +fail_globfree: + globfree(pglob); + return ret; +} + +void +globfree(glob_t *pglob) +{ + size_t i; + for (i = 0; i < pglob->gl_pathc; i++) + free(pglob->gl_pathv[i]); + free(pglob->gl_pathv); +} #endif /* __WIN32__ */