-
/*
- * crawl_folders.c -- crawl folder hierarchy
- *
- * This code is Copyright (c) 2008, by the authors of nmh. See the
- * COPYRIGHT file in the root directory of the nmh distribution for
- * complete copyright information.
- */
+** crawl_folders.c -- crawl folder hierarchy
+**
+** This code is Copyright (c) 2008, by the authors of nmh. See the
+** COPYRIGHT file in the root directory of the nmh distribution for
+** complete copyright information.
+*/
#include <h/mh.h>
#include <h/crawl_folders.h>
#include <h/utils.h>
+#include <dirent.h>
+#include <sys/stat.h>
struct crawl_context {
- int max; /* how many folders we currently can hold in
- * the array `folders', increased by
- * CRAWL_NUMFOLDERS at a time */
- int total; /* how many `folders' actually has */
- char **folders; /* the array of folders */
- int start;
- int foldp;
+ int max; /*
+ ** number of folders we can hold in the folders array;
+ ** increased by CRAWL_NUMFOLDERS at a time
+ */
+ int total; /* how many `folders' actually has */
+ char **folders; /* the array of folders */
+ int start;
+ int foldp;
};
/*
- * Add the folder name into the
- * list in a sorted fashion.
- */
+** Add the folder name into the
+** list in a sorted fashion.
+*/
static void
-add_folder (char *fold, struct crawl_context *crawl)
+add_folder(char *fold, struct crawl_context *crawl)
{
- register int i, j;
-
- /* if necessary, reallocate the space for folder names */
- if (crawl->foldp >= crawl->max) {
- crawl->max += CRAWL_NUMFOLDERS;
- crawl->folders = mh_xrealloc (crawl->folders,
- crawl->max * sizeof(char *));
- }
-
- for (i = crawl->start; i < crawl->foldp; i++)
- if (strcmp (fold, crawl->folders[i]) < 0) {
- for (j = crawl->foldp - 1; j >= i; j--)
- crawl->folders[j + 1] = crawl->folders[j];
- crawl->foldp++;
- crawl->folders[i] = fold;
- return;
+ int i, j;
+
+ /* if necessary, reallocate the space for folder names */
+ if (crawl->foldp >= crawl->max) {
+ crawl->max += CRAWL_NUMFOLDERS;
+ crawl->folders = mh_xrealloc(crawl->folders,
+ crawl->max * sizeof(char *));
}
- crawl->total++;
- crawl->folders[crawl->foldp++] = fold;
+ for (i = crawl->start; i < crawl->foldp; i++)
+ if (strcmp(fold, crawl->folders[i]) < 0) {
+ for (j = crawl->foldp - 1; j >= i; j--)
+ crawl->folders[j + 1] = crawl->folders[j];
+ crawl->foldp++;
+ crawl->folders[i] = fold;
+ return;
+ }
+
+ crawl->total++;
+ crawl->folders[crawl->foldp++] = fold;
}
static void
-add_children (char *name, struct crawl_context *crawl)
+add_children(char *name, struct crawl_context *crawl)
{
- char *prefix, *child;
- struct stat st;
- struct dirent *dp;
- DIR * dd;
- int child_is_folder;
-
- if (!(dd = opendir (name))) {
- admonish (name, "unable to read directory ");
- return;
- }
-
- if (strcmp (name, ".") == 0) {
- prefix = getcpy ("");
- } else {
- prefix = concat (name, "/", (void *)NULL);
- }
-
- while ((dp = readdir (dd))) {
- /* If the system supports it, try to skip processing of children we
- * know are not directories or symlinks. */
- child_is_folder = -1;
-#if defined(HAVE_STRUCT_DIRENT_D_TYPE)
- if (dp->d_type == DT_DIR) {
- child_is_folder = 1;
- } else if (dp->d_type != DT_LNK && dp->d_type != DT_UNKNOWN) {
- continue;
+ char *prefix, *child;
+ struct stat st;
+ struct dirent *dp;
+ DIR * dd;
+ int child_is_folder;
+
+ if (!(dd = opendir(name))) {
+ admonish(name, "unable to read directory ");
+ return;
}
-#endif
- if (!strcmp (dp->d_name, ".") || !strcmp (dp->d_name, "..")) {
- continue;
- }
- child = concat (prefix, dp->d_name, (void *)NULL);
- /* If we have no d_type or d_type is DT_LNK or DT_UNKNOWN, stat the
- * child to see what it is. */
- if (child_is_folder == -1) {
- child_is_folder = (stat (child, &st) != -1 && S_ISDIR(st.st_mode));
- }
- if (child_is_folder) {
- /* add_folder saves child in the list, don't free it */
- add_folder (child, crawl);
+
+ if (strcmp(name, ".") == 0) {
+ prefix = mh_xstrdup("");
} else {
- free (child);
+ prefix = concat(name, "/", (void *)NULL);
}
- }
- closedir (dd);
- free(prefix);
+ while ((dp = readdir(dd))) {
+ /*
+ ** If the system supports it, try to skip processing of
+ ** children we know are not directories or symlinks.
+ */
+ child_is_folder = -1;
+#if defined(HAVE_STRUCT_DIRENT_D_TYPE)
+ if (dp->d_type == DT_DIR) {
+ child_is_folder = 1;
+ } else if (dp->d_type != DT_LNK && dp->d_type != DT_UNKNOWN) {
+ continue;
+ }
+#endif
+ if (strcmp(dp->d_name, ".")==0 ||
+ strcmp(dp->d_name, "..")==0) {
+ continue;
+ }
+ child = concat(prefix, dp->d_name, (void *)NULL);
+ /*
+ ** If we have no d_type or d_type is DT_LNK or DT_UNKNOWN,
+ ** stat the child to see what it is.
+ */
+ if (child_is_folder == -1) {
+ child_is_folder = (stat(child, &st) != -1 && S_ISDIR(st.st_mode));
+ }
+ if (child_is_folder) {
+ /* add_folder saves child in the list, don't free it */
+ add_folder(child, crawl);
+ } else {
+ mh_free0(&child);
+ }
+ }
+
+ closedir(dd);
+ mh_free0(&prefix);
}
static void
-crawl_folders_body (struct crawl_context *crawl,
- char *dir, crawl_callback_t *callback, void *baton)
+crawl_folders_body(struct crawl_context *crawl, char *dir,
+ crawl_callback_t *callback, void *baton)
{
- int i;
- int os = crawl->start;
- int of = crawl->foldp;
+ int i;
+ int os = crawl->start;
+ int of = crawl->foldp;
- crawl->start = crawl->foldp;
+ crawl->start = crawl->foldp;
- add_children (dir, crawl);
+ add_children(dir, crawl);
- for (i = crawl->start; i < crawl->foldp; i++) {
- char *fold = crawl->folders[i];
- int crawl_children = 1;
+ for (i = crawl->start; i < crawl->foldp; i++) {
+ char *fold = crawl->folders[i];
+ int crawl_children = 1;
- if (callback != NULL) {
- crawl_children = callback (fold, baton);
- }
+ if (callback != NULL) {
+ crawl_children = callback(fold, baton);
+ }
- if (crawl_children) {
- crawl_folders_body (crawl, fold, callback, baton);
+ if (crawl_children) {
+ crawl_folders_body(crawl, fold, callback, baton);
+ }
}
- }
- crawl->start = os;
- crawl->foldp = of;
+ crawl->start = os;
+ crawl->foldp = of;
}
void
-crawl_folders (char *dir, crawl_callback_t *callback, void *baton)
+crawl_folders(char *dir, crawl_callback_t *callback, void *baton)
{
- struct crawl_context *crawl = mh_xmalloc (sizeof(*crawl));
- crawl->max = CRAWL_NUMFOLDERS;
- crawl->total = crawl->start = crawl->foldp = 0;
- crawl->folders = mh_xmalloc (crawl->max * sizeof(*crawl->folders));
-
- crawl_folders_body (crawl, dir, callback, baton);
-
- /* Note that we "leak" the folder names, on the assumption that the caller
- * is using them. */
- free (crawl->folders);
- free (crawl);
+ struct crawl_context *crawl = mh_xcalloc(1, sizeof(*crawl));
+ crawl->max = CRAWL_NUMFOLDERS;
+ crawl->total = crawl->start = crawl->foldp = 0;
+ crawl->folders = mh_xcalloc(crawl->max, sizeof(*crawl->folders));
+
+ crawl_folders_body(crawl, dir, callback, baton);
+
+ /*
+ ** Note that we "leak" the folder names, on the assumption that the
+ ** caller is using them.
+ */
+ mh_free0(&(crawl->folders));
+ mh_free0(&crawl);
}