diff options
Diffstat (limited to 'e-util/e-path.c')
-rw-r--r-- | e-util/e-path.c | 90 |
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); +} |