aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/recurse.c
diff options
context:
space:
mode:
authorDavid M. Syzdek <david@syzdek.net>2009-02-07 17:18:10 -0900
committerDavid M. Syzdek <david@syzdek.net>2009-02-07 17:18:10 -0900
commit257433b920763bceab0f8c84583a280e13af574c (patch)
tree2460add49d4bff8b4928caf98369ff3f478759a2 /src/recurse.c
parent0079087c80ee8c7d4920b5620af1005873bf9b96 (diff)
downloaddmstools-257433b920763bceab0f8c84583a280e13af574c.tar.gz
dmstools-257433b920763bceab0f8c84583a280e13af574c.tar.bz2
dmstools-257433b920763bceab0f8c84583a280e13af574c.tar.xz
dmstools-257433b920763bceab0f8c84583a280e13af574c.zip
Updating algorithm for directory scanning.
Diffstat (limited to 'src/recurse.c')
-rw-r--r--src/recurse.c397
1 files changed, 250 insertions, 147 deletions
diff --git a/src/recurse.c b/src/recurse.c
index 8a1c0cc..959a141 100644
--- a/src/recurse.c
+++ b/src/recurse.c
@@ -1,7 +1,54 @@
1/* 1/*
2 * Recursively list files in a directory. 2 *
3 * DMS Tools and Utilities
4 * Copyright (C) 2008 David M. Syzdek <david@syzdek.net>.
5 *
6 * @SYZDEK_LICENSE_HEADER_START@
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License Version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 * @SYZDEK_LICENSE_HEADER_END@
3 */ 22 */
23/**
24 * @file src/recurse.c simple recursive directory listing utility
25 */
26/*
27 * Simple Build:
28 * gcc -W -Wall -O2 -c recurse.c
29 * gcc -W -Wall -O2 -o recurse recurse.o
30 *
31 * GNU Libtool Build:
32 * libtool --mode=compile gcc -W -Wall -g -O2 -c recurse.c
33 * libtool --mode=link gcc -W -Wall -g -O2 -o recurse recurse.lo
34 *
35 * GNU Libtool Install:
36 * libtool --mode=install install -c recurse /usr/local/bin/recurse
37 *
38 * GNU Libtool Clean:
39 * libtool --mode=clean rm -f recurse.lo recurse
40 */
41#define _DMSTOOLS_SRC_RECURSE_C 1
4 42
43///////////////
44// //
45// Headers //
46// //
47///////////////
48
49#ifdef HAVE_COMMON_H
50#include "common.h"
51#endif
5 52
6#include <stdio.h> 53#include <stdio.h>
7#include <stdlib.h> 54#include <stdlib.h>
@@ -11,6 +58,15 @@
11#include <sys/stat.h> 58#include <sys/stat.h>
12#include <dirent.h> 59#include <dirent.h>
13 60
61///////////////////
62// //
63// Definitions //
64// //
65///////////////////
66
67#ifndef PACKAGE_BUGREPORT
68#define PACKAGE_BUGREPORT "david@syzdek.net"
69#endif
14#ifndef PACKAGE_NAME 70#ifndef PACKAGE_NAME
15#define PACKAGE_NAME "Directory Recusring Tool" 71#define PACKAGE_NAME "Directory Recusring Tool"
16#endif 72#endif
@@ -29,34 +85,48 @@
29#define MY_OPT_LINKS 0x20 85#define MY_OPT_LINKS 0x20
30#define MY_OPT_QUIET 0x40 86#define MY_OPT_QUIET 0x40
31 87
32//typedef struct recurse_data Recurse;
33//struct recurse_data
34//{
35// char **
36//};
37 88
89//////////////////
90// //
91// Prototypes //
92// //
93//////////////////
38 94
39int main(int argc, char * argv[]); 95int main(int argc, char * argv[]);
96
40void my_version(void); 97void my_version(void);
98
41void my_usage(void); 99void my_usage(void);
42int recurse_directory(int * lenp, char *** listp, int opts);
43int recurse_list(const char * src, int opts);
44 100
101int my_work(const char * file, void * data);
45 102
103int recurse_directory(char * origin, int opts, void * data,
104 int (*func)(const char * file, int opts, void * data));
105
106int recurse_file(const char * file, int opts, void * data,
107 int (*func)(const char * file, int opts, void * data), unsigned * countp,
108 char *** queuep, unsigned * sizep);
109
110
111/////////////////
112// //
113// Functions //
114// //
115/////////////////
46 116
47int main(int argc, char * argv[]) 117int main(int argc, char * argv[])
48{ 118{
49 int c; 119 int c;
50 int i; 120 int i;
51 int err; 121 //int err;
52 int opts; 122 int opts;
53 int option_index; 123 int option_index;
54 int len; 124 int len;
55 void * ptr; 125 //void * ptr;
56 char ** list; 126 char ** list;
57 127
58 static char short_options[] = "achLqrvV"; 128 static char short_options[] = "acfhLqrvV";
59 static struct option long_options[] = 129 static struct option long_options[] =
60 { 130 {
61 {"help", no_argument, 0, 'h'}, 131 {"help", no_argument, 0, 'h'},
62 {"quiet", no_argument, 0, 'q'}, 132 {"quiet", no_argument, 0, 'q'},
@@ -123,42 +193,20 @@ int main(int argc, char * argv[])
123 }; 193 };
124 194
125 for(i = optind; i < argc; i++) 195 for(i = optind; i < argc; i++)
126 { 196 switch (recurse_directory(argv[i], opts, NULL, NULL))
127/*
128 len++;
129 if (!(ptr = realloc(list, (sizeof(char *)*len))))
130 {
131 fprintf(stderr, "out of virtual memory\n");
132 for(i = 0; i < (len-1); i++)
133 free(list[0]);
134 free(list);
135 return(1);
136 };
137 list = ptr;
138 if (!(list[len-1] = strdup(argv[i])))
139 { 197 {
140 fprintf(stderr, "out of virtual memory\n"); 198 case -1: return(1);
141 for(i = 0; i < (len-1); i++) 199 case 0: break;
142 free(list[0]); 200 default:
143 free(list); 201 if (!(opts & MY_OPT_CONTINUE))
144 return(1); 202 return(1);
203 break;
145 }; 204 };
146*/ 205 return(0);
147 if ((recurse_list(argv[i], opts)))
148 return(1);
149 };
150
151 err = recurse_list(&len, &list, opts);
152
153 for(i = 0; i < len; i++)
154 free(list[i]);
155 free(list);
156
157 return(err);
158} 206}
159 207
160 208
161/* displays usage */ 209// displays usage
162void my_usage(void) 210void my_usage(void)
163{ 211{
164 printf("Usage: %s [OPTIONS] file1 file2 ... fileN\n", PROGRAM_NAME); 212 printf("Usage: %s [OPTIONS] file1 file2 ... fileN\n", PROGRAM_NAME);
@@ -194,137 +242,192 @@ void my_version(void)
194} 242}
195 243
196 244
197int recurse_directory(int * lenp, char *** listp, int opts) 245int recurse_directory(char * origin, int opts, void * data,
246 int (*func)(const char * file, int opts, void * data))
198{ 247{
199 int err; 248 int err;
200 DIR * d; 249 DIR * d;
201 void * ptr;
202 char * dir;
203 char * file; 250 char * file;
204 size_t dir_len; 251 char ** queue;
205 size_t file_len; 252 void * ptr;
206 struct stat sb; 253 size_t len_dir;
254 size_t len_file;
255 unsigned size;
256 unsigned count;
207 struct dirent * dp; 257 struct dirent * dp;
208 258
209 // points to directory name 259 size = 0;
210 if (!(dir = (*listp)[(*lenp)-1])) 260 count = 0;
211 return(0); 261 ptr = NULL;
212 //(*listp)[(*lenp)-1] = NULL; 262 queue = NULL;
213 //(*lenp)--; 263
214 264 // seeds queue with first file/directory
215 // opens directory for reading 265 if ((err = recurse_file(origin, opts, data, func, &count, &queue, &size)))
216 if (!(d = opendir(dir))) 266 return(err);
217 {
218 if (opts & MY_OPT_QUIET)
219 fprintf(stderr, "%s: %s, %s\n", PROGRAM_NAME, dir, strerror(errno) );
220 free(dir);
221 (*listp)[(*lenp)-1] = NULL;
222 if (!(opts & MY_OPT_CONTINUE))
223 return(0);
224 };
225 267
226 // loops through directory 268 if (!(opts & MY_OPT_RECURSE))
227 for(dp = readdir(d); dp; dp = readdir(d))
228 { 269 {
229 // skips hidden files, current directory, and parent 270 if (queue)
230 if (dp->d_name[0] == '.')
231 { 271 {
232 if (dp->d_name[1] == '\0') 272 free(queue[0]);
233 continue; 273 free(queue);
234 if ( (dp->d_name[1] == '.') && (dp->d_name[2] == '\0') )
235 continue;
236 if (!(opts & MY_OPT_HIDDEN))
237 continue;
238 }; 274 };
275 return(0);
276 };
239 277
240 // builds file name 278 while(count)
241 dir_len = strlen(dir); 279 {
242 file_len = strlen(dp->d_name); 280 if (opts & MY_OPT_VERBOSE)
243 if (!(file = malloc(sizeof(char) * (dir_len + file_len + 2)))) 281 printf("%s\n", queue[count-1]);
282
283 // opens directory for processing
284 if (!(d = opendir(queue[count-1])))
244 { 285 {
245 fprintf(stderr, "%s: out of virtual memory\n", PROGRAM_NAME); 286 if ( ((!(opts & MY_OPT_QUIET))&&(opts & MY_OPT_CONTINUE)) || (!(opts & MY_OPT_CONTINUE)) )
246 free(dir); 287 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, queue[count-1], strerror(errno));
247 return(1); 288 if (!(opts & MY_OPT_CONTINUE))
289 return(1);
248 }; 290 };
249 strcpy(&file[0], dir); 291
250 strcpy(&file[dir_len], "/"); 292 len_dir = strlen(queue[count-1]);
251 strcpy(&file[dir_len+1], dp->d_name); 293
252 file[dir_len+file_len+1] = '\0'; 294 for(dp = readdir(d); dp; dp = readdir(d))
253
254 // retrieves file information
255 if ((opts & MY_OPT_LINKS))
256 err = stat(file, &sb);
257 else
258 err = lstat(file, &sb);
259 if (err == -1)
260 if (opts & MY_OPT_QUIET)
261 fprintf(stderr, "%s: %s, %s\n", PROGRAM_NAME, file, strerror(errno) );
262
263 // checks file type
264 switch(sb.st_mode & (S_IFDIR|S_IFREG|S_IFLNK))
265 { 295 {
266 case S_IFDIR: 296 len_file = strlen(dp->d_name);
267 if (!(ptr = realloc(*listp, sizeof(char *) * ((*lenp)+1)))) 297 if (!(file = malloc(sizeof(char) * (len_dir + len_file + 2))))
298 {
299 fprintf(stderr, "%s: out of virtual memory\n", PROGRAM_NAME);
300 return(-1);
301 };
302 sprintf(file, "%s/%s", queue[count-1], dp->d_name);
303
304 if ( (dp->d_name[0] == '.') && (opts & MY_OPT_HIDDEN) )
305 {
306 if ( (dp->d_name[1] != '/') &&
307 (dp->d_name[1] != '\0') &&
308 (dp->d_name[1] != '.') )
268 { 309 {
269 fprintf(stderr, "%s: out of virtual memory\n", PROGRAM_NAME); 310 switch (err = recurse_file(file, opts, data, func, &count, &queue, &size))
270 free(dir); 311 {
271 free(file); 312 case -1:
272 closedir(d); 313 free(file);
273 return(1); 314 closedir(d);
315 return(1);
316 case 0:
317 free(file);
318 break;
319 default:
320 free(file);
321 if (!(opts & MY_OPT_CONTINUE))
322 {
323 closedir(d);
324 return(1);
325 };
326 break;
327 };
274 }; 328 };
275 *listp = ptr; 329 }
276 (*listp)[(*lenp)] = file; 330 else if (dp->d_name[0] != '.')
277 (*lenp)++; 331 {
278 printf("%s\n", file); 332 switch (err = recurse_file(file, opts, data, func, &count, &queue, &size))
279 break; 333 {
280 case S_IFREG: 334 case -1:
281 //if (!(opts & MY_OPT_QUIET)) 335 free(file);
282 printf("%s\n", file); 336 closedir(d);
283 free(file); 337 return(1);
284 break; 338 case 0:
285 //case S_IFLNK: 339 free(file);
286 // free(file); 340 break;
287 // break; 341 default:
288 default: 342 free(file);
289 //if (!( (opts & MY_OPT_QUIET) && (opts & MY_OPT_CONTINUE) )) 343 if (!(opts & MY_OPT_CONTINUE))
290 // fprintf(stderr, "%s: %s: invalid file type\n", PROGRAM_NAME, file); 344 {
291 free(file); 345 closedir(d);
292 //if (!(opts & MY_OPT_CONTINUE)) 346 return(1);
293 //{ 347 };
294 // closedir(d); 348 break;
295 // return(1); 349 };
296 //}; 350 };
297 break;
298 }; 351 };
299 };
300 352
301 closedir(d); 353 // closes directory and removes from queue
354 closedir(d);
355 count--;
356 free(queue[count]);
357 };
302 358
303 free(dir); 359 free(queue);
304 360
305 return(0); 361 return(0);
306} 362}
307 363
308 364
309int recurse_list(const char * src, int opts) 365int recurse_file(const char * file, int opts, void * data,
366 int (*func)(const char * file, int opts, void * data), unsigned * countp,
367 char *** queuep, unsigned * sizep)
310{ 368{
311 int len; 369 int err;
312 char ** list; 370 void * ptr;
313 371 unsigned u;
314 len = 0; 372 struct stat sb;
315 list = NULL; 373
316 374 if (opts & MY_OPT_LINKS)
317 while(len > 0) 375 err = stat(file, &sb);
376 else
377 err = lstat(file, &sb);
378 if (err == -1)
379 {
380 if ( ((!(opts & MY_OPT_QUIET))&&(opts & MY_OPT_CONTINUE)) || (!(opts & MY_OPT_CONTINUE)) )
381 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, file, strerror(errno));
382 return(1);
383 };
384 switch(sb.st_mode & (S_IFDIR|S_IFREG|S_IFLNK))
318 { 385 {
319 printf("%s\n", list[len-1]); 386 case S_IFDIR:
320 //if ((recurse_directory(lenp, listp, opts))) 387 // adjust size of array
321 // return(1); 388 if (*countp >= *sizep)
322 len--; 389 {
323 if (list[len]) 390 *sizep += 20;
324 free(list[len]); 391 if (!(ptr = realloc(*queuep, sizeof(char *) * (*sizep))))
325 list[len] = NULL; 392 {
393 fprintf(stderr, "%s: out of virtual memory\n", PROGRAM_NAME);
394 return(-1);
395 };
396 *queuep = ptr;
397 };
398
399 // copy path name
400 if (!(ptr = strdup(file)))
401 {
402 fprintf(stderr, "%s: out of virtual memory\n", PROGRAM_NAME);
403 return(-1);
404 };
405
406 // insert path name at head of array
407 for(u = (*countp); u > 0; u--)
408 (*queuep)[u] = (*queuep)[u-1];
409 (*queuep)[0] = ptr;
410 (*countp)++;
411 break;
412
413 case S_IFLNK: // ignore symbolic links
414 break;
415
416 case S_IFREG:
417 if (opts & MY_OPT_VERBOSE)
418 printf("%s\n", file);
419 if (func)
420 return(func(file, opts, data));
421 break;
422
423 default:
424 if ( ((!(opts & MY_OPT_QUIET))&&(opts & MY_OPT_CONTINUE)) || (!(opts & MY_OPT_CONTINUE)) )
425 fprintf(stderr, "%s: %s: unknown file type\n", PROGRAM_NAME, file);
426 return(1);
427 break;
326 }; 428 };
429
327 return(0); 430 return(0);
328} 431}
329 432
330/* end of source file */ 433// end of source code