diff --git a/src/libstrongswan/collections/enumerator.c b/src/libstrongswan/collections/enumerator.c index 8049ac016..0c97f796f 100644 --- a/src/libstrongswan/collections/enumerator.c +++ b/src/libstrongswan/collections/enumerator.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008-2013 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -25,6 +25,10 @@ #include #include +#ifdef HAVE_GLOB_H +#include +#endif /* HAVE_GLOB_H */ + #include /** @@ -157,8 +161,106 @@ enumerator_t* enumerator_create_directory(const char *path) return &this->public; } +#ifdef HAVE_GLOB_H + /** - * Enumerator implementation for directory enumerator + * Enumerator implementation for glob enumerator + */ +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** glob data */ + glob_t glob; + /** current match */ + char **match; + /** absolute path of current file */ + char full[PATH_MAX]; +} glob_enum_t; + +/** + * Implementation of enumerator_create_glob().destroy + */ +static void destroy_glob_enum(glob_enum_t *this) +{ + globfree(&this->glob); + free(this); +} + +/** + * Implementation of enumerator_create_glob().enumerate + */ +static bool enumerate_glob_enum(glob_enum_t *this, char **file, struct stat *st) +{ + char *match = *(++this->match); + + if (!match) + { + return FALSE; + } + if (file) + { + *file = match; + } + if (st) + { + if (stat(match, st)) + { + DBG1(DBG_LIB, "stat() on '%s' failed: %s", match, + strerror(errno)); + return FALSE; + } + } + return TRUE; +} + +/** + * See header + */ +enumerator_t* enumerator_create_glob(const char *pattern) +{ + glob_enum_t *this; + int status; + + if (!pattern) + { + return enumerator_create_empty(); + } + + INIT(this, + .public = { + .enumerate = (void*)enumerate_glob_enum, + .destroy = (void*)destroy_glob_enum, + }, + .glob = { + .gl_offs = 1, /* reserve one slot so we can enumerate easily */ + } + ); + + status = glob(pattern, GLOB_DOOFFS | GLOB_ERR, NULL, &this->glob); + if (status == GLOB_NOMATCH) + { + DBG1(DBG_LIB, "no files found matching '%s'", pattern); + } + else if (status != 0) + { + DBG1(DBG_LIB, "expanding file pattern '%s' failed: %s", pattern, + strerror(errno)); + } + this->match = this->glob.gl_pathv; + return &this->public; +} + +#else /* HAVE_GLOB_H */ + +enumerator_t* enumerator_create_glob(const char *pattern) +{ + return NULL; +} + +#endif /* HAVE_GLOB_H */ + +/** + * Enumerator implementation for token enumerator */ typedef struct { /** implements enumerator_t */ diff --git a/src/libstrongswan/collections/enumerator.h b/src/libstrongswan/collections/enumerator.h index 299373a3e..55f8d83e6 100644 --- a/src/libstrongswan/collections/enumerator.h +++ b/src/libstrongswan/collections/enumerator.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -69,7 +70,9 @@ enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item)); * This enumerator_t.enumerate() function returns a (to the directory) relative * filename (as a char*), an absolute filename (as a char*) and a file status * (to a struct stat), which all may be NULL. "." and ".." entries are - * skipped. Example: + * skipped. + * + * Example: * * @code char *rel, *abs; @@ -95,6 +98,38 @@ enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item)); */ enumerator_t* enumerator_create_directory(const char *path); +/** + * Create an enumerator over files/directories matching a file pattern. + * + * This enumerator_t.enumerate() function returns the filename (as a char*), + * and a file status (to a struct stat), which both may be NULL. + * + * Example: + * + * @code + char *file; + struct stat st; + enumerator_t *e; + + e = enumerator_create_glob("/etc/ipsec.*.conf"); + if (e) + { + while (e->enumerate(e, &file, &st)) + { + if (S_ISREG(st.st_mode)) + { + printf("%s\n", file); + } + } + e->destroy(e); + } + @endcode + * + * @param pattern file pattern to match + * @return the enumerator, NULL if not supported + */ +enumerator_t* enumerator_create_glob(const char *pattern); + /** * Create an enumerator over tokens of a string. *