9 /* #include <scan_dir.h>
11 /* SCAN_DIR *scan_dir_open(path)
14 /* char *scan_dir_next(scan)
17 /* char *scan_dir_path(scan)
20 /* void scan_push(scan, entry)
24 /* SCAN_DIR *scan_pop(scan)
27 /* SCAN_DIR *scan_dir_close(scan)
30 /* These functions scan directories for names. The "." and
31 /* ".." names are skipped. Essentially, this is <dirent>
32 /* extended with error handling and with knowledge of the
33 /* name of the directory being scanned.
35 /* scan_dir_open() opens the named directory and
36 /* returns a handle for subsequent use.
38 /* scan_dir_close() terminates the directory scan, cleans up
39 /* and returns a null pointer.
41 /* scan_dir_next() returns the next requested object in the specified
42 /* directory. It skips the "." and ".." entries.
44 /* scan_dir_path() returns the name of the directory being scanned.
46 /* scan_dir_push() causes the specified directory scan to enter the
47 /* named subdirectory.
49 /* scan_dir_pop() leaves the directory being scanned and returns
50 /* to the previous one. The result is the argument, null if no
51 /* previous directory information is available.
53 /* All errors are fatal.
57 /* The Secure Mailer license must be distributed with this software.
60 /* IBM T.J. Watson Research
62 /* Yorktown Heights, NY 10598, USA
72 #ifdef HAVE_SYS_NDIR_H
84 /* Utility library. */
88 #include "stringops.h"
93 * The interface is based on an opaque structure, so we don't have to expose
94 * the user to the guts. Subdirectory info sits in front of parent directory
95 * info: a simple last-in, first-out list.
97 typedef struct SCAN_INFO SCAN_INFO
;
100 char *path
; /* directory name */
101 DIR *dir
; /* directory structure */
102 SCAN_INFO
*parent
; /* linkage */
105 SCAN_INFO
*current
; /* current scan */
108 #define SCAN_DIR_PATH(scan) (scan->current->path)
109 #define STR(x) vstring_str(x)
111 /* scan_dir_path - return the path of the directory being read. */
113 char *scan_dir_path(SCAN_DIR
*scan
)
115 return (SCAN_DIR_PATH(scan
));
118 /* scan_dir_push - enter directory */
120 void scan_dir_push(SCAN_DIR
*scan
, const char *path
)
122 const char *myname
= "scan_dir_push";
125 info
= (SCAN_INFO
*) mymalloc(sizeof(*info
));
127 info
->path
= concatenate(SCAN_DIR_PATH(scan
), "/", path
, (char *) 0);
129 info
->path
= mystrdup(path
);
130 if ((info
->dir
= opendir(info
->path
)) == 0)
131 msg_fatal("%s: open directory %s: %m", myname
, info
->path
);
133 msg_info("%s: open %s", myname
, info
->path
);
134 info
->parent
= scan
->current
;
135 scan
->current
= info
;
138 /* scan_dir_pop - leave directory */
140 SCAN_DIR
*scan_dir_pop(SCAN_DIR
*scan
)
142 const char *myname
= "scan_dir_pop";
143 SCAN_INFO
*info
= scan
->current
;
148 parent
= info
->parent
;
149 if (closedir(info
->dir
))
150 msg_fatal("%s: close directory %s: %m", myname
, info
->path
);
152 msg_info("%s: close %s", myname
, info
->path
);
154 myfree((char *) info
);
155 scan
->current
= parent
;
156 return (parent
? scan
: 0);
159 /* scan_dir_open - start directory scan */
161 SCAN_DIR
*scan_dir_open(const char *path
)
165 scan
= (SCAN_DIR
*) mymalloc(sizeof(*scan
));
167 scan_dir_push(scan
, path
);
171 /* scan_dir_next - find next entry */
173 char *scan_dir_next(SCAN_DIR
*scan
)
175 const char *myname
= "scan_dir_next";
176 SCAN_INFO
*info
= scan
->current
;
179 #define STREQ(x,y) (strcmp((x),(y)) == 0)
182 while ((dp
= readdir(info
->dir
)) != 0) {
183 if (STREQ(dp
->d_name
, ".") || STREQ(dp
->d_name
, "..")) {
185 msg_info("%s: skip %s", myname
, dp
->d_name
);
189 msg_info("%s: found %s", myname
, dp
->d_name
);
197 /* scan_dir_close - terminate directory scan */
199 SCAN_DIR
*scan_dir_close(SCAN_DIR
*scan
)
201 while (scan
->current
)
203 myfree((char *) scan
);