aboutsummaryrefslogtreecommitdiff
path: root/utility.c
diff options
context:
space:
mode:
Diffstat (limited to 'utility.c')
-rw-r--r--utility.c795
1 files changed, 390 insertions, 405 deletions
diff --git a/utility.c b/utility.c
index 369aa21f2..277e27c70 100644
--- a/utility.c
+++ b/utility.c
@@ -27,31 +27,30 @@
27#include <string.h> 27#include <string.h>
28#include <errno.h> 28#include <errno.h>
29#include <fcntl.h> 29#include <fcntl.h>
30//#include <sys/types.h>
31//#include <sys/stat.h>
32#include <dirent.h> 30#include <dirent.h>
33#include <time.h> 31#include <time.h>
34#include <utime.h> 32#include <utime.h>
33#include <sys/stat.h>
34#include <unistd.h>
35 35
36#if 0 36#if 0
37 37
38extern char * 38extern char *join_paths(char *buffer, const char *a, const char *b)
39join_paths(char * buffer, const char * a, const char * b)
40{ 39{
41 int length = 0; 40 int length = 0;
42 41
43 if ( a && *a ) { 42 if (a && *a) {
44 length = strlen(a); 43 length = strlen(a);
45 memcpy(buffer, a, length); 44 memcpy(buffer, a, length);
46 } 45 }
47 if ( b && *b ) { 46 if (b && *b) {
48 if ( length > 0 && buffer[length - 1] != '/' ) 47 if (length > 0 && buffer[length - 1] != '/')
49 buffer[length++] = '/'; 48 buffer[length++] = '/';
50 if ( *b == '/' ) 49 if (*b == '/')
51 b++; 50 b++;
52 strcpy(&buffer[length], b); 51 strcpy(&buffer[length], b);
53 } 52 }
54 return buffer; 53 return buffer;
55} 54}
56 55
57#endif 56#endif
@@ -61,73 +60,72 @@ join_paths(char * buffer, const char * a, const char * b)
61 60
62 61
63 62
64static CHUNK * chunkList; 63static CHUNK *chunkList;
65 64
66 65
67/* 66/*
68 * Return the standard ls-like mode string from a file mode. 67 * Return the standard ls-like mode string from a file mode.
69 * This is static and so is overwritten on each call. 68 * This is static and so is overwritten on each call.
70 */ 69 */
71const char * 70const char *modeString(int mode)
72modeString(int mode)
73{ 71{
74 static char buf[12]; 72 static char buf[12];
75 73
76 strcpy(buf, "----------"); 74 strcpy(buf, "----------");
77 75
78 /* 76 /*
79 * Fill in the file type. 77 * Fill in the file type.
80 */ 78 */
81 if (S_ISDIR(mode)) 79 if (S_ISDIR(mode))
82 buf[0] = 'd'; 80 buf[0] = 'd';
83 if (S_ISCHR(mode)) 81 if (S_ISCHR(mode))
84 buf[0] = 'c'; 82 buf[0] = 'c';
85 if (S_ISBLK(mode)) 83 if (S_ISBLK(mode))
86 buf[0] = 'b'; 84 buf[0] = 'b';
87 if (S_ISFIFO(mode)) 85 if (S_ISFIFO(mode))
88 buf[0] = 'p'; 86 buf[0] = 'p';
89#ifdef S_ISLNK 87#ifdef S_ISLNK
90 if (S_ISLNK(mode)) 88 if (S_ISLNK(mode))
91 buf[0] = 'l'; 89 buf[0] = 'l';
92#endif 90#endif
93#ifdef S_ISSOCK 91#ifdef S_ISSOCK
94 if (S_ISSOCK(mode)) 92 if (S_ISSOCK(mode))
95 buf[0] = 's'; 93 buf[0] = 's';
96#endif 94#endif
97 95
98 /* 96 /*
99 * Now fill in the normal file permissions. 97 * Now fill in the normal file permissions.
100 */ 98 */
101 if (mode & S_IRUSR) 99 if (mode & S_IRUSR)
102 buf[1] = 'r'; 100 buf[1] = 'r';
103 if (mode & S_IWUSR) 101 if (mode & S_IWUSR)
104 buf[2] = 'w'; 102 buf[2] = 'w';
105 if (mode & S_IXUSR) 103 if (mode & S_IXUSR)
106 buf[3] = 'x'; 104 buf[3] = 'x';
107 if (mode & S_IRGRP) 105 if (mode & S_IRGRP)
108 buf[4] = 'r'; 106 buf[4] = 'r';
109 if (mode & S_IWGRP) 107 if (mode & S_IWGRP)
110 buf[5] = 'w'; 108 buf[5] = 'w';
111 if (mode & S_IXGRP) 109 if (mode & S_IXGRP)
112 buf[6] = 'x'; 110 buf[6] = 'x';
113 if (mode & S_IROTH) 111 if (mode & S_IROTH)
114 buf[7] = 'r'; 112 buf[7] = 'r';
115 if (mode & S_IWOTH) 113 if (mode & S_IWOTH)
116 buf[8] = 'w'; 114 buf[8] = 'w';
117 if (mode & S_IXOTH) 115 if (mode & S_IXOTH)
118 buf[9] = 'x'; 116 buf[9] = 'x';
119 117
120 /* 118 /*
121 * Finally fill in magic stuff like suid and sticky text. 119 * Finally fill in magic stuff like suid and sticky text.
122 */ 120 */
123 if (mode & S_ISUID) 121 if (mode & S_ISUID)
124 buf[3] = ((mode & S_IXUSR) ? 's' : 'S'); 122 buf[3] = ((mode & S_IXUSR) ? 's' : 'S');
125 if (mode & S_ISGID) 123 if (mode & S_ISGID)
126 buf[6] = ((mode & S_IXGRP) ? 's' : 'S'); 124 buf[6] = ((mode & S_IXGRP) ? 's' : 'S');
127 if (mode & S_ISVTX) 125 if (mode & S_ISVTX)
128 buf[9] = ((mode & S_IXOTH) ? 't' : 'T'); 126 buf[9] = ((mode & S_IXOTH) ? 't' : 'T');
129 127
130 return buf; 128 return buf;
131} 129}
132 130
133 131
@@ -135,15 +133,14 @@ modeString(int mode)
135 * Return TRUE if a fileName is a directory. 133 * Return TRUE if a fileName is a directory.
136 * Nonexistant files return FALSE. 134 * Nonexistant files return FALSE.
137 */ 135 */
138BOOL 136int isDirectory(const char *name)
139isDirectory(const char * name)
140{ 137{
141 struct stat statBuf; 138 struct stat statBuf;
142 139
143 if (stat(name, &statBuf) < 0) 140 if (stat(name, &statBuf) < 0)
144 return FALSE; 141 return FALSE;
145 142
146 return S_ISDIR(statBuf.st_mode); 143 return S_ISDIR(statBuf.st_mode);
147} 144}
148 145
149 146
@@ -151,15 +148,14 @@ isDirectory(const char * name)
151 * Return TRUE if a filename is a block or character device. 148 * Return TRUE if a filename is a block or character device.
152 * Nonexistant files return FALSE. 149 * Nonexistant files return FALSE.
153 */ 150 */
154BOOL 151int isDevice(const char *name)
155isDevice(const char * name)
156{ 152{
157 struct stat statBuf; 153 struct stat statBuf;
158 154
159 if (stat(name, &statBuf) < 0) 155 if (stat(name, &statBuf) < 0)
160 return FALSE; 156 return FALSE;
161 157
162 return S_ISBLK(statBuf.st_mode) || S_ISCHR(statBuf.st_mode); 158 return S_ISBLK(statBuf.st_mode) || S_ISCHR(statBuf.st_mode);
163} 159}
164 160
165 161
@@ -169,102 +165,118 @@ isDevice(const char * name)
169 * error message output. (Failure is not indicted if the attributes cannot 165 * error message output. (Failure is not indicted if the attributes cannot
170 * be set.) 166 * be set.)
171 */ 167 */
172BOOL 168int
173copyFile( 169copyFile(
174 const char * srcName, 170 const char *srcName,
175 const char * destName, 171 const char *destName, int setModes, int followLinks)
176 BOOL setModes
177)
178{ 172{
179 int rfd; 173 int rfd;
180 int wfd; 174 int wfd;
181 int rcc; 175 int rcc;
182 char buf[BUF_SIZE]; 176 char buf[BUF_SIZE];
183 struct stat statBuf1; 177 struct stat statBuf1;
184 struct stat statBuf2; 178 struct stat statBuf2;
185 struct utimbuf times; 179 struct utimbuf times;
186 180
187 if (stat(srcName, &statBuf1) < 0) 181 if (stat(srcName, &statBuf1) < 0) {
188 { 182 perror(srcName);
189 perror(srcName); 183 return FALSE;
190 184 }
191 return FALSE;
192 }
193 185
194 if (stat(destName, &statBuf2) < 0) 186 if (stat(destName, &statBuf2) < 0) {
195 { 187 statBuf2.st_ino = -1;
196 statBuf2.st_ino = -1; 188 statBuf2.st_dev = -1;
197 statBuf2.st_dev = -1; 189 }
198 }
199 190
200 if ((statBuf1.st_dev == statBuf2.st_dev) && 191 if ((statBuf1.st_dev == statBuf2.st_dev) &&
201 (statBuf1.st_ino == statBuf2.st_ino)) 192 (statBuf1.st_ino == statBuf2.st_ino)) {
202 { 193 fprintf(stderr, "Copying file \"%s\" to itself\n", srcName);
203 fprintf(stderr, "Copying file \"%s\" to itself\n", srcName); 194 return FALSE;
195 }
204 196
205 return FALSE; 197 if (S_ISDIR(statBuf1.st_mode)) {
198 /* Make sure the directory is writable */
199 if (mkdir(destName, 0777777 ^ umask(0))) {
200 perror(destName);
201 return (FALSE);
206 } 202 }
207 203 } else if (S_ISFIFO(statBuf1.st_mode)) {
204 if (mkfifo(destName, 644)) {
205 perror(destName);
206 return (FALSE);
207 }
208 } else if (S_ISBLK(statBuf1.st_mode) || S_ISCHR(statBuf1.st_mode)) {
209 if (mknod(destName, 644, statBuf1.st_rdev)) {
210 perror(destName);
211 return (FALSE);
212 }
213 } else if (S_ISLNK(statBuf1.st_mode)) {
214 char *link_val;
215 int link_size;
216
217 link_val = (char *) alloca(PATH_MAX + 2);
218 link_size = readlink(srcName, link_val, PATH_MAX + 1);
219 if (link_size < 0) {
220 perror(srcName);
221 return (FALSE);
222 }
223 link_val[link_size] = '\0';
224 if (symlink(link_val, destName)) {
225 perror(srcName);
226 return (FALSE);
227 }
228 } else {
208 rfd = open(srcName, O_RDONLY); 229 rfd = open(srcName, O_RDONLY);
209 230 if (rfd < 0) {
210 if (rfd < 0) 231 perror(srcName);
211 { 232 return FALSE;
212 perror(srcName);
213
214 return FALSE;
215 } 233 }
216 234
217 wfd = creat(destName, statBuf1.st_mode); 235 wfd = creat(destName, statBuf1.st_mode);
218 236 if (wfd < 0) {
219 if (wfd < 0) 237 perror(destName);
220 { 238 close(rfd);
221 perror(destName); 239 return FALSE;
222 close(rfd);
223
224 return FALSE;
225 }
226
227 while ((rcc = read(rfd, buf, sizeof(buf))) > 0)
228 {
229 if (fullWrite(wfd, buf, rcc) < 0)
230 goto error_exit;
231 } 240 }
232 241
233 if (rcc < 0) 242 while ((rcc = read(rfd, buf, sizeof(buf))) > 0) {
234 { 243 if (fullWrite(wfd, buf, rcc) < 0)
235 perror(srcName);
236 goto error_exit; 244 goto error_exit;
237 } 245 }
246 if (rcc < 0) {
247 perror(srcName);
248 goto error_exit;
249 }
238 250
239 (void) close(rfd); 251 close(rfd);
240
241 if (close(wfd) < 0)
242 {
243 perror(destName);
244 252
245 return FALSE; 253 if (close(wfd) < 0) {
254 perror(destName);
255 return FALSE;
246 } 256 }
257 }
247 258
248 if (setModes) 259 if (setModes == TRUE) {
249 { 260 chmod(destName, statBuf1.st_mode);
250 (void) chmod(destName, statBuf1.st_mode); 261 if (followLinks == TRUE)
251 262 chown(destName, statBuf1.st_uid, statBuf1.st_gid);
252 (void) chown(destName, statBuf1.st_uid, statBuf1.st_gid); 263 else
264 lchown(destName, statBuf1.st_uid, statBuf1.st_gid);
253 265
254 times.actime = statBuf1.st_atime; 266 times.actime = statBuf1.st_atime;
255 times.modtime = statBuf1.st_mtime; 267 times.modtime = statBuf1.st_mtime;
256 268
257 (void) utime(destName, &times); 269 utime(destName, &times);
258 } 270 }
259 271
260 return TRUE; 272 return TRUE;
261 273
262 274
263error_exit: 275 error_exit:
264 close(rfd); 276 close(rfd);
265 close(wfd); 277 close(wfd);
266 278
267 return FALSE; 279 return FALSE;
268} 280}
269 281
270 282
@@ -273,25 +285,25 @@ error_exit:
273 * If the directory name is NULL, then the original fileName is returned. 285 * If the directory name is NULL, then the original fileName is returned.
274 * The built path is in a static area, and is overwritten for each call. 286 * The built path is in a static area, and is overwritten for each call.
275 */ 287 */
276const char * 288char *buildName(const char *dirName, const char *fileName)
277buildName(const char * dirName, const char * fileName)
278{ 289{
279 const char * cp; 290 const char *cp;
280 static char buf[PATH_LEN]; 291 static char buf[PATH_LEN];
281 292
282 if ((dirName == NULL) || (*dirName == '\0')) 293 if ((dirName == NULL) || (*dirName == '\0')) {
283 return fileName; 294 strcpy(buf, fileName);
295 return buf;
296 }
284 297
285 cp = strrchr(fileName, '/'); 298 cp = strrchr(fileName, '/');
286 299
287 if (cp) 300 if (cp)
288 fileName = cp + 1; 301 fileName = cp + 1;
289 302
290 strcpy(buf, dirName); 303 strcpy(buf, dirName);
291 strcat(buf, "/"); 304 strcat(buf, "/");
292 strcat(buf, fileName);
293 305
294 return buf; 306 return buf;
295} 307}
296 308
297 309
@@ -302,41 +314,33 @@ buildName(const char * dirName, const char * fileName)
302 * with an error message given. This does not handle spaces within 314 * with an error message given. This does not handle spaces within
303 * arguments correctly. 315 * arguments correctly.
304 */ 316 */
305BOOL 317int makeString( int argc, const char **argv, char *buf, int bufLen)
306makeString(
307 int argc,
308 const char ** argv,
309 char * buf,
310 int bufLen
311)
312{ 318{
313 int len; 319 int len;
314 320
315 while (argc-- > 0) 321 while (argc-- > 0) {
316 { 322 len = strlen(*argv);
317 len = strlen(*argv);
318 323
319 if (len >= bufLen) 324 if (len >= bufLen) {
320 { 325 fprintf(stderr, "Argument string too long\n");
321 fprintf(stderr, "Argument string too long\n");
322 326
323 return FALSE; 327 return FALSE;
324 } 328 }
325 329
326 strcpy(buf, *argv++); 330 strcpy(buf, *argv++);
327 331
328 buf += len; 332 buf += len;
329 bufLen -= len; 333 bufLen -= len;
330 334
331 if (argc) 335 if (argc)
332 *buf++ = ' '; 336 *buf++ = ' ';
333 337
334 bufLen--; 338 bufLen--;
335 } 339 }
336 340
337 *buf = '\0'; 341 *buf = '\0';
338 342
339 return TRUE; 343 return TRUE;
340} 344}
341 345
342 346
@@ -346,23 +350,22 @@ makeString(
346 * list of chunks which can be freed all at one time. You CAN NOT free 350 * list of chunks which can be freed all at one time. You CAN NOT free
347 * an individual chunk. 351 * an individual chunk.
348 */ 352 */
349char * 353char *getChunk(int size)
350getChunk(int size)
351{ 354{
352 CHUNK * chunk; 355 CHUNK *chunk;
353 356
354 if (size < CHUNK_INIT_SIZE) 357 if (size < CHUNK_INIT_SIZE)
355 size = CHUNK_INIT_SIZE; 358 size = CHUNK_INIT_SIZE;
356 359
357 chunk = (CHUNK *) malloc(size + sizeof(CHUNK) - CHUNK_INIT_SIZE); 360 chunk = (CHUNK *) malloc(size + sizeof(CHUNK) - CHUNK_INIT_SIZE);
358 361
359 if (chunk == NULL) 362 if (chunk == NULL)
360 return NULL; 363 return NULL;
361 364
362 chunk->next = chunkList; 365 chunk->next = chunkList;
363 chunkList = chunk; 366 chunkList = chunk;
364 367
365 return chunk->data; 368 return chunk->data;
366} 369}
367 370
368 371
@@ -371,19 +374,18 @@ getChunk(int size)
371 * The returned string cannot be individually freed, but can only be freed 374 * The returned string cannot be individually freed, but can only be freed
372 * with other strings when freeChunks is called. Returns NULL on failure. 375 * with other strings when freeChunks is called. Returns NULL on failure.
373 */ 376 */
374char * 377char *chunkstrdup(const char *str)
375chunkstrdup(const char * str)
376{ 378{
377 int len; 379 int len;
378 char * newStr; 380 char *newStr;
379 381
380 len = strlen(str) + 1; 382 len = strlen(str) + 1;
381 newStr = getChunk(len); 383 newStr = getChunk(len);
382 384
383 if (newStr) 385 if (newStr)
384 memcpy(newStr, str, len); 386 memcpy(newStr, str, len);
385 387
386 return newStr; 388 return newStr;
387} 389}
388 390
389 391
@@ -391,17 +393,15 @@ chunkstrdup(const char * str)
391 * Free all chunks of memory that had been allocated since the last 393 * Free all chunks of memory that had been allocated since the last
392 * call to this routine. 394 * call to this routine.
393 */ 395 */
394void 396void freeChunks(void)
395freeChunks(void)
396{ 397{
397 CHUNK * chunk; 398 CHUNK *chunk;
398 399
399 while (chunkList) 400 while (chunkList) {
400 { 401 chunk = chunkList;
401 chunk = chunkList; 402 chunkList = chunk->next;
402 chunkList = chunk->next; 403 free((char *) chunk);
403 free((char *) chunk); 404 }
404 }
405} 405}
406 406
407 407
@@ -411,27 +411,25 @@ freeChunks(void)
411 * The string is returned from a static buffer, and so is overwritten for 411 * The string is returned from a static buffer, and so is overwritten for
412 * each call. 412 * each call.
413 */ 413 */
414const char * 414const char *timeString(time_t timeVal)
415timeString(time_t timeVal)
416{ 415{
417 time_t now; 416 time_t now;
418 char * str; 417 char *str;
419 static char buf[26]; 418 static char buf[26];
420 419
421 time(&now); 420 time(&now);
422 421
423 str = ctime(&timeVal); 422 str = ctime(&timeVal);
424 423
425 strcpy(buf, &str[4]); 424 strcpy(buf, &str[4]);
426 buf[12] = '\0'; 425 buf[12] = '\0';
427 426
428 if ((timeVal > now) || (timeVal < now - 365*24*60*60L)) 427 if ((timeVal > now) || (timeVal < now - 365 * 24 * 60 * 60L)) {
429 { 428 strcpy(&buf[7], &str[20]);
430 strcpy(&buf[7], &str[20]); 429 buf[11] = '\0';
431 buf[11] = '\0'; 430 }
432 }
433 431
434 return buf; 432 return buf;
435} 433}
436 434
437 435
@@ -445,88 +443,81 @@ timeString(time_t timeVal)
445 * \c quotes character c 443 * \c quotes character c
446 * Adapted from code written by Ingo Wilken. 444 * Adapted from code written by Ingo Wilken.
447 */ 445 */
448BOOL 446int match(const char *text, const char *pattern)
449match(const char * text, const char * pattern)
450{ 447{
451 const char * retryPat; 448 const char *retryPat;
452 const char * retryText; 449 const char *retryText;
453 int ch; 450 int ch;
454 BOOL found; 451 int found;
455 452
456 retryPat = NULL; 453 retryPat = NULL;
457 retryText = NULL; 454 retryText = NULL;
458 455
459 while (*text || *pattern) 456 while (*text || *pattern) {
460 { 457 ch = *pattern++;
461 ch = *pattern++; 458
462 459 switch (ch) {
463 switch (ch) 460 case '*':
464 { 461 retryPat = pattern;
465 case '*': 462 retryText = text;
466 retryPat = pattern; 463 break;
467 retryText = text; 464
468 break; 465 case '[':
469 466 found = FALSE;
470 case '[': 467
471 found = FALSE; 468 while ((ch = *pattern++) != ']') {
472 469 if (ch == '\\')
473 while ((ch = *pattern++) != ']') 470 ch = *pattern++;
474 { 471
475 if (ch == '\\') 472 if (ch == '\0')
476 ch = *pattern++; 473 return FALSE;
477 474
478 if (ch == '\0') 475 if (*text == ch)
479 return FALSE; 476 found = TRUE;
480 477 }
481 if (*text == ch) 478
482 found = TRUE; 479 if (!found) {
483 } 480 pattern = retryPat;
484 481 text = ++retryText;
485 if (!found) 482 }
486 { 483
487 pattern = retryPat; 484 /* fall into next case */
488 text = ++retryText; 485
489 } 486 case '?':
490 487 if (*text++ == '\0')
491 /* fall into next case */ 488 return FALSE;
492 489
493 case '?': 490 break;
494 if (*text++ == '\0') 491
495 return FALSE; 492 case '\\':
496 493 ch = *pattern++;
497 break; 494
498 495 if (ch == '\0')
499 case '\\': 496 return FALSE;
500 ch = *pattern++; 497
501 498 /* fall into next case */
502 if (ch == '\0') 499
503 return FALSE; 500 default:
504 501 if (*text == ch) {
505 /* fall into next case */ 502 if (*text)
506 503 text++;
507 default: 504 break;
508 if (*text == ch) 505 }
509 { 506
510 if (*text) 507 if (*text) {
511 text++; 508 pattern = retryPat;
512 break; 509 text = ++retryText;
513 } 510 break;
514 511 }
515 if (*text) 512
516 { 513 return FALSE;
517 pattern = retryPat;
518 text = ++retryText;
519 break;
520 }
521
522 return FALSE;
523 }
524
525 if (pattern == NULL)
526 return FALSE;
527 } 514 }
528 515
529 return TRUE; 516 if (pattern == NULL)
517 return FALSE;
518 }
519
520 return TRUE;
530} 521}
531 522
532 523
@@ -535,27 +526,25 @@ match(const char * text, const char * pattern)
535 * This does multiple writes as necessary. 526 * This does multiple writes as necessary.
536 * Returns the amount written, or -1 on an error. 527 * Returns the amount written, or -1 on an error.
537 */ 528 */
538int 529int fullWrite(int fd, const char *buf, int len)
539fullWrite(int fd, const char * buf, int len)
540{ 530{
541 int cc; 531 int cc;
542 int total; 532 int total;
543 533
544 total = 0; 534 total = 0;
545 535
546 while (len > 0) 536 while (len > 0) {
547 { 537 cc = write(fd, buf, len);
548 cc = write(fd, buf, len);
549 538
550 if (cc < 0) 539 if (cc < 0)
551 return -1; 540 return -1;
552 541
553 buf += cc; 542 buf += cc;
554 total+= cc; 543 total += cc;
555 len -= cc; 544 len -= cc;
556 } 545 }
557 546
558 return total; 547 return total;
559} 548}
560 549
561 550
@@ -565,30 +554,28 @@ fullWrite(int fd, const char * buf, int len)
565 * Returns the amount read, or -1 on an error. 554 * Returns the amount read, or -1 on an error.
566 * A short read is returned on an end of file. 555 * A short read is returned on an end of file.
567 */ 556 */
568int 557int fullRead(int fd, char *buf, int len)
569fullRead(int fd, char * buf, int len)
570{ 558{
571 int cc; 559 int cc;
572 int total; 560 int total;
573 561
574 total = 0; 562 total = 0;
575 563
576 while (len > 0) 564 while (len > 0) {
577 { 565 cc = read(fd, buf, len);
578 cc = read(fd, buf, len);
579 566
580 if (cc < 0) 567 if (cc < 0)
581 return -1; 568 return -1;
582 569
583 if (cc == 0) 570 if (cc == 0)
584 break; 571 break;
585 572
586 buf += cc; 573 buf += cc;
587 total+= cc; 574 total += cc;
588 len -= cc; 575 len -= cc;
589 } 576 }
590 577
591 return total; 578 return total;
592} 579}
593 580
594 581
@@ -598,84 +585,82 @@ fullRead(int fd, char * buf, int len)
598 * by the fileAction and dirAction function pointers). 585 * by the fileAction and dirAction function pointers).
599 */ 586 */
600int 587int
601recursiveAction( const char *fileName, BOOL recurse, BOOL followLinks, 588recursiveAction(const char *fileName, int recurse, int followLinks,
602 int (*fileAction)(const char* fileName), 589 int (*fileAction) (const char *fileName),
603 int (*dirAction)(const char* fileName)) 590 int (*dirAction) (const char *fileName))
604{ 591{
605 int status; 592 int status;
606 struct stat statbuf; 593 struct stat statbuf;
607 struct dirent* next; 594 struct dirent *next;
608
609 if (!recurse && S_ISDIR(statbuf.st_mode)) {
610 if (dirAction==NULL)
611 return(TRUE);
612 else
613 return(dirAction(fileName));
614 } else {
615 if (fileAction==NULL)
616 return(TRUE);
617 else
618 return(fileAction(fileName));
619 }
620 595
621 if (followLinks) 596 if (followLinks)
622 status = stat(fileName, &statbuf);
623 else
624 status = lstat(fileName, &statbuf); 597 status = lstat(fileName, &statbuf);
625 598 else
599 status = stat(fileName, &statbuf);
626 if (status < 0) { 600 if (status < 0) {
627 perror(fileName); 601 perror(fileName);
628 return( FALSE); 602 return (FALSE);
603 }
604
605 if (recurse == FALSE) {
606 if (S_ISDIR(statbuf.st_mode)) {
607 if (dirAction == NULL)
608 return (TRUE);
609 else
610 return (dirAction(fileName));
611 } else {
612 if (fileAction == NULL)
613 return (TRUE);
614 else
615 return (fileAction(fileName));
616 }
629 } 617 }
630 618
631 if (S_ISDIR(statbuf.st_mode)) { 619 if (S_ISDIR(statbuf.st_mode)) {
632 DIR *dir; 620 DIR *dir;
621 fprintf(stderr, "Dir: %s\n", fileName);
633 dir = opendir(fileName); 622 dir = opendir(fileName);
634 if (!dir) { 623 if (!dir) {
635 perror(fileName); 624 perror(fileName);
636 return(FALSE); 625 return (FALSE);
626 }
627 if (dirAction != NULL) {
628 status = dirAction(fileName);
629 if (status == FALSE) {
630 perror("cp");
631 return (FALSE);
632 }
637 } 633 }
638 while ((next = readdir (dir)) != NULL) { 634 while ((next = readdir(dir)) != NULL) {
639 char nextFile[NAME_MAX]; 635 char nextFile[NAME_MAX];
640 if ( (strcmp(next->d_name, "..") == 0) || (strcmp(next->d_name, ".") == 0) ) { 636 if ((strcmp(next->d_name, "..") == 0)
641 continue; 637 || (strcmp(next->d_name, ".") == 0)) {
642 } 638 continue;
643 sprintf(nextFile, "%s/%s", fileName, next->d_name); 639 }
644 status = recursiveAction(nextFile, TRUE, followLinks, fileAction, dirAction); 640 sprintf(nextFile, "%s/%s", fileName, next->d_name);
645 if (status < 0) { 641 status =
646 closedir(dir); 642 recursiveAction(nextFile, TRUE, followLinks, fileAction,
647 return(FALSE); 643 dirAction);
648 } 644 if (status < 0) {
645 closedir(dir);
646 return (FALSE);
647 }
649 } 648 }
650 status = closedir (dir); 649 status = closedir(dir);
651 if (status < 0) { 650 if (status < 0) {
652 perror(fileName); 651 perror(fileName);
653 return( FALSE); 652 return (FALSE);
654 } 653 }
655 if (dirAction==NULL) 654 } else {
656 return(TRUE); 655 fprintf(stderr, "File: %s\n", fileName);
657 else 656 if (fileAction == NULL)
658 return(dirAction(fileName)); 657 return (TRUE);
659 }
660 else {
661 if (fileAction==NULL)
662 return(TRUE);
663 else 658 else
664 return(fileAction(fileName)); 659 return (fileAction(fileName));
665 } 660 }
661 return (TRUE);
666} 662}
667 663
668 664
669 665
670/* END CODE */ 666/* END CODE */
671
672
673
674
675
676
677
678
679
680
681