aboutsummaryrefslogtreecommitdiffstats
path: root/e-util/e-path.c
diff options
context:
space:
mode:
Diffstat (limited to 'e-util/e-path.c')
-rw-r--r--e-util/e-path.c90
1 files changed, 89 insertions, 1 deletions
diff --git a/e-util/e-path.c b/e-util/e-path.c
index 0728c94013..22b370b436 100644
--- a/e-util/e-path.c
+++ b/e-util/e-path.c
@@ -21,7 +21,9 @@
#include <config.h>
+#include <dirent.h>
#include <string.h>
+#include <sys/stat.h>
#include <glib.h>
#include "e-path.h"
@@ -37,7 +39,8 @@
* This converts the "virtual" path @path into an expanded form that
* allows a given name to refer to both a file and a directory. The
* expanded path will have a "subfolders" directory inserted between
- * each path component.
+ * each path component. If the path ends with "/", the returned
+ * physical path will end with "/subfolders"
*
* If @prefix is non-%NULL, it will be prepended to the returned path.
*
@@ -117,3 +120,88 @@ e_path_to_physical (const char *prefix, const char *vpath)
return ppath;
}
+
+
+static gboolean
+find_folders_recursive (const char *physical_path, const char *path,
+ EPathFindFoldersCallback callback, gpointer data)
+{
+ DIR *dir;
+ char *subfolder_directory_path;
+ gboolean ok;
+
+ if (*path) {
+ if (!callback (physical_path, path, data))
+ return FALSE;
+
+ subfolder_directory_path = g_strdup_printf ("%s/%s", physical_path, SUBFOLDER_DIR_NAME);
+ } else {
+ /* On the top level, we have no folders and,
+ * consequently, no subfolder directory.
+ */
+
+ subfolder_directory_path = g_strdup (physical_path);
+ }
+
+ /* Now scan the subfolders and load them. */
+ dir = opendir (subfolder_directory_path);
+ if (dir == NULL) {
+ g_free (subfolder_directory_path);
+ return TRUE;
+ }
+
+ ok = TRUE;
+ while (ok) {
+ struct stat file_stat;
+ struct dirent *dirent;
+ char *file_path;
+ char *new_path;
+
+ dirent = readdir (dir);
+ if (dirent == NULL)
+ break;
+
+ if (strcmp (dirent->d_name, ".") == 0 || strcmp (dirent->d_name, "..") == 0)
+ continue;
+
+ file_path = g_strdup_printf ("%s/%s", subfolder_directory_path,
+ dirent->d_name);
+
+ if (stat (file_path, &file_stat) < 0 ||
+ ! S_ISDIR (file_stat.st_mode)) {
+ g_free (file_path);
+ continue;
+ }
+
+ new_path = g_strdup_printf ("%s/%s", path, dirent->d_name);
+
+ ok = find_folders_recursive (file_path, new_path, callback, data);
+
+ g_free (file_path);
+ g_free (new_path);
+ }
+
+ closedir (dir);
+ g_free (subfolder_directory_path);
+
+ return ok;
+}
+
+/**
+ * e_path_find_folders:
+ * @prefix: directory to start from
+ * @callback: Callback to invoke on each folder
+ * @data: Data for @callback
+ *
+ * Walks the folder tree starting at @prefix and calls @callback
+ * on each folder.
+ *
+ * Return value: %TRUE on success, %FALSE if an error occurs at any point
+ **/
+gboolean
+e_path_find_folders (const char *prefix,
+ EPathFindFoldersCallback callback,
+ gpointer data)
+{
+ return find_folders_recursive (prefix, "", callback, data);
+}