From 8af83008790ddd9114bacde8bbfb83e59330597b Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Wed, 22 Sep 2004 02:27:53 +0000 Subject: [PATCH] New patch from Marc St-Onge. --- backup-dir-dels.diff | 311 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 backup-dir-dels.diff diff --git a/backup-dir-dels.diff b/backup-dir-dels.diff new file mode 100644 index 0000000..4eca0fa --- /dev/null +++ b/backup-dir-dels.diff @@ -0,0 +1,311 @@ +This patches creates two new command line options as follows: + --delete-dir + --delete-suffix + +The delete-dir and delete-suffix options give the ability to store +backup of deleted files on the receiver in different directories +or with different suffix than the backup of files that have been +changed but that are still on the source drive. Both commands can +be combined. + +The default behaviour if one or both of the options are not specified +is the previous behaviour, both backups use the same directory or +suffix. + +Marc St-Onge + +--- orig/backup.c 2004-09-20 19:50:13 ++++ backup.c 2004-09-22 02:18:49 +@@ -22,11 +22,17 @@ + + extern int verbose; + extern int backup_suffix_len; ++extern int delete_suffix_len; + extern int backup_dir_len; ++extern int delete_dir_len; + extern unsigned int backup_dir_remainder; ++extern unsigned int delete_dir_remainder; + extern char backup_dir_buf[MAXPATHLEN]; ++extern char delete_dir_buf[MAXPATHLEN]; + extern char *backup_suffix; ++extern char *delete_suffix; + extern char *backup_dir; ++extern char *delete_dir; + + extern int am_root; + extern int preserve_devices; +@@ -35,6 +41,8 @@ extern int preserve_hard_links; + extern int orig_umask; + extern int safe_symlinks; + ++static int deleting; ++ + /* make a complete pathname for backup file */ + char *get_backup_name(char *fname) + { +@@ -52,10 +60,27 @@ char *get_backup_name(char *fname) + return NULL; + } + ++static char *get_delete_name(char *fname) ++{ ++ if (delete_dir) { ++ if (stringjoin(delete_dir_buf + delete_dir_len, delete_dir_remainder, ++ fname, delete_suffix, NULL) < delete_dir_remainder) ++ return delete_dir_buf; ++ } else { ++ if (stringjoin(delete_dir_buf, MAXPATHLEN, ++ fname, delete_suffix, NULL) < MAXPATHLEN) ++ return delete_dir_buf; ++ } ++ ++ rprintf(FERROR, "delete filename too long\n"); ++ return NULL; ++} ++ + /* simple backup creates a backup with a suffix in the same directory */ + static int make_simple_backup(char *fname) + { +- char *fnamebak = get_backup_name(fname); ++ char *fnamebak = deleting ? get_delete_name(fname) ++ : get_backup_name(fname); + + if (!fnamebak) + return 0; +@@ -81,7 +106,8 @@ path + static int make_bak_dir(char *fullpath) + { + STRUCT_STAT st; +- char *rel = fullpath + backup_dir_len; ++ int dir_len = deleting ? delete_dir_len : backup_dir_len; ++ char *rel = fullpath + dir_len; + char *end = rel + strlen(rel); + char *p = end; + +@@ -173,7 +199,8 @@ static int keep_backup(char *fname) + if (!(file = make_file(fname, NULL, NO_EXCLUDES))) + return 1; /* the file could have disappeared */ + +- if (!(buf = get_backup_name(fname))) ++ buf = deleting ? get_delete_name(fname) : get_backup_name(fname); ++ if (!buf) + return 0; + + #ifdef HAVE_MKNOD +@@ -262,7 +289,18 @@ static int keep_backup(char *fname) + /* main backup switch routine */ + int make_backup(char *fname) + { ++ int ret; + if (backup_dir) +- return keep_backup(fname); +- return make_simple_backup(fname); ++ ret = keep_backup(fname); ++ else ++ ret = make_simple_backup(fname); ++ deleting = 0; /* Always restore the default backup process. */ ++ return ret; ++} ++ ++/* backup switch routine called only when backing-up deleted file */ ++int safe_delete(char *fname) ++{ ++ deleting = 1; ++ return make_backup(fname); + } +--- orig/options.c 2004-09-20 05:10:48 ++++ options.c 2004-09-22 02:25:03 +@@ -113,10 +113,14 @@ int no_detach = 0; + int write_batch = 0; + int read_batch = 0; + int backup_dir_len = 0; ++int delete_dir_len = 0; + int backup_suffix_len; ++int delete_suffix_len; + unsigned int backup_dir_remainder; ++unsigned int delete_dir_remainder; + + char *backup_suffix = NULL; ++char *delete_suffix = NULL; + char *tmpdir = NULL; + char *partial_dir = NULL; + char *compare_dest = NULL; +@@ -126,7 +130,9 @@ char *log_format = NULL; + char *password_file = NULL; + char *rsync_path = RSYNC_PATH; + char *backup_dir = NULL; ++char *delete_dir = NULL; + char backup_dir_buf[MAXPATHLEN]; ++char delete_dir_buf[MAXPATHLEN]; + int rsync_port = RSYNC_PORT; + int link_dest = 0; + +@@ -239,7 +245,9 @@ void usage(enum logcode F) + rprintf(F," --no-implied-dirs don't send implied dirs with -R\n"); + rprintf(F," -b, --backup make backups (see --suffix & --backup-dir)\n"); + rprintf(F," --backup-dir make backups into this directory\n"); ++ rprintf(F," --delete-dir make backups of deleted files into this directory\n"); + rprintf(F," --suffix=SUFFIX backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX); ++ rprintf(F," --delete-suffix=SUFFIX deleted files suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX); + rprintf(F," -u, --update update only (don't overwrite newer files)\n"); + rprintf(F," --inplace update destination files inplace (SEE MAN PAGE)\n"); + rprintf(F," -K, --keep-dirlinks treat symlinked dir on receiver as dir\n"); +@@ -326,6 +334,7 @@ static struct poptOption long_options[] + /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ + {"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0}, + {"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 }, ++ {"delete-suffix", 0, POPT_ARG_STRING, &delete_suffix, 0, 0, 0 }, + {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 }, + {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 }, + {"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 }, +@@ -396,6 +405,7 @@ static struct poptOption long_options[] + {"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 }, + {"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 }, + {"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 }, ++ {"delete-dir", 0, POPT_ARG_STRING, &delete_dir, 0, 0, 0 }, + {"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links, 0, 0, 0 }, + {"read-batch", 0, POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 }, + {"write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 }, +@@ -733,6 +743,8 @@ int parse_arguments(int *argc, const cha + compare_dest = sanitize_path(NULL, compare_dest, NULL, 0); + if (backup_dir) + backup_dir = sanitize_path(NULL, backup_dir, NULL, 0); ++ if (delete_dir) ++ delete_dir = sanitize_path(NULL, delete_dir, NULL, 0); + if (files_from) + files_from = sanitize_path(NULL, files_from, NULL, 0); + } +@@ -758,6 +770,12 @@ int parse_arguments(int *argc, const cha + if (check_exclude(elp, backup_dir, 1) < 0) + goto options_rejected; + } ++ /* Clean delete_dir same as for backup_dir */ ++ if (delete_dir) { ++ clean_fname(delete_dir, 1); ++ if (check_exclude(elp, delete_dir, 1) < 0) ++ goto options_rejected; ++ } + } + if (server_exclude_list.head && files_from) { + clean_fname(files_from, 1); +@@ -784,6 +802,16 @@ int parse_arguments(int *argc, const cha + backup_suffix); + return 0; + } ++ /* if deleted_suffix not supplied, default to backup_suffix */ ++ if (!delete_suffix) ++ delete_suffix = delete_dir ? "" : backup_suffix; ++ delete_suffix_len = strlen(delete_suffix); ++ if (strchr(delete_suffix, '/') != NULL) { ++ snprintf(err_buf, sizeof err_buf, ++ "--delete-suffix cannot contain slashes: %s\n", ++ delete_suffix); ++ return 0; ++ } + if (backup_dir) { + backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf); + backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len; +@@ -803,6 +831,31 @@ int parse_arguments(int *argc, const cha + "--suffix cannot be a null string without --backup-dir\n"); + return 0; + } ++ /* If delete_dir not supplied default to backup_dir if it has been supplied */ ++ if (backup_dir && !delete_dir) { ++ delete_dir = backup_dir; ++ delete_dir_len = backup_dir_len; ++ delete_dir_remainder = backup_dir_remainder; ++ strlcpy(delete_dir_buf, backup_dir_buf, sizeof backup_dir_buf); ++ } else if (delete_dir) { ++ delete_dir_len = strlcpy(delete_dir_buf, delete_dir, sizeof delete_dir_buf); ++ delete_dir_remainder = sizeof delete_dir_buf - delete_dir_len; ++ if (delete_dir_remainder < 32) { ++ snprintf(err_buf, sizeof err_buf, ++ "the --delete-dir path is WAY too long.\n"); ++ return 0; ++ } ++ if (delete_dir_buf[delete_dir_len - 1] != '/') { ++ delete_dir_buf[delete_dir_len++] = '/'; ++ delete_dir_buf[delete_dir_len] = '\0'; ++ } ++ if (verbose > 1 && !am_sender) ++ rprintf(FINFO, "delete_dir is %s\n", delete_dir_buf); ++ } else if (!delete_suffix_len && (!am_server || !am_sender)) { ++ snprintf(err_buf, sizeof err_buf, ++ "--delete-suffix cannot be a null string without --delete-dir\n"); ++ return 0; ++ } + + if (do_progress && !verbose) + verbose = 1; +@@ -1005,6 +1058,10 @@ void server_options(char **args,int *arg + args[ac++] = "--backup-dir"; + args[ac++] = backup_dir; + } ++ if (delete_dir) { ++ args[ac++] = "--delete-dir"; ++ args[ac++] = delete_dir; ++ } + + /* Only send --suffix if it specifies a non-default value. */ + if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) { +@@ -1013,7 +1070,13 @@ void server_options(char **args,int *arg + goto oom; + args[ac++] = arg; + } +- ++ /* Only send --delete-suffix if it specifies a non-default value. */ ++ if (strcmp(delete_suffix, delete_dir ? "" : BACKUP_SUFFIX) != 0) { ++ /* We use the following syntax to avoid weirdness with '~'. */ ++ if (asprintf(&arg, "--delete-suffix=%s", delete_suffix) < 0) ++ goto oom; ++ args[ac++] = arg; ++ } + if (am_sender) { + if (delete_excluded) + args[ac++] = "--delete-excluded"; +--- orig/receiver.c 2004-09-21 09:40:27 ++++ receiver.c 2004-09-22 02:09:20 +@@ -42,8 +42,11 @@ extern char *compare_dest; + extern int make_backups; + extern int do_progress; + extern char *backup_dir; ++extern char *delete_dir; + extern char *backup_suffix; ++extern char *delete_suffix; + extern int backup_suffix_len; ++extern int delete_suffix_len; + extern int cleanup_got_literal; + extern int module_id; + extern int ignore_errors; +@@ -77,11 +80,14 @@ static void delete_one(char *fn, int is_ + } + } + +- ++/* Function now checks if file matches backup or delete suffix patterns */ + static int is_backup_file(char *fn) + { + int k = strlen(fn) - backup_suffix_len; +- return k > 0 && strcmp(fn+k, backup_suffix) == 0; ++ if (k > 0 && strcmp(fn+k, backup_suffix) == 0) ++ return 1; ++ k = strlen(fn) - delete_suffix_len; ++ return k > 0 && strcmp(fn+k, delete_suffix) == 0; + } + + +@@ -122,10 +128,11 @@ void delete_files(struct file_list *flis + continue; + if (flist_find(flist,local_file_list->files[i]) < 0) { + char *f = f_name(local_file_list->files[i]); +- if (make_backups && (backup_dir || !is_backup_file(f))) { +- make_backup(f); ++ int backup_file = is_backup_file(f); ++ if (make_backups && (delete_dir || !backup_file)) { ++ safe_delete(f); + if (verbose) { +- rprintf(FINFO, "deleting %s\n", ++ rprintf(FINFO, "safe-deleting %s\n", + safe_fname(f)); + } + } else { -- 2.34.1