]>
diplodocus.org Git - nmh/blob - sbr/crawl_folders.c
3 * crawl_folders.c -- crawl folder hierarchy
5 * This code is Copyright (c) 2008, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
11 #include <h/crawl_folders.h>
14 struct crawl_context
{
15 int max
; /* how many folders we currently can hold in
16 * the array `folders', increased by
17 * CRAWL_NUMFOLDERS at a time */
18 int total
; /* how many `folders' actually has */
19 char **folders
; /* the array of folders */
25 * Add the folder name into the
26 * list in a sorted fashion.
30 add_folder (char *fold
, struct crawl_context
*crawl
)
34 /* if necessary, reallocate the space for folder names */
35 if (crawl
->foldp
>= crawl
->max
) {
36 crawl
->max
+= CRAWL_NUMFOLDERS
;
37 crawl
->folders
= mh_xrealloc (crawl
->folders
,
38 crawl
->max
* sizeof(char *));
41 for (i
= crawl
->start
; i
< crawl
->foldp
; i
++)
42 if (strcmp (fold
, crawl
->folders
[i
]) < 0) {
43 for (j
= crawl
->foldp
- 1; j
>= i
; j
--)
44 crawl
->folders
[j
+ 1] = crawl
->folders
[j
];
46 crawl
->folders
[i
] = fold
;
51 crawl
->folders
[crawl
->foldp
++] = fold
;
55 add_children (char *name
, struct crawl_context
*crawl
)
63 if (!(dd
= opendir (name
))) {
64 admonish (name
, "unable to read directory ");
68 if (strcmp (name
, ".") == 0) {
71 prefix
= concat (name
, "/", (void *)NULL
);
74 while ((dp
= readdir (dd
))) {
75 /* If the system supports it, try to skip processing of children we
76 * know are not directories or symlinks. */
78 #if defined(HAVE_STRUCT_DIRENT_D_TYPE)
79 if (dp
->d_type
== DT_DIR
) {
81 } else if (dp
->d_type
!= DT_LNK
&& dp
->d_type
!= DT_UNKNOWN
) {
85 if (!strcmp (dp
->d_name
, ".") || !strcmp (dp
->d_name
, "..")) {
88 child
= concat (prefix
, dp
->d_name
, (void *)NULL
);
89 /* If we have no d_type or d_type is DT_LNK or DT_UNKNOWN, stat the
90 * child to see what it is. */
91 if (child_is_folder
== -1) {
92 child_is_folder
= (stat (child
, &st
) != -1 && S_ISDIR(st
.st_mode
));
94 if (child_is_folder
) {
95 /* add_folder saves child in the list, don't free it */
96 add_folder (child
, crawl
);
107 crawl_folders_body (struct crawl_context
*crawl
,
108 char *dir
, crawl_callback_t
*callback
, void *baton
)
111 int os
= crawl
->start
;
112 int of
= crawl
->foldp
;
114 crawl
->start
= crawl
->foldp
;
116 add_children (dir
, crawl
);
118 for (i
= crawl
->start
; i
< crawl
->foldp
; i
++) {
119 char *fold
= crawl
->folders
[i
];
120 int crawl_children
= 1;
122 if (callback
!= NULL
) {
123 crawl_children
= callback (fold
, baton
);
126 if (crawl_children
) {
127 crawl_folders_body (crawl
, fold
, callback
, baton
);
136 crawl_folders (char *dir
, crawl_callback_t
*callback
, void *baton
)
138 struct crawl_context
*crawl
= mh_xmalloc (sizeof(*crawl
));
139 crawl
->max
= CRAWL_NUMFOLDERS
;
140 crawl
->total
= crawl
->start
= crawl
->foldp
= 0;
141 crawl
->folders
= mh_xmalloc (crawl
->max
* sizeof(*crawl
->folders
));
143 crawl_folders_body (crawl
, dir
, callback
, baton
);
145 /* Note that we "leak" the folder names, on the assumption that the caller
147 free (crawl
->folders
);