diff options
author | Andreas Gruenbacher <agruen@suse.de> | 2006-01-26 03:40:50 +0000 |
---|---|---|
committer | Andreas Gruenbacher <agruen@suse.de> | 2006-01-26 03:40:50 +0000 |
commit | f96155d58b601c1cc17a97566f9123af0fdeef24 (patch) | |
tree | 45467b92489ff3e3b80dbd76ac05cb942cdf396c /lib | |
parent | aff07add99f56ae67ac58cb334881d3197d97a21 (diff) | |
download | quilt-f96155d58b601c1cc17a97566f9123af0fdeef24.tar.gz |
- lib/backup-files.c: Stop using ftw and implement our own dir
walking: ftw is a portability nightmare. The foreachdir function
is based a proposal from Gary V. Vaughan <gary@gnu.org>, thanks!
Diffstat (limited to 'lib')
-rw-r--r-- | lib/backup-files.c | 85 | ||||
-rw-r--r-- | lib/ftw.c | 116 | ||||
-rw-r--r-- | lib/ftw.h | 23 |
3 files changed, 68 insertions, 156 deletions
diff --git a/lib/backup-files.c b/lib/backup-files.c index 79f3e55..f28e89c 100644 --- a/lib/backup-files.c +++ b/lib/backup-files.c @@ -1,8 +1,8 @@ /* File: backup-files.c - Copyright (C) 2003 Andreas Gruenbacher <agruen@suse.de> - SuSE Labs, SuSE Linux AG + Copyright (C) 2003, 2004, 2005, 2006 + Andreas Gruenbacher <agruen@suse.de>, SuSE Labs This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -40,7 +40,7 @@ #include <stdlib.h> #include <errno.h> #include <string.h> -#include <ftw.h> +#include <dirent.h> #if !defined(HAVE_MKSTEMP) && defined(HAVE_MKTEMP) # define mkstemp(x) creat(mktemp(x), 0600) @@ -57,7 +57,7 @@ int opt_nolinks, opt_touch; #define LINE_LENGTH 1024 -void +static void usage(void) { printf("Usage: %s [-B prefix] [-z suffix] [-f {file|-}] [-s] [-b|-r|-x] [-L] {file|-} ...\n" @@ -84,13 +84,13 @@ malloc_nofail(size_t size) { void *p = malloc(size); if (!p) { - fprintf(stderr, "%s\n", strerror(ENOMEM)); + perror(NULL); exit(1); } return p; } -void +static void create_parents(const char *filename) { struct stat st; @@ -120,7 +120,7 @@ out: free(fn); } -void +static void remove_parents(const char *filename) { char *fn = malloc_nofail(strlen(filename) + 1), *f; @@ -273,7 +273,7 @@ ensure_nolinks(const char *filename) return 0; } -int +static int process_file(const char *file) { char *backup = malloc_nofail( @@ -375,19 +375,72 @@ fail: return 1; } -int -walk(const char *path, const struct stat *stat, int flag) +static int +foreachdir_rec(const char *path, struct stat *st, + int (*walk)(const char *, const struct stat *)) +{ + DIR *dir; + struct dirent *dp; + char *p = NULL; + int failed = 0; + + if (!(dir = opendir(path))) + return walk(path, NULL); + while ((dp = readdir(dir))) { + char *p0 = p; + + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; + if (!(p = realloc(p, strlen(path) + 1 + + strlen(dp->d_name) + 1))) { + free(p0); + return -1; + } + sprintf(p, "%s/%s", path, dp->d_name); + if (lstat(p, st)) + continue; /* file has disappeared meanwhile */ + if (S_ISDIR(st->st_mode)) { + failed = foreachdir_rec(p, st, walk); + if (failed) + goto out; + } else { + failed = walk(p, st); + if (failed) + goto out; + } + } + if (closedir(dir) != 0) + failed = -1; + +out: + free(p); + return failed; +} + +static int +foreachdir(const char *path, + int (*walk)(const char *, const struct stat *)) +{ + struct stat st; + + if (lstat(path, &st)) + return walk(path, NULL); + return foreachdir_rec(path, &st, walk); +} + +static int +walk(const char *path, const struct stat *st) { size_t prefix_len=strlen(opt_prefix), suffix_len=strlen(opt_suffix); size_t len = strlen(path); char *p; int ret; - if (flag == FTW_DNR) { + if (!st) { perror(path); return 1; } - if (!S_ISREG(stat->st_mode)) + if (!S_ISREG(st->st_mode)) return 0; if (strncmp(opt_prefix, path, prefix_len)) return 0; /* prefix does not match */ @@ -493,14 +546,12 @@ main(int argc, char *argv[]) if (strcmp(argv[optind], "-") == 0) { char *dir = strdup(opt_prefix), *d = strrchr(dir, '/'); if (d) - *(d+1) = '\0'; + *d = '\0'; else d = "."; - status = ftw(dir, walk, 0); - /* An error here indicates a problem somewhere - * during the walk */ + status = foreachdir(dir, walk); if (status == -1) - perror("ftw"); + perror(dir); free(dir); } else diff --git a/lib/ftw.c b/lib/ftw.c deleted file mode 100644 index 8762194..0000000 --- a/lib/ftw.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Written by Jesper Juhl <jj@dif.dk> - released under the terms of the GPL - * - * Credit should be given to : - * R. Stevens author of "Advanced Programming in the UNIX Environment" - * since I have made heavy use of some of his example code. - * - */ - -/* To compile the test code: gcc -DTEST_FTW ftw.c */ - -#include "ftw.h" - -static int depth; -static char *path; - -static int trawl(char *path, ftw_func *f, int d) { - int retval; - struct stat sb; - struct dirent *dir; - DIR *dp; - char *p; - - if (depth == d) - return(0); - - if (lstat(path, &sb) == -1) - return(f(path, &sb, FTW_NS)); - - if (!S_ISDIR(sb.st_mode)) - return(f(path, &sb, FTW_F)); - - if ((retval = f(path, &sb, FTW_D)) != 0) - return(retval); - - p = path + strlen(path); - *p++ = '/'; - *p = '\0'; - - if ((dp = opendir(path)) == NULL) - return(f(path, &sb, FTW_DNR)); - - while ((dir = readdir(dp)) != NULL) { - if ((strncmp(dir->d_name, ".", 1) == 0) || - (strncmp(dir->d_name, "..", 2) == 0)) - continue; - - strcpy(p, dir->d_name); - depth++; - if ((retval = trawl(path, f, d)) != 0) - break; - depth--; - } - - p[-1] = '\0'; - - closedir(dp); - return(retval); -} - -int ftw(const char *directory, ftw_func *f, int d) { - int retval; - - if ((path = (char *)malloc(sysconf(_PC_PATH_MAX)+1)) == NULL) - return(-1); - - strcpy(path, directory); - depth = 0; - retval = trawl(path, f, d); - - free(path); - return(retval); -} - -#ifdef TEST_FTW -int foo(const char *file, struct stat *sb, int flag) { - - switch (flag) { - case FTW_F : - if (S_ISREG(sb->st_mode)) printf("%s is a regular file\n\n", file); - else if (S_ISBLK(sb->st_mode)) printf("%s is a block dev\n\n", file); - else if (S_ISCHR(sb->st_mode)) printf("%s is a char dev\n\n", file); - else if (S_ISFIFO(sb->st_mode)) printf("%s is a fifo\n\n", file); - else if (S_ISLNK(sb->st_mode)) printf("%s is a link\n\n", file); - break; - case FTW_D : - printf("%s is a directory\n\n", file); - break; - case FTW_NS : - printf("stat failed on %s\n\n", file); - break; - case FTW_DNR : - printf("%s is a directory which can't be read\n\n", file); - break; - default : - printf("%s is unknown\n\n", file); - break; - } - return(0); -} - -int main(int argc, char *argv[]) { - - if (argc == 2) { - ftw(argv[1], foo, 1); - exit(0); - } else if (argc > 2) { - ftw(argv[1], foo, atoi(argv[2])); - exit(0); - } else { - printf("usage %s <dirname> [depth]\n", argv[0]); - exit(1); - } -} -#endif - diff --git a/lib/ftw.h b/lib/ftw.h deleted file mode 100644 index 5e8f0cf..0000000 --- a/lib/ftw.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _FTW_H_ -#define _FTW_H_ - -#include <stdio.h> -#include <stdlib.h> -#include <dirent.h> -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> -#include <limits.h> - -#define FTW_F 1 -#define FTW_D 2 -#define FTW_DNR 3 -#define FTW_NS 4 - -/* This is a replacement for the FTW file traversal utility */ - -typedef int ftw_func(const char *file, const struct stat *sb, int flag); - -int ftw(const char *directory, ftw_func *f, int d); - -#endif /* _FTW_H_ */ |