Krolyxon
Commit a90bd1c

Branches

Refs →

nsxiva90bd1c

Refactored recursive directory util functions

Author
Bert
Date
2011-04-08 10:23 +0200
Parent
e999688
Commit
a90bd1c833b3475e434bd2de95ab9dd0347f1780

+139 −94

4 files changed

  1. M Makefile +1 −1
  2. M main.c +24 −12
  3. M util.c +99 −79
  4. M util.h +15 −2
M Makefile View
@@ -1,6 +1,6 @@
11 all: sxiv
22
3−VERSION=git-20110407
3+VERSION=git-20110408
44
55 CC?=gcc
66 PREFIX?=/usr/local
M main.c View
@@ -92,11 +92,15 @@ int load_image(int new) {
9292 return ret;
9393 }
9494
95+int fncmp(const void *a, const void *b) {
96+ return strcoll(*((char* const*) a), *((char* const*) b));
97+}
98+
9599 int main(int argc, char **argv) {
96− int i, j;
100+ int i, start;
97101 const char *filename;
98− char **fnames;
99102 struct stat fstats;
103+ r_dir_t dir;
100104
101105 parse_options(argc, argv);
102106
@@ -121,18 +125,26 @@ int main(int argc, char **argv) {
121125 } else {
122126 for (i = 0; i < options->filecnt; ++i) {
123127 filename = options->filenames[i];
124− if (!stat(filename, &fstats) && S_ISDIR(fstats.st_mode)) {
125− if (options->recursive && (fnames = read_dir_rec(filename))) {
126− for (j = 0; fnames[j]; ++j) {
127− if (!check_append(fnames[j]))
128− free(fnames[j]);
129− }
130− free(fnames);
131− } else {
128+
129+ if (stat(filename, &fstats) || !S_ISDIR(fstats.st_mode)) {
130+ check_append(filename);
131+ } else {
132+ if (!options->recursive) {
132133 warn("ignoring directory: %s", filename);
134+ continue;
133135 }
134− } else {
135− check_append(filename);
136+ if (r_opendir(&dir, filename)) {
137+ warn("could not open directory: %s", filename);
138+ continue;
139+ }
140+ start = fileidx;
141+ while ((filename = r_readdir(&dir))) {
142+ if (!check_append(filename))
143+ free((void*) filename);
144+ }
145+ r_closedir(&dir);
146+ if (fileidx - start > 1)
147+ qsort(filenames + start, fileidx - start, sizeof(char*), fncmp);
136148 }
137149 }
138150 }
M util.c View
@@ -18,7 +18,6 @@
1818
1919 #include <stdlib.h>
2020 #include <string.h>
21−#include <dirent.h>
2221 #include <sys/types.h>
2322 #include <sys/stat.h>
2423 #include <unistd.h>
@@ -28,7 +27,6 @@
2827 #include "util.h"
2928
3029 #define DNAME_CNT 512
31−#define FNAME_CNT 1024
3230 #define FNAME_LEN 1024
3331
3432 void cleanup();
@@ -161,7 +159,105 @@ end:
161159 return path;
162160 }
163161
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) {
165261 char *dir, *d;
166262 struct stat stats;
167263 int err = 0;
@@ -202,82 +298,6 @@ int create_dir_rec(const char *path) {
202298 return err;
203299 }
204300
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−
281301 char* readline(FILE *stream) {
282302 size_t len;
283303 char *buf, *s, *end;
M util.h View
@@ -21,6 +21,7 @@
2121
2222 #include <stdio.h>
2323 #include <stdarg.h>
24+#include <dirent.h>
2425
2526 #define ABS(a) ((a) < 0 ? (-(a)) : (a))
2627 #define MIN(a,b) ((a) < (b) ? (a) : (b))
@@ -35,6 +36,16 @@
3536 (tv)->tv_usec = (ts)->tv_nsec / 1000; \
3637 }
3738
39+typedef struct {
40+ DIR *dir;
41+ char *name;
42+ int d;
43+
44+ char **stack;
45+ int stcap;
46+ int stlen;
47+} r_dir_t;
48+
3849 void* s_malloc(size_t);
3950 void* s_realloc(void*, size_t);
4051
@@ -45,8 +56,10 @@ void size_readable(float*, const char**);
4556
4657 char* absolute_path(const char*);
4758
48−int create_dir_rec(const char*);
49−char** read_dir_rec(const char*);
59+int r_opendir(r_dir_t*, const char*);
60+int r_closedir(r_dir_t*);
61+char* r_readdir(r_dir_t*);
62+int r_mkdir(const char *);
5063
5164 char* readline(FILE*);
5265