From: Tobias Brunner Date: Wed, 4 Sep 2013 16:14:29 +0000 (+0200) Subject: enumerator: Add enumerator to enumerate files matching a pattern X-Git-Tag: 5.2.0dr4~1^2~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=96de74b879f478955246aeee382afb5476187228;p=thirdparty%2Fstrongswan.git enumerator: Add enumerator to enumerate files matching a pattern This enumerator is a wrapper around glob(3). If that function is not supported NULL is returned. If no files match or an error occurs during the pattern expansion an error is logged and the enumerator simply returns no items. RFC: if GLOB_ERR is not supplied glob returns GLOB_NOMATCH if e.g. the base directory of the pattern does not exist, which would otherwise result in an error. This way there is at least a clear error message in case of a typo. --- diff --git a/src/libstrongswan/collections/enumerator.c b/src/libstrongswan/collections/enumerator.c index 8049ac016e..0c97f796fe 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 299373a3e1..55f8d83e66 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. *