diff options
author | Andreas Gruenbacher <agruen@suse.de> | 2004-06-06 00:20:07 +0000 |
---|---|---|
committer | Andreas Gruenbacher <agruen@suse.de> | 2004-06-06 00:20:07 +0000 |
commit | eb1a6de33c1b631e4636ff26dde2945a0db8db74 (patch) | |
tree | f8f6db4094c602e59fbbf9398e6edfaa499e851f /lib | |
parent | 77265baff69c1576f9e90e13b9a23d72363ab897 (diff) | |
download | quilt-eb1a6de33c1b631e4636ff26dde2945a0db8db74.tar.gz |
- backup-file.c: Add code to recursively search .pc directories.
Add a "no-op" mode as default, and allow to just unlink files.
- apatch/rpatch: let backup-files search .pc directories instead
of generating temporary file lists.
- rpatch/pop: unlink files of topmost patch after popping instead
of unlinking at each step.
- If QUILTRC is set in the environment, use this as the
configuration file.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/backup-files.c | 91 |
1 files changed, 70 insertions, 21 deletions
diff --git a/lib/backup-files.c b/lib/backup-files.c index 5f37ef5..fcbd2ff 100644 --- a/lib/backup-files.c +++ b/lib/backup-files.c @@ -25,6 +25,8 @@ * -B and -Z options. */ +#define _GNU_SOURCE + #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -33,14 +35,16 @@ #include <stdlib.h> #include <errno.h> #include <string.h> +#include <alloca.h> +#include <ftw.h> const char *progname; -enum { what_backup, what_restore, what_remove }; +enum { what_noop, what_backup, what_restore, what_remove }; const char *opt_prefix="", *opt_suffix="", *opt_file; -int opt_silent, opt_what=what_backup, opt_ignore_missing; -int opt_nolinks; +int opt_silent, opt_what=what_noop, opt_ignore_missing; +int opt_nolinks, opt_walk_directory; #define LINE_LENGTH 1024 @@ -48,11 +52,12 @@ int opt_nolinks; void usage(void) { - printf("Usage: %s [-B prefix] [-z suffix] [-f {filelist|-}] [-s] [-r|-x] [-L] filename ...\n" + printf("Usage: %s [-B prefix] [-z suffix] [-f {filelist|-}] [-s] [-b|-r|-x] [-L] {filename|-} ...\n" "\n" "\tCreate hard linked backup copies of a list of files\n" "\tread from standard input.\n" "\n" + "\t-b\tCreate backup\n" "\t-r\tRestore the backup\n" "\t-x\tRemove backup files and empty parent directories\n" "\t-B\tPath name prefix for backup files\n" @@ -63,10 +68,13 @@ usage(void) } void -create_parents(char *filename) +create_parents(const char *filename) { struct stat st; - char *f = strchr(filename, '/'); + char *fn = alloca(strlen(filename) + 1), *f; + + strcpy(fn, filename); + f = strchr(fn, '/'); if (f == NULL) return; @@ -74,7 +82,7 @@ create_parents(char *filename) if (stat(f, &st) != 0) { while (f != NULL) { *f = '\0'; - mkdir(filename, 0777); + mkdir(fn, 0777); *f = '/'; f = strchr(f+1, '/'); } @@ -205,26 +213,20 @@ ensure_nolinks(const char *filename) } int -process_file(char *file) +process_file(const char *file) { - char backup[LINE_LENGTH]; - - if (strlen(opt_prefix) + strlen(file) + - strlen(opt_suffix) >= sizeof(backup)) { - perror("Line buffer too small\n"); - return 1; - } + char *backup = alloca(strlen(opt_prefix) + strlen(file) + + strlen(opt_suffix) + 1); - snprintf(backup, sizeof(backup), "%s%s%s", - opt_prefix, file, opt_suffix); + sprintf(backup, "%s%s%s", opt_prefix, file, opt_suffix); if (opt_what == what_backup) { struct stat st; - int new_file = (stat(file, &st) == -1 && errno == ENOENT); + int missing_file = (stat(file, &st) == -1 && errno == ENOENT); unlink(backup); create_parents(backup); - if (new_file) { + if (missing_file) { int fd; if (!opt_silent) @@ -289,19 +291,56 @@ process_file(char *file) unlink(backup); remove_parents(backup); return 0; + } else if (opt_what == what_noop) { + struct stat st; + int missing_file = (stat(file, &st) == -1 && errno == ENOENT); + + if (!missing_file && opt_nolinks) { + if (ensure_nolinks(file)) + return 1; + } + return 0; } else return 1; } int +walk(const char *path, const struct stat *stat, int flag, struct FTW *ftw) +{ + size_t prefix_len=strlen(opt_prefix), suffix_len=strlen(opt_suffix); + size_t len = strlen(path); + char *p; + + if (flag == FTW_DNR) { + perror(path); + return 1; + } + if (!S_ISREG(stat->st_mode)) + return 0; + if (strncmp(opt_prefix, path, prefix_len)) + return 0; /* prefix does not match */ + if (len < suffix_len || strcmp(opt_suffix, path + len - suffix_len)) + return 0; /* suffix does not match */ + + p = alloca(len - prefix_len - suffix_len + 1); + memcpy(p, path + prefix_len, len - prefix_len - suffix_len); + p[len - prefix_len - suffix_len] = '\0'; + return process_file(p); +} + +int main(int argc, char *argv[]) { int opt, status=0; progname = argv[0]; - while ((opt = getopt(argc, argv, "rxB:z:f:shFL")) != -1) { + while ((opt = getopt(argc, argv, "brxB:z:f:shFL")) != -1) { switch(opt) { + case 'b': + opt_what = what_backup; + break; + case 'r': opt_what = what_restore; break; @@ -377,7 +416,17 @@ main(int argc, char *argv[]) } } for (; optind < argc; optind++) { - if ((status = process_file(argv[optind])) != 0) + if (strcmp(argv[optind], "-") == 0) { + char *dir = strdup(opt_prefix), *d = strrchr(dir, '/'); + if (d) + *(d+1) = '\0'; + else + d = "."; + status = nftw(dir, walk, 0, 0); + free(dir); + } else + status = process_file(argv[optind]); + if (status) return status; } |