--- embedaddon/strongswan/src/libstrongswan/collections/enumerator.c 2020/06/03 09:46:43 1.1 +++ embedaddon/strongswan/src/libstrongswan/collections/enumerator.c 2021/03/17 00:20:08 1.1.1.2 @@ -27,6 +27,8 @@ #ifdef HAVE_GLOB_H #include +#elif defined(WIN32) +#include #endif /* HAVE_GLOB_H */ #include @@ -171,9 +173,9 @@ enumerator_t* enumerator_create_directory(const char * return NULL; } /* append a '/' if not already done */ - if (this->full[len-1] != '/') + if (!path_is_separator(this->full[len-1])) { - this->full[len++] = '/'; + this->full[len++] = DIRECTORY_SEPARATOR[0]; this->full[len] = '\0'; } this->full_end = &this->full[len]; @@ -201,8 +203,6 @@ typedef struct { glob_t glob; /** iteration count */ u_int pos; - /** absolute path of current file */ - char full[PATH_MAX]; } glob_enum_t; METHOD(enumerator_t, destroy_glob_enum, void, @@ -269,6 +269,143 @@ enumerator_t* enumerator_create_glob(const char *patte { DBG1(DBG_LIB, "expanding file pattern '%s' failed: %s", pattern, strerror(errno)); + } + return &this->public; +} + +#elif defined(WIN32) /* HAVE_GLOB_H */ + +/** + * Enumerator implementation for glob enumerator on Windows + */ +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** search handle */ + HANDLE handle; + /** current file path */ + char path[PATH_MAX]; + /** base path */ + char *base; +} glob_enum_t; + +METHOD(enumerator_t, destroy_glob_enum, void, + glob_enum_t *this) +{ + if (this->handle != INVALID_HANDLE_VALUE) + { + FindClose(this->handle); + } + free(this->base); + free(this); +} + +/** + * Create the combined path from the given file data + */ +static bool combine_glob_path(glob_enum_t *this, WIN32_FIND_DATA *data) +{ + if (snprintf(this->path, sizeof(this->path), "%s%s%s", this->base, + DIRECTORY_SEPARATOR, data->cFileName) >= sizeof(this->path)) + { + DBG1(DBG_LIB, "path for '%s' too long, ignored", data->cFileName); + return FALSE; + } + return TRUE; +} + +/** + * Return the path and stat data for the current file + */ +static bool enumerate_glob_enum_data(glob_enum_t *this, va_list args) +{ + struct stat *st; + char **file; + + VA_ARGS_VGET(args, file, st); + + if (file) + { + *file = this->path; + } + if (st && stat(this->path, st)) + { + DBG1(DBG_LIB, "stat() on '%s' failed: %s", this->path, + strerror(errno)); + return FALSE; + } + return TRUE; +} + +METHOD(enumerator_t, enumerate_glob_enum, bool, + glob_enum_t *this, va_list args) +{ + WIN32_FIND_DATA data; + + do + { + if (!FindNextFile(this->handle, &data)) + { + return FALSE; + } + } + while (!combine_glob_path(this, &data)); + + return enumerate_glob_enum_data(this, args); +} + +METHOD(enumerator_t, enumerate_glob_enum_first, bool, + glob_enum_t *this, va_list args) +{ + if (enumerate_glob_enum_data(this, args)) + { + this->public.venumerate = _enumerate_glob_enum; + return TRUE; + } + return FALSE; +} + +/* + * Described in header + */ +enumerator_t *enumerator_create_glob(const char *pattern) +{ + glob_enum_t *this; + WIN32_FIND_DATA data; + + if (!pattern) + { + return enumerator_create_empty(); + } + + INIT(this, + .public = { + .enumerate = enumerator_enumerate_default, + .venumerate = _enumerate_glob_enum_first, + .destroy = _destroy_glob_enum, + }, + .base = path_dirname(pattern), + ); + + this->handle = FindFirstFile(pattern, &data); + if (this->handle == INVALID_HANDLE_VALUE) + { + if (GetLastError() == ERROR_FILE_NOT_FOUND || + GetLastError() == ERROR_PATH_NOT_FOUND) + { + DBG1(DBG_LIB, "no files found matching '%s'", pattern); + } + else + { + DBG1(DBG_LIB, "FindFirstFile failed for pattern '%s' (%d)", pattern, + GetLastError()); + } + destroy_glob_enum(this); + return enumerator_create_empty(); + } + else if (!combine_glob_path(this, &data)) + { /* check the next file if we can't combine the path for the first one */ + this->public.venumerate = _enumerate_glob_enum; } return &this->public; }