summaryrefslogtreecommitdiffstats
path: root/lib/backup-files.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/backup-files.c')
-rw-r--r--lib/backup-files.c228
1 files changed, 135 insertions, 93 deletions
diff --git a/lib/backup-files.c b/lib/backup-files.c
index b9f1b21..c6e0c6d 100644
--- a/lib/backup-files.c
+++ b/lib/backup-files.c
@@ -1,14 +1,29 @@
-/* backup-files.c
- Andreas Gruenbacher, 18 January 2003
+/*
+ File: backup-files.c
+
+ Copyright (C) 2003 Andreas Gruenbacher <agruen@suse.de>
+ SuSE Labs, SuSE Linux AG
+
+ 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.
- `patch -b' fails to back up files correctly if a file occurs
- more than once in a patch, so we use this utility instead.
+ 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.
*/
/*
- - catch SIGINT
- - remove backup files and directories
-*/
+ * 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.
+ */
#include <sys/types.h>
#include <sys/stat.h>
@@ -20,10 +35,18 @@
const char *progname;
+enum { what_backup, what_restore, what_remove };
+
+const char *opt_prefix="", *opt_suffix="", *opt_file=NULL;
+int opt_silent=0, opt_what=what_backup;
+
+#define LINE_LENGTH 1024
+
+
void
usage(void)
{
- printf("Usage: %s [-B prefix] [-z suffix] [-f filelist] [-s] [-r|-x]\n"
+ printf("Usage: %s [-B prefix] [-z suffix] [-f {filelist|-}] [-s] [-r|-x] filename ...\n"
"\n"
"\tCreate hard linked backup copies of a list of files\n"
"\tread from standard input.\n"
@@ -60,26 +83,96 @@ create_parents(char *filename)
void
remove_parents(char *filename)
{
- char *f;
+ char *f, *g = NULL;
+ f = strrchr(filename, '/');
while ((f = strrchr(filename, '/')) != NULL) {
- *f = '\0';
+ if (g != NULL)
+ *g = '/';
+ g = f;
+ *f= '\0';
+
rmdir(filename);
}
+ if (g != NULL)
+ *g = '/';
}
-enum { what_backup, what_restore, what_remove };
+int
+process_file(char *file)
+{
+ char backup[LINE_LENGTH];
-#define LINE_LENGTH 1024
+ if (strlen(opt_prefix) + strlen(file) +
+ strlen(opt_suffix) >= sizeof(backup)) {
+ perror("Line buffer too small\n");
+ return 1;
+ }
+
+ snprintf(backup, sizeof(backup), "%s%s%s",
+ opt_prefix, file, opt_suffix);
+
+ if (opt_what == what_backup) {
+ int fd;
+ create_parents(backup);
+
+ unlink(backup);
+ if (link(file, backup) == 0) {
+ if (!opt_silent)
+ printf("Copying %s\n", file);
+ } else if ((fd = creat(backup, 0666)) != -1) {
+ close(fd);
+ if (!opt_silent)
+ printf("New file %s\n", file);
+ } else {
+ perror(backup);
+ return 1;
+ }
+ return 0;
+ } else if (opt_what == what_restore) {
+ struct stat st;
+ create_parents(file);
+
+ if (stat(backup, &st) != 0) {
+ perror(backup);
+ return 1;
+ }
+ if (st.st_size == 0) {
+ if (unlink(file) == 0 || errno == ENOENT) {
+ if (!opt_silent)
+ printf("Removing %s\n", file);
+ unlink(backup);
+ remove_parents(backup);
+ } else {
+ perror(file);
+ return 1;
+ }
+ } else {
+ unlink(file);
+ if (link(backup, file) == 0) {
+ if (!opt_silent)
+ printf("Restoring %s\n", file);
+ unlink(backup);
+ remove_parents(backup);
+ } else {
+ fprintf(stderr, "Could not restore "
+ "file `%s' to `%s': %s\n",
+ backup, file, strerror(errno));
+ return 1;
+ }
+ }
+ return 0;
+ } else if (opt_what == what_remove) {
+ unlink(backup);
+ remove_parents(backup);
+ return 0;
+ } else
+ return 1;
+}
int
main(int argc, char *argv[])
{
- char orig[LINE_LENGTH], *o, backup[LINE_LENGTH];
- FILE *file;
-
- const char *opt_prefix="", *opt_suffix="", *opt_file=NULL;
- int opt_silent=0, opt_what=what_backup;
int opt, status=0;
progname = argv[0];
@@ -117,95 +210,44 @@ main(int argc, char *argv[])
}
}
- if ((*opt_prefix == '\0' && *opt_suffix == '\0') || optind != argc) {
+ if ((*opt_prefix == '\0' && *opt_suffix == '\0') ||
+ (opt_file == NULL && optind == argc)) {
usage();
return 1;
}
if (opt_file != NULL) {
- if ((file = fopen(opt_file, "r")) == NULL) {
- perror(opt_file);
- return 1;
- }
- } else {
- file = stdin;
- }
-
- while (fgets(orig, sizeof(orig), file)) {
- if (strlen(opt_prefix) + strlen(orig) + strlen(opt_suffix) >=
- sizeof(backup)) {
- perror("Line buffer too small\n");
- return 1;
- }
-
- o = strchr(orig, '\0');
- if (o > orig && *(o-1) == '\n')
- *(o-1) = '\0';
- if (*orig == '\0')
- continue;
-
- snprintf(backup, sizeof(backup), "%s%s%s",
- opt_prefix, orig, opt_suffix);
+ FILE *file;
+ char line[LINE_LENGTH];
- if (opt_what == what_backup) {
- int fd;
- create_parents(backup);
-
- if (link(orig, backup) == 0) {
- if (!opt_silent)
- printf("Copying %s\n", orig);
- } else if ((fd = creat(backup, 0666)) != -1) {
- close(fd);
- if (!opt_silent)
- printf("New file %s\n", orig);
- } else {
- perror(backup);
+ if (!strcmp(opt_file, "-")) {
+ file = stdin;
+ } else {
+ if ((file = fopen(opt_file, "r")) == NULL) {
+ perror(opt_file);
return 1;
}
- } else if (opt_what == what_restore) {
- struct stat st;
+ }
- create_parents(orig);
+ while (fgets(line, sizeof(line), file)) {
+ char *l = strchr(line, '\0');
- if (stat(backup, &st) != 0) {
- perror(backup);
- status=1;
+ if (l > line && *(l-1) == '\n')
+ *(l-1) = '\0';
+ if (*line == '\0')
continue;
- }
- if (st.st_size == 0) {
- if (unlink(orig) == 0 || errno == ENOENT) {
- if (!opt_silent)
- printf("Removing %s\n", orig);
- unlink(backup);
- remove_parents(backup);
- } else {
- if (errno != ENOENT) {
- perror(orig);
- status=1;
- }
- }
- } else {
- unlink(orig);
- if (link(backup, orig) == 0) {
- if (!opt_silent)
- printf("Restoring %s\n", orig);
- unlink(backup);
- remove_parents(backup);
- } else {
- fprintf(stderr, "Could not restore "
- "file `%s' to `%s': %s\n",
- backup, orig, strerror(errno));
- status=1;
- }
- }
- } else {
- unlink(backup);
- remove_parents(backup);
+
+ if ((status = process_file(line)) != 0)
+ return status;
}
- }
- if (file != stdin) {
- fclose(file);
+ if (file != stdin) {
+ fclose(file);
+ }
+ }
+ for (; optind < argc; optind++) {
+ if ((status = process_file(argv[optind])) != 0)
+ return status;
}
return status;