]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Minor] Add generic routine for glob patterns
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 26 May 2018 12:59:25 +0000 (13:59 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 26 May 2018 12:59:25 +0000 (13:59 +0100)
src/libutil/util.c
src/libutil/util.h

index d55a8e8acc80c9da6fc7d371d5e9aebead3c91cb..0b76f193b0c48f847e47380b2323a9a60976bdf6 100644 (file)
@@ -80,6 +80,7 @@
 #endif
 #endif
 #include <math.h> /* for pow */
+#include <glob.h>
 
 #include "cryptobox.h"
 #include "zlib.h"
@@ -2846,4 +2847,91 @@ rspamd_fstring_gzip (rspamd_fstring_t **in)
        *in = comp;
 
        return TRUE;
+}
+
+static gboolean
+rspamd_glob_dir (const gchar *full_path, const gchar *pattern,
+                                gboolean recursive, guint rec_len,
+                                GPtrArray *res, GError **err)
+{
+       glob_t globbuf;
+       const gchar *path;
+       static gchar pathbuf[PATH_MAX]; /* Static to help recursion */
+       guint i;
+       static const guint rec_lim = 16;
+       struct stat st;
+
+       if (rec_len > rec_lim) {
+               g_set_error (err, g_quark_from_static_string ("glob"), EOVERFLOW,
+                               "maximum nesting is reached: %d", rec_lim);
+
+               return FALSE;
+       }
+
+       memset (&globbuf, 0, sizeof (globbuf));
+
+       if (glob (full_path, 0, NULL, &globbuf) != 0) {
+               g_set_error (err, g_quark_from_static_string ("glob"), errno,
+                               "glob %s failed: %s", full_path, strerror (errno));
+               globfree (&globbuf);
+
+               return FALSE;
+       }
+
+       for (i = 0; i < globbuf.gl_pathc; i ++) {
+               path = globbuf.gl_pathv[i];
+
+               if (stat (path, &st) == -1) {
+                       if (errno == EPERM || errno == EACCES || errno == ELOOP) {
+                               /* Silently ignore */
+                               continue;
+                       }
+
+                       g_set_error (err, g_quark_from_static_string ("glob"), errno,
+                                       "stat %s failed: %s", path, strerror (errno));
+                       globfree (&globbuf);
+
+                       return FALSE;
+               }
+
+               if (S_ISREG (st.st_mode)) {
+                       g_ptr_array_add (res, g_strdup (path));
+               }
+               else if (recursive && S_ISDIR (st.st_mode)) {
+                       rspamd_snprintf (pathbuf, sizeof (pathbuf), "%s%c%s",
+                                       path, G_DIR_SEPARATOR, pattern);
+
+                       if (!rspamd_glob_dir (full_path, pattern, recursive, rec_len + 1,
+                                       res, err)) {
+                               globfree (&globbuf);
+
+                               return FALSE;
+                       }
+               }
+       }
+
+       globfree (&globbuf);
+
+       return TRUE;
+}
+
+GPtrArray *
+rspamd_glob_path (const gchar *dir,
+                                 const gchar *pattern,
+                                 gboolean recursive,
+                                 GError **err)
+{
+       gchar path[PATH_MAX];
+       GPtrArray *res;
+
+       res = g_ptr_array_new_full (32, (GDestroyNotify)g_free);
+       rspamd_snprintf (path, sizeof (path), "%s%c%s", dir, G_DIR_SEPARATOR, pattern);
+
+       if (!rspamd_glob_dir (path, pattern, recursive, 0, res, err)) {
+               g_ptr_array_free (res, TRUE);
+
+               return NULL;
+       }
+
+       return res;
 }
\ No newline at end of file
index 6470b5c456b777b4f46850703916bafc256e86a6..96e85af3047bda4d8bc51f4419da019bb85ad5de 100644 (file)
@@ -498,4 +498,17 @@ void rspamd_localtime (gint64 ts, struct tm *dest);
  */
 gboolean rspamd_fstring_gzip (rspamd_fstring_t **in);
 
+/**
+ * Perform globbing searching for the specified path. Allow recursion,
+ * returns an error if maximum nesting is reached.
+ * @param pattern
+ * @param recursive
+ * @param err
+ * @return GPtrArray of gchar *, elements are freed when array is freed
+ */
+GPtrArray *rspamd_glob_path (const gchar *dir,
+                                                        const gchar *pattern,
+                                                        gboolean recursive,
+                                                        GError **err);
+
 #endif