New patch from Marc St-Onge.
authorWayne Davison <wayned@samba.org>
Wed, 22 Sep 2004 02:27:53 +0000 (02:27 +0000)
committerWayne Davison <wayned@samba.org>
Wed, 22 Sep 2004 02:27:53 +0000 (02:27 +0000)
backup-dir-dels.diff [new file with mode: 0644]

diff --git a/backup-dir-dels.diff b/backup-dir-dels.diff
new file mode 100644 (file)
index 0000000..4eca0fa
--- /dev/null
@@ -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 {