]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
enumerator: Add enumerator to enumerate files matching a pattern
authorTobias Brunner <tobias@strongswan.org>
Wed, 4 Sep 2013 16:14:29 +0000 (18:14 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 15 May 2014 09:28:05 +0000 (11:28 +0200)
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.

src/libstrongswan/collections/enumerator.c
src/libstrongswan/collections/enumerator.h

index 8049ac016e15340a7edeacbd893fd8c143e8d584..0c97f796fe75c044aae8ef0c26301c645c3b8df3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2013 Tobias Brunner
  * Copyright (C) 2007 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
 #include <errno.h>
 #include <string.h>
 
+#ifdef HAVE_GLOB_H
+#include <glob.h>
+#endif /* HAVE_GLOB_H */
+
 #include <utils/debug.h>
 
 /**
@@ -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 */
index 299373a3e14a6208a86c7c143b2882387667f2dc..55f8d83e6685a761e64866ab8c9b8a1a6b87b204 100644 (file)
@@ -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.
  *