summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@suse.de>2004-06-06 00:20:07 +0000
committerAndreas Gruenbacher <agruen@suse.de>2004-06-06 00:20:07 +0000
commiteb1a6de33c1b631e4636ff26dde2945a0db8db74 (patch)
treef8f6db4094c602e59fbbf9398e6edfaa499e851f /lib
parent77265baff69c1576f9e90e13b9a23d72363ab897 (diff)
downloadquilt-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.c91
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;
}