Remove not used code (JLR define)
[mmh] / sbr / crawl_folders.c
1 /*
2 ** crawl_folders.c -- crawl folder hierarchy
3 **
4 ** This code is Copyright (c) 2008, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <h/crawl_folders.h>
11 #include <h/utils.h>
12 #include <dirent.h>
13 #include <sys/stat.h>
14
15 struct crawl_context {
16         int max;    /*
17                     ** number of folders we can hold in the folders array;
18                     ** increased by CRAWL_NUMFOLDERS at a time
19                     */
20         int total;  /* how many `folders' actually has */
21         char **folders;  /* the array of folders */
22         int start;
23         int foldp;
24 };
25
26 /*
27 ** Add the folder name into the
28 ** list in a sorted fashion.
29 */
30
31 static void
32 add_folder(char *fold, struct crawl_context *crawl)
33 {
34         int i, j;
35
36         /* if necessary, reallocate the space for folder names */
37         if (crawl->foldp >= crawl->max) {
38                 crawl->max += CRAWL_NUMFOLDERS;
39                 crawl->folders = mh_xrealloc(crawl->folders,
40                         crawl->max * sizeof(char *));
41         }
42
43         for (i = crawl->start; i < crawl->foldp; i++)
44                 if (strcmp(fold, crawl->folders[i]) < 0) {
45                         for (j = crawl->foldp - 1; j >= i; j--)
46                                 crawl->folders[j + 1] = crawl->folders[j];
47                         crawl->foldp++;
48                         crawl->folders[i] = fold;
49                         return;
50                 }
51
52         crawl->total++;
53         crawl->folders[crawl->foldp++] = fold;
54 }
55
56 static void
57 add_children(char *name, struct crawl_context *crawl)
58 {
59         char *prefix, *child;
60         struct stat st;
61         struct dirent *dp;
62         DIR * dd;
63         int child_is_folder;
64
65         if (!(dd = opendir(name))) {
66                 admonish(name, "unable to read directory ");
67                 return;
68         }
69
70         if (strcmp(name, ".") == 0) {
71                 prefix = mh_xstrdup("");
72         } else {
73                 prefix = concat(name, "/", (void *)NULL);
74         }
75
76         while ((dp = readdir(dd))) {
77                 /*
78                 ** If the system supports it, try to skip processing of
79                 ** children we know are not directories or symlinks.
80                 */
81                 child_is_folder = -1;
82 #if defined(HAVE_STRUCT_DIRENT_D_TYPE)
83                 if (dp->d_type == DT_DIR) {
84                         child_is_folder = 1;
85                 } else if (dp->d_type != DT_LNK && dp->d_type != DT_UNKNOWN) {
86                         continue;
87                 }
88 #endif
89                 if (strcmp(dp->d_name, ".")==0 ||
90                                 strcmp(dp->d_name, "..")==0) {
91                         continue;
92                 }
93                 child = concat(prefix, dp->d_name, (void *)NULL);
94                 /*
95                 ** If we have no d_type or d_type is DT_LNK or DT_UNKNOWN,
96                 ** stat the child to see what it is.
97                 */
98                 if (child_is_folder == -1) {
99                         child_is_folder = (stat(child, &st) != -1 && S_ISDIR(st.st_mode));
100                 }
101                 if (child_is_folder) {
102                         /* add_folder saves child in the list, don't free it */
103                         add_folder(child, crawl);
104                 } else {
105                         mh_free0(&child);
106                 }
107         }
108
109         closedir(dd);
110         mh_free0(&prefix);
111 }
112
113 static void
114 crawl_folders_body(struct crawl_context *crawl, char *dir,
115         crawl_callback_t *callback, void *baton)
116 {
117         int i;
118         int os = crawl->start;
119         int of = crawl->foldp;
120
121         crawl->start = crawl->foldp;
122
123         add_children(dir, crawl);
124
125         for (i = crawl->start; i < crawl->foldp; i++) {
126                 char *fold = crawl->folders[i];
127                 int crawl_children = 1;
128
129                 if (callback != NULL) {
130                         crawl_children = callback(fold, baton);
131                 }
132
133                 if (crawl_children) {
134                         crawl_folders_body(crawl, fold, callback, baton);
135                 }
136         }
137
138         crawl->start = os;
139         crawl->foldp = of;
140 }
141
142 void
143 crawl_folders(char *dir, crawl_callback_t *callback, void *baton)
144 {
145         struct crawl_context *crawl = mh_xcalloc(1, sizeof(*crawl));
146         crawl->max = CRAWL_NUMFOLDERS;
147         crawl->total = crawl->start = crawl->foldp = 0;
148         crawl->folders = mh_xcalloc(crawl->max, sizeof(*crawl->folders));
149
150         crawl_folders_body(crawl, dir, callback, baton);
151
152         /*
153         ** Note that we "leak" the folder names, on the assumption that the
154         ** caller is using them.
155         */
156         mh_free0(&(crawl->folders));
157         mh_free0(&crawl);
158 }