From 94e2ecad7c47cddbd719d774861947bf726c7a4e Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 1 Feb 2012 18:08:49 +0100 Subject: Clean up legacy C code Finally get rid of the old C implementation of backup-files, together with all the related checks in configure and variables in Makefile. Signed-off-by: Jean Delvare --- lib/backup-files.c | 622 ----------------------------------------------------- 1 file changed, 622 deletions(-) delete mode 100644 lib/backup-files.c (limited to 'lib/backup-files.c') diff --git a/lib/backup-files.c b/lib/backup-files.c deleted file mode 100644 index e2c1ea1..0000000 --- a/lib/backup-files.c +++ /dev/null @@ -1,622 +0,0 @@ -/* - File: backup-files.c - - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 - Andreas Gruenbacher , SuSE Labs - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -/* - * Create backup files of a list of files similar to GNU patch. A path - * name prefix and suffix for the backup file can be specified with the - * -B and -z options. - */ - -#define _GNU_SOURCE 1 - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined(HAVE_MKSTEMP) && defined(HAVE_MKTEMP) -# define mkstemp(x) creat(mktemp(x), 0600) -#endif - -#ifndef PATH_MAX -# define PATH_MAX 4096 -#endif - -#ifdef __MINGW32__ -#define mkdir(x,y) mkdir(x) -/* Symlinks are not supported */ -#define lstat stat -static int link(const char *oldpath, const char *newpath) -{ - errno = ENOSYS; - return -1; -} -#endif - -const char *progname; - -enum { what_noop, what_backup, what_restore, what_remove }; - -const char *opt_prefix="", *opt_suffix="", *opt_file; -int opt_silent, opt_what=what_noop; -int opt_nolinks, opt_touch; -int opt_keep_backup; - -#define LINE_LENGTH 1024 - - -static void -usage(void) -{ - printf("Usage: %s [-B prefix] [-z suffix] [-f {file|-}] [-sktL] [-b|-r|-x] {file|-} ...\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-k\tWhen doing a restore, keep the backup files\n" - "\t-B\tPath name prefix for backup files\n" - "\t-z\tPath name suffix for backup files\n" - "\t-s\tSilent operation; only print error messages\n" - "\t-f\tRead the filenames to process from file (- = standard input)\n" - "\t-t\tTouch original files after restore (update their mtimes)\n\n" - "\t-L\tEnsure that when finished, the source file has a link count of 1\n\n", - progname); -} - -static void * -malloc_nofail(size_t size) -{ - void *p = malloc(size); - if (!p) { - perror(progname); - exit(1); - } - return p; -} - -static void -create_parents(const char *filename) -{ - struct stat st; - int rv = -1; - char *fn = malloc_nofail(strlen(filename) + 1), *f; - - strcpy(fn, filename); - - f = strrchr(fn, '/'); - if (f == NULL) - goto out; - *f = '\0'; - if (stat(fn, &st) == 0) - goto out; - *f = '/'; - - f = strchr(fn, '/'); - while (f != NULL) { - *f = '\0'; - if (!rv || (rv = stat(fn, &st)) != 0) { - mkdir(fn, 0777); - } - *f = '/'; - f = strchr(f+1, '/'); - } -out: - free(fn); -} - -static void -remove_parents(const char *filename) -{ - char *fn = malloc_nofail(strlen(filename) + 1), *f; - - strcpy(fn, filename); - - f = strrchr(fn, '/'); - if (f == NULL) - goto out; - do { - *f = '\0'; - if (rmdir(fn) == -1) - goto out; - } while ((f = strrchr(fn, '/')) != NULL); - rmdir(fn); -out: - free(fn); -} - -static int -copy_fd(int from_fd, int to_fd) -{ - char buffer[16384]; - char *wbuf; - ssize_t len, l; - - for ( ;; ) { - len = read(from_fd, buffer, sizeof(buffer)); - if (len == 0) - return 0; - if (len < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - return 1; - } - for (wbuf = buffer; len != 0; ) { - l = write(to_fd, wbuf, len); - if (l < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - return 1; - } - wbuf += l; - len -= l; - } - } -} - -static int -copy_file(const char *from, const struct stat *st, const char *to) -{ - int from_fd, to_fd, error = 1; - - if ((from_fd = open(from, O_RDONLY)) == -1) { - perror(from); - return 1; - } - unlink(to); /* make sure we don't inherit this file's mode. */ - if ((to_fd = creat(to, st->st_mode)) < 0) { - perror(to); - close(from_fd); - return 1; - } -#if defined(HAVE_FCHMOD) - (void) fchmod(to_fd, st->st_mode); -#elif defined(HAVE_CHMOD) - (void) chmod(to, st->st_mode); -#endif - if (copy_fd(from_fd, to_fd)) { - fprintf(stderr, "%s -> %s: %s\n", from, to, strerror(errno)); - unlink(to); - goto out; - } - - error = 0; -out: - close(from_fd); - close(to_fd); - - return error; -} - -static int -link_or_copy_file(const char *from, const struct stat *st, const char *to) -{ - if (link(from, to) == 0) - return 0; - if (errno != EXDEV && errno != EPERM && - errno != EMLINK && errno != ENOSYS) { - fprintf(stderr, "Could not link file `%s' to `%s': %s\n", - from, to, strerror(errno)); - return 1; - } - return copy_file(from, st, to); -} - -static int -ensure_nolinks(const char *filename) -{ - struct stat st; - - if (stat(filename, &st) != 0) { - perror(filename); - return 1; - } - if (st.st_nlink > 1) { - char *tmpname = malloc(1 + strlen(filename) + 7 + 1), *c; - int from_fd = -1, to_fd = -1; - int error = 1; - - if (!tmpname) - goto fail; - from_fd = open(filename, O_RDONLY); - if (from_fd == -1) - goto fail; - - /* Temp file name is "path/to/.file.XXXXXX" */ - strcpy(tmpname, filename); - strcat(tmpname, ".XXXXXX"); - c = strrchr(tmpname, '/'); - if (c == NULL) - c = tmpname; - else - c++; - memmove(c + 1, c, strlen(c) + 1); - *c = '.'; - - to_fd = mkstemp(tmpname); - if (to_fd == -1) - goto fail; - if (copy_fd(from_fd, to_fd)) - goto fail; -#if defined(HAVE_FCHMOD) - (void) fchmod(to_fd, st.st_mode); -#elif defined(HAVE_CHMOD) - (void) chmod(tmpname, st.st_mode); -#endif - close(from_fd); - from_fd = -1; - close(to_fd); - to_fd = -1; - if (rename(tmpname, filename)) - goto fail; - - error = 0; - fail: - if (error) - perror(filename); - if (from_fd != -1) - close(from_fd); - if (to_fd != -1) - close(to_fd); - free(tmpname); - return error; - } else - return 0; -} - -static int -process_file(const char *file) -{ - char *backup = malloc_nofail( - strlen(opt_prefix) + strlen(file) + strlen(opt_suffix) + 1); - - sprintf(backup, "%s%s%s", opt_prefix, file, opt_suffix); - - if (opt_what == what_backup) { - struct stat st; - int missing_file = (stat(file, &st) == -1 && errno == ENOENT); - - unlink(backup); - create_parents(backup); - if (missing_file) { - int fd; - - if (!opt_silent) - printf("New file %s\n", file); - /* Old versions of GNU patch create new files with mode==0. - (This has been changed/fixed in patch version 2.6.) */ - if ((fd = creat(backup, 0666)) == -1) { - perror(backup); - goto fail; - } - close(fd); - } else { - if (!opt_silent) - printf("Copying %s\n", file); - if (opt_nolinks && st.st_nlink == 1) { - if (copy_file(file, &st, backup)) - goto fail; - } else { - if (link_or_copy_file(file, &st, backup)) - goto fail; - if (opt_nolinks && ensure_nolinks(file)) - goto fail; - } - if (opt_touch) - (void) utime(backup, NULL); - else { - struct utimbuf ut; - ut.actime = ut.modtime = st.st_mtime; - (void) utime(backup, &ut); - } - } - } else if (opt_what == what_restore) { - struct stat st; - - create_parents(file); - if (stat(backup, &st) != 0) { - perror(backup); - goto fail; - } - if (st.st_size == 0) { - if (unlink(file) == 0 || errno == ENOENT) { - if (!opt_silent) - printf("Removing %s\n", file); - } else { - perror(file); - goto fail; - } - if (!opt_keep_backup) { - unlink(backup); - remove_parents(backup); - } - } else { - if (!opt_silent) - printf("Restoring %s\n", file); - unlink(file); - if (opt_nolinks && st.st_nlink != 1) { - if (copy_file(backup, &st, file)) - goto fail; - } else { - if (link_or_copy_file(backup, &st, file)) - goto fail; - if (opt_nolinks && ensure_nolinks(file)) - goto fail; - } - if (!opt_keep_backup) { - unlink(backup); - remove_parents(backup); - } - if (opt_touch) - (void) utime(file, NULL); - else { - struct utimbuf ut; - ut.actime = ut.modtime = st.st_mtime; - (void) utime(file, &ut); - } - } - } else if (opt_what == what_remove) { - unlink(backup); - remove_parents(backup); - } 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)) - goto fail; - } - } else - goto fail; - - free(backup); - return 0; - -fail: - free(backup); - return 1; -} - -static int -foreachdir_rec(const char *path, struct stat *st, - int (*walk)(const char *, const struct stat *)) -{ - DIR *dir; - struct dirent *dp; - int failed = 0; - - struct path { - char *name; - struct path *next; - }; - struct path *paths = NULL, *last_path = NULL; - - if (access(path, R_OK|X_OK) || !(dir = opendir(path))) - return walk(path, NULL); - while ((dp = readdir(dir))) { - struct path *p; - size_t size; - - if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) - continue; - - p = malloc_nofail(sizeof(*p)); - if (!last_path) - paths = p; - else - last_path->next = p; - p->next = NULL; - last_path = p; - - size = strlen(path) + 1 + strlen(dp->d_name) + 1; - p->name = malloc_nofail(size); - sprintf(p->name, "%s/%s", path, dp->d_name); - } - if (closedir(dir) != 0) - failed = -1; - - while (paths != NULL) { - struct path *next; - - if (lstat(paths->name, st)) - continue; /* file has disappeared meanwhile */ - if (S_ISDIR(st->st_mode)) { - failed = foreachdir_rec(paths->name, st, walk); - if (failed) - goto out; - } else { - failed = walk(paths->name, st); - if (failed) - goto out; - } - next = paths->next; - free(paths->name); - free(paths); - paths = next; - } - -out: - 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 (!st) { - perror(path); - return 1; - } - if (!S_ISREG(st->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 = malloc_nofail(len - prefix_len - suffix_len + 1); - memcpy(p, path + prefix_len, len - prefix_len - suffix_len); - p[len - prefix_len - suffix_len] = '\0'; - ret = process_file(p); - free(p); - return ret; -} - -int -main(int argc, char *argv[]) -{ - int opt, status = 0; - - progname = argv[0]; - - while ((opt = getopt(argc, argv, "brkxB:z:f:shLt")) != -1) { - switch(opt) { - case 'b': - opt_what = what_backup; - break; - - case 'r': - opt_what = what_restore; - break; - - case 'k': - opt_keep_backup = 1; - break; - - case 'x': - opt_what = what_remove; - break; - - case 'B': - opt_prefix = optarg; - break; - - case 'f': - opt_file = optarg; - break; - - case 'z': - opt_suffix = optarg; - break; - - case 's': - opt_silent = 1; - break; - - case 'L': - opt_nolinks = 1; - break; - - case 't': - opt_touch = 1; - break; - - case 'h': - default: - usage(); - return 0; - } - } - - if ((*opt_prefix == '\0' && *opt_suffix == '\0') || - (opt_file == NULL && optind == argc)) { - usage(); - return 1; - } - - if (opt_file != NULL) { - FILE *file; - char line[LINE_LENGTH]; - - if (!strcmp(opt_file, "-")) { - file = stdin; - } else { - if ((file = fopen(opt_file, "r")) == NULL) { - perror(opt_file); - return 1; - } - } - - while (fgets(line, sizeof(line), file)) { - char *l = strchr(line, '\0'); - - if (l > line && *(l-1) == '\n') - *(l-1) = '\0'; - if (*line == '\0') - continue; - - if ((status = process_file(line)) != 0) - return status; - } - - if (file != stdin) { - fclose(file); - } - } - for (; optind < argc; optind++) { - if (strcmp(argv[optind], "-") == 0) { - struct stat st; - char *dir = strdup(opt_prefix), *d = strrchr(dir, '/'); - if (d) - *d = '\0'; - else - d = "."; - if (stat(dir, &st) == 0) { - status = foreachdir(dir, walk); - if (status == -1) - perror(dir); - } - free(dir); - } else - status = process_file(argv[optind]); - if (status) - return status; - } - - return status; -} -- cgit