| @@ -18,7 +18,6 @@ |
| 18 | 18 | | |
| 19 | 19 | | #include <stdlib.h> |
| 20 | 20 | | #include <string.h> |
| 21 | | − | #include <dirent.h> |
| 22 | 21 | | #include <sys/types.h> |
| 23 | 22 | | #include <sys/stat.h> |
| 24 | 23 | | #include <unistd.h> |
| @@ -28,7 +27,6 @@ |
| 28 | 27 | | #include "util.h" |
| 29 | 28 | | |
| 30 | 29 | | #define DNAME_CNT 512 |
| 31 | | − | #define FNAME_CNT 1024 |
| 32 | 30 | | #define FNAME_LEN 1024 |
| 33 | 31 | | |
| 34 | 32 | | void cleanup(); |
| @@ -161,7 +159,105 @@ end: |
| 161 | 159 | | return path; |
| 162 | 160 | | } |
| 163 | 161 | | |
| 164 | | − | int create_dir_rec(const char *path) { |
| 162 | + | int r_opendir(r_dir_t *rdir, const char *dirname) { |
| 163 | + | if (!rdir || !dirname || !*dirname) |
| 164 | + | return -1; |
| 165 | + | |
| 166 | + | if (!(rdir->dir = opendir(dirname))) { |
| 167 | + | rdir->name = NULL; |
| 168 | + | rdir->stack = NULL; |
| 169 | + | return -1; |
| 170 | + | } |
| 171 | + | |
| 172 | + | rdir->stcap = DNAME_CNT; |
| 173 | + | rdir->stack = (char**) s_malloc(rdir->stcap * sizeof(char*)); |
| 174 | + | rdir->stlen = 0; |
| 175 | + | |
| 176 | + | rdir->name = (char*) dirname; |
| 177 | + | rdir->d = 0; |
| 178 | + | |
| 179 | + | return 0; |
| 180 | + | } |
| 181 | + | |
| 182 | + | int r_closedir(r_dir_t *rdir) { |
| 183 | + | int ret = 0; |
| 184 | + | |
| 185 | + | if (!rdir) |
| 186 | + | return -1; |
| 187 | + | |
| 188 | + | if (rdir->stack) { |
| 189 | + | while (rdir->stlen > 0) |
| 190 | + | free(rdir->stack[--rdir->stlen]); |
| 191 | + | free(rdir->stack); |
| 192 | + | rdir->stack = NULL; |
| 193 | + | } |
| 194 | + | |
| 195 | + | if (rdir->dir) { |
| 196 | + | if (!(ret = closedir(rdir->dir))) |
| 197 | + | rdir->dir = NULL; |
| 198 | + | } |
| 199 | + | |
| 200 | + | if (rdir->d && rdir->name) { |
| 201 | + | free(rdir->name); |
| 202 | + | rdir->name = NULL; |
| 203 | + | } |
| 204 | + | |
| 205 | + | return ret; |
| 206 | + | } |
| 207 | + | |
| 208 | + | char* r_readdir(r_dir_t *rdir) { |
| 209 | + | size_t len; |
| 210 | + | char *filename; |
| 211 | + | struct dirent *dentry; |
| 212 | + | struct stat fstats; |
| 213 | + | |
| 214 | + | if (!rdir || !rdir->dir || !rdir->name) |
| 215 | + | return NULL; |
| 216 | + | |
| 217 | + | while (1) { |
| 218 | + | if (rdir->dir && (dentry = readdir(rdir->dir))) { |
| 219 | + | if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) |
| 220 | + | continue; |
| 221 | + | |
| 222 | + | len = strlen(rdir->name) + strlen(dentry->d_name) + 2; |
| 223 | + | filename = (char*) s_malloc(len); |
| 224 | + | snprintf(filename, len, "%s%s%s", rdir->name, |
| 225 | + | rdir->name[strlen(rdir->name)-1] == '/' ? "" : "/", |
| 226 | + | dentry->d_name); |
| 227 | + | |
| 228 | + | if (!stat(filename, &fstats) && S_ISDIR(fstats.st_mode)) { |
| 229 | + | /* put subdirectory on the stack */ |
| 230 | + | if (rdir->stlen == rdir->stcap) { |
| 231 | + | rdir->stcap *= 2; |
| 232 | + | rdir->stack = (char**) s_realloc(rdir->stack, |
| 233 | + | rdir->stcap * sizeof(char*)); |
| 234 | + | } |
| 235 | + | rdir->stack[rdir->stlen++] = filename; |
| 236 | + | continue; |
| 237 | + | } |
| 238 | + | return filename; |
| 239 | + | } |
| 240 | + | |
| 241 | + | if (rdir->stlen > 0) { |
| 242 | + | /* open next subdirectory */ |
| 243 | + | closedir(rdir->dir); |
| 244 | + | if (rdir->d) |
| 245 | + | free(rdir->name); |
| 246 | + | rdir->name = rdir->stack[--rdir->stlen]; |
| 247 | + | rdir->d = 1; |
| 248 | + | if (!(rdir->dir = opendir(rdir->name))) |
| 249 | + | warn("could not open directory: %s", rdir->name); |
| 250 | + | continue; |
| 251 | + | } |
| 252 | + | |
| 253 | + | /* no more entries */ |
| 254 | + | break; |
| 255 | + | } |
| 256 | + | |
| 257 | + | return NULL; |
| 258 | + | } |
| 259 | + | |
| 260 | + | int r_mkdir(const char *path) { |
| 165 | 261 | | char *dir, *d; |
| 166 | 262 | | struct stat stats; |
| 167 | 263 | | int err = 0; |
| @@ -202,82 +298,6 @@ int create_dir_rec(const char *path) { |
| 202 | 298 | | return err; |
| 203 | 299 | | } |
| 204 | 300 | | |
| 205 | | − | int fncmp(const void *a, const void *b) { |
| 206 | | − | return strcoll(*((char* const*) a), *((char* const*) b)); |
| 207 | | − | } |
| 208 | | − | |
| 209 | | − | char** read_dir_rec(const char *dirname) { |
| 210 | | − | int dcnt, didx, fcnt, fidx; |
| 211 | | − | char **dnames, **fnames, *filename; |
| 212 | | − | unsigned char first; |
| 213 | | − | size_t len; |
| 214 | | − | DIR *dir; |
| 215 | | − | struct dirent *dentry; |
| 216 | | − | struct stat fstats; |
| 217 | | − | |
| 218 | | − | if (!dirname) |
| 219 | | − | return NULL; |
| 220 | | − | |
| 221 | | − | dcnt = DNAME_CNT; |
| 222 | | − | didx = first = 1; |
| 223 | | − | dnames = (char**) s_malloc(dcnt * sizeof(char*)); |
| 224 | | − | dnames[0] = (char*) dirname; |
| 225 | | − | |
| 226 | | − | fcnt = FNAME_CNT; |
| 227 | | − | fidx = 0; |
| 228 | | − | fnames = (char**) s_malloc(fcnt * sizeof(char*)); |
| 229 | | − | |
| 230 | | − | while (didx > 0) { |
| 231 | | − | dirname = dnames[--didx]; |
| 232 | | − | if (!(dir = opendir(dirname))) { |
| 233 | | − | warn("could not open directory: %s", dirname); |
| 234 | | − | } else { |
| 235 | | − | while ((dentry = readdir(dir))) { |
| 236 | | − | if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) |
| 237 | | − | continue; |
| 238 | | − | |
| 239 | | − | len = strlen(dirname) + strlen(dentry->d_name) + 2; |
| 240 | | − | filename = (char*) s_malloc(len * sizeof(char)); |
| 241 | | − | snprintf(filename, len, "%s%s%s", dirname, |
| 242 | | − | dirname[strlen(dirname)-1] == '/' ? "" : "/", dentry->d_name); |
| 243 | | − | |
| 244 | | − | if (!stat(filename, &fstats) && S_ISDIR(fstats.st_mode)) { |
| 245 | | − | if (didx == dcnt) { |
| 246 | | − | dcnt *= 2; |
| 247 | | − | dnames = (char**) s_realloc(dnames, dcnt * sizeof(char*)); |
| 248 | | − | } |
| 249 | | − | dnames[didx++] = filename; |
| 250 | | − | } else { |
| 251 | | − | if (fidx + 1 == fcnt) { |
| 252 | | − | fcnt *= 2; |
| 253 | | − | fnames = (char**) s_realloc(fnames, fcnt * sizeof(char*)); |
| 254 | | − | } |
| 255 | | − | fnames[fidx++] = filename; |
| 256 | | − | } |
| 257 | | − | } |
| 258 | | − | closedir(dir); |
| 259 | | − | } |
| 260 | | − | |
| 261 | | − | if (!first) |
| 262 | | − | free((void*) dirname); |
| 263 | | − | else |
| 264 | | − | first = 0; |
| 265 | | − | } |
| 266 | | − | |
| 267 | | − | if (!fidx) { |
| 268 | | − | free(fnames); |
| 269 | | − | fnames = NULL; |
| 270 | | − | } else { |
| 271 | | − | if (fidx > 1) |
| 272 | | − | qsort(fnames, fidx, sizeof(char*), fncmp); |
| 273 | | − | fnames[fidx] = NULL; |
| 274 | | − | } |
| 275 | | − | |
| 276 | | − | free(dnames); |
| 277 | | − | |
| 278 | | − | return fnames; |
| 279 | | − | } |
| 280 | | − | |
| 281 | 301 | | char* readline(FILE *stream) { |
| 282 | 302 | | size_t len; |
| 283 | 303 | | char *buf, *s, *end; |