The patches for 3.3.0.
[rsync-patches.git] / backup-dir-dels.diff
index f443a2fb7e0658d2bca7db9ee1414a4749c0bf99..50ac8762bc6520526e67a0ba55844aba70e4af2d 100644 (file)
@@ -115,7 +115,7 @@ diff --git a/backup.c b/backup.c
                        unmake_file(file);
                }
  
-@@ -156,28 +163,34 @@ static BOOL copy_valid_path(const char *fname)
+@@ -156,7 +163,12 @@ static BOOL copy_valid_path(const char *fname)
  /* Make a complete pathname for backup file and verify any new path elements. */
  char *get_backup_name(const char *fname)
  {
@@ -123,27 +123,13 @@ diff --git a/backup.c b/backup.c
 +      char *suffix = deleting ? backup_suffix_dels : backup_suffix;
 +
        if (backup_dir) {
-               static int initialized = 0;
--              if (!initialized) {
 +              int prefix_len = deleting ? backup_dir_dels_len : backup_dir_len;
 +              unsigned int remainder = deleting ? backup_dir_dels_remainder : backup_dir_remainder;
-+              int init_bits = deleting ? 2 : 1;
-+              if (!(initialized & init_bits)) {
+               static int initialized = 0;
+               if (!initialized) {
                        int ret;
--                      if (backup_dir_len > 1)
--                              backup_dir_buf[backup_dir_len-1] = '\0';
--                      ret = make_path(backup_dir_buf, 0);
--                      if (backup_dir_len > 1)
--                              backup_dir_buf[backup_dir_len-1] = '/';
-+                      if (prefix_len > 1)
-+                              buf[prefix_len-1] = '\0';
-+                      ret = make_path(buf, 0);
-+                      if (prefix_len > 1)
-+                              buf[prefix_len-1] = '/';
-                       if (ret < 0)
-                               return NULL;
--                      initialized = 1;
-+                      initialized |= init_bits;
+@@ -170,14 +182,14 @@ char *get_backup_name(const char *fname)
+                       initialized = 1;
                }
                /* copy fname into backup_dir_buf while validating the dirs. */
 -              if (copy_valid_path(fname))
@@ -156,12 +142,12 @@ diff --git a/backup.c b/backup.c
  
 -      if (stringjoin(backup_dir_buf, MAXPATHLEN, fname, backup_suffix, NULL) < MAXPATHLEN)
 -              return backup_dir_buf;
-+      if (stringjoin(buf, MAXPATHLEN, fname, suffix, NULL) < MAXPATHLEN)
++      if (stringjoin(backup_dir_buf, MAXPATHLEN, fname, suffix, NULL) < MAXPATHLEN)
 +              return buf;
  
        rprintf(FERROR, "backup filename too long\n");
        return NULL;
-@@ -352,3 +365,13 @@ int make_backup(const char *fname, BOOL prefer_rename)
+@@ -353,3 +365,13 @@ int make_backup(const char *fname, BOOL prefer_rename)
                rprintf(FINFO, "backed up %s to %s\n", fname, buf);
        return ret;
  }
@@ -218,7 +204,7 @@ diff --git a/delete.c b/delete.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -153,10 +153,14 @@ int no_detach
+@@ -166,10 +166,14 @@ int no_detach
  int write_batch = 0;
  int read_batch = 0;
  int backup_dir_len = 0;
@@ -233,8 +219,8 @@ diff --git a/options.c b/options.c
  char *tmpdir = NULL;
  char *partial_dir = NULL;
  char *basis_dir[MAX_BASIS_DIRS+1];
-@@ -168,7 +172,9 @@ char *stdout_format = NULL;
- char *password_file = NULL;
+@@ -182,7 +186,9 @@ char *password_file = NULL;
+ char *early_input_file = NULL;
  char *rsync_path = RSYNC_PATH;
  char *backup_dir = NULL;
 +char *backup_dir_dels = NULL;
@@ -243,16 +229,7 @@ diff --git a/options.c b/options.c
  char *sockopts = NULL;
  char *usermap = NULL;
  char *groupmap = NULL;
-@@ -681,6 +687,8 @@ void usage(enum logcode F)
-   rprintf(F,"     --backup-deleted        make backups only of deleted files\n");
-   rprintf(F,"     --backup-dir=DIR        make backups into hierarchy based in DIR\n");
-   rprintf(F,"     --suffix=SUFFIX         set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
-+  rprintf(F,"     --backup-dir-dels=DIR   backup removed files into hierarchy based in DIR\n");
-+  rprintf(F,"     --suffix-dels=SUFFIX    set removed-files suffix (def. --suffix w/o b-d-d)\n");
-   rprintf(F," -u, --update                skip files that are newer on the receiver\n");
-   rprintf(F,"     --inplace               update destination files in-place (SEE MAN PAGE)\n");
-   rprintf(F,"     --append                append data onto shorter files\n");
-@@ -999,7 +1007,9 @@ static struct poptOption long_options[] = {
+@@ -780,7 +786,9 @@ static struct poptOption long_options[] = {
    {"backup-deleted",   0,  POPT_ARG_VAL,    &make_backups, 1, 0, 0 },
    {"no-backup",        0,  POPT_ARG_VAL,    &make_backups, 0, 0, 0 },
    {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
@@ -262,7 +239,7 @@ diff --git a/options.c b/options.c
    {"list-only",        0,  POPT_ARG_VAL,    &list_only, 2, 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 },
-@@ -2101,6 +2111,8 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -2253,6 +2261,8 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, SP_DEFAULT);
                if (backup_dir)
                        backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, SP_DEFAULT);
@@ -271,7 +248,7 @@ diff --git a/options.c b/options.c
        }
        if (daemon_filter_list.head && !am_sender) {
                filter_rule_list *elp = &daemon_filter_list;
-@@ -2122,6 +2134,14 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -2274,6 +2284,14 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        if (check_filter(elp, FLOG, dir, 1) < 0)
                                goto options_rejected;
                }
@@ -286,9 +263,9 @@ diff --git a/options.c b/options.c
        }
  
        if (!backup_suffix)
-@@ -2133,6 +2153,20 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -2285,6 +2303,20 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        backup_suffix);
-               return 0;
+               goto cleanup;
        }
 +      /* --suffix-dels defaults to --suffix, or empty for a client given an
 +       * explicit --backup-dir-dels (just as --suffix defaults to empty when
@@ -306,8 +283,8 @@ diff --git a/options.c b/options.c
 +      }
        if (backup_dir) {
                size_t len;
-               while (*backup_dir == '.' && backup_dir[1] == '/')
-@@ -2168,6 +2202,34 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+               make_backups = 1; /* --backup-dir implies --backup */
+@@ -2321,6 +2353,34 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        "P *%s", backup_suffix);
                parse_filter_str(&filter_list, backup_dir_buf, rule_template(0), 0);
        }
@@ -340,11 +317,11 @@ diff --git a/options.c b/options.c
 +              parse_filter_str(&filter_list, backup_dir_dels_buf, rule_template(0), 0);
 +      }
  
-       if (preserve_times) {
-               preserve_times = PRESERVE_FILE_TIMES;
-@@ -2594,6 +2656,10 @@ void server_options(char **args, int *argc_p)
+       if (make_backups && !backup_dir)
+               omit_dir_times = -1; /* Implied, so avoid -O to sender. */
+@@ -2790,11 +2850,20 @@ void server_options(char **args, int *argc_p)
                args[ac++] = "--backup-dir";
-               args[ac++] = backup_dir;
+               args[ac++] = safe_arg("", backup_dir);
        }
 +      if (backup_dir_dels && backup_dir_dels != backup_dir) {
 +              args[ac++] = "--backup-dir-dels";
@@ -352,19 +329,39 @@ diff --git a/options.c b/options.c
 +      }
  
        /* Only send --suffix if it specifies a non-default value. */
-       if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
-@@ -2602,6 +2668,14 @@ void server_options(char **args, int *argc_p)
-                       goto oom;
-               args[ac++] = arg;
-       }
+       if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0)
+               args[ac++] = safe_arg("--suffix", backup_suffix);
 +      /* Only send --suffix-dels if it specifies a value different from the
 +       * --suffix value, which would normally be used for deletions too. */
-+      if (strcmp(backup_suffix_dels, backup_suffix) != 0) {
-+              /* We use the following syntax to avoid weirdness with '~'. */
-+              if (asprintf(&arg, "--suffix-dels=%s", backup_suffix_dels) < 0)
-+                      goto oom;
-+              args[ac++] = arg;
-+      }
++      if (strcmp(backup_suffix_dels, backup_suffix) != 0)
++              args[ac++] = safe_arg("--suffix-dels", backup_suffix_dels);
++
+       if (checksum_choice)
+               args[ac++] = safe_arg("--checksum-choice", checksum_choice);
+diff --git a/rsync.1.md b/rsync.1.md
+--- a/rsync.1.md
++++ b/rsync.1.md
+@@ -430,7 +430,9 @@ has its own detailed description later in this manpage.
+ --backup, -b             make backups (see --suffix & --backup-dir)
+ --backup-deleted         make backups only of deleted files
+ --backup-dir=DIR         make backups into hierarchy based in DIR
++--backup-dir-dels=DIR    backup removed files into hierarchy based in DIR
+ --suffix=SUFFIX          backup suffix (default ~ w/o --backup-dir)
++--suffix-dels=SUFFIX     set removed-files suffix (def. --suffix w/o b-d-d)
+ --update, -u             skip files that are newer on the receiver
+ --inplace                update destination files in-place
+ --append                 append data onto shorter files
+@@ -1028,6 +1030,11 @@ expand it.
+     daemon is the receiver, the backup dir cannot go outside the module's path
+     hierarchy, so take extra care not to delete it or copy into it.
++0.  `--backup-dir-dels=DIR`
++
++    Works like [`--backup-dir`](#opt) except for deleted files in conjunction
++    with the [`--backup-deleted`](#opt) option.
++
+ 0.  `--suffix=SUFFIX`
  
-       if (checksum_choice) {
-               if (asprintf(&arg, "--checksum-choice=%s", checksum_choice) < 0)
+     This option allows you to override the default backup suffix used with the