]> git.tuebingen.mpg.de Git - dss.git/commitdiff
Merge branch 'refs/heads/t/multiple-source-dirs'
authorAndre Noll <maan@tuebingen.mpg.de>
Wed, 18 Sep 2019 08:33:29 +0000 (10:33 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Wed, 18 Sep 2019 08:33:29 +0000 (10:33 +0200)
Was cooking for more than a year.

* refs/heads/t/multiple-source-dirs:
  create_rsync_argv(): Allocate correctly sized arg array.
  Support multiple source directories.

1  2 
dss.c

diff --combined dss.c
index 217f22e36f8d1b36f65874a9336635946376cdb5,b6a3d3e714059861ab1ae100933655b7e4e13c50..a219cfd37b4569fbc3aa67fb2d4443a950353197
--- 1/dss.c
--- 2/dss.c
+++ b/dss.c
@@@ -81,7 -81,7 +81,7 @@@ static int64_t next_snapshot_time
  static struct timeval next_removal_check;
  /** Creation time of the snapshot currently being created. */
  static int64_t current_snapshot_creation_time;
 -/** The snapshot currently being removed. */
 +/* Set by the pre-rm hook, cleared by handle_remove_exit(). */
  struct snapshot *snapshot_currently_being_removed;
  /** Needed by the post-create hook. */
  static char *path_to_last_complete_snapshot;
@@@ -574,6 -574,9 +574,6 @@@ static int is_reference_snapshot(struc
        return strcmp(s->name, name_of_reference_snapshot)? 0 : 1;
  }
  
 -/*
 - * return: 0: no redundant snapshots, 1: rm process started, negative: error
 - */
  static struct snapshot *find_redundant_snapshot(struct snapshot_list *sl)
  {
        int i, interval;
@@@ -1383,7 -1386,7 +1383,7 @@@ out
  static void create_rsync_argv(char ***argv, int64_t *num)
  {
        char *logname;
-       int i = 0, j, N = OPT_GIVEN(DSS, RSYNC_OPTION);
+       int i = 0, j, N;
        struct snapshot_list sl;
        static bool seeded;
  
        name_of_reference_snapshot = name_of_newest_complete_snapshot(&sl);
        free_snapshot_list(&sl);
  
-       *argv = dss_malloc((15 + N) * sizeof(char *));
+       /*
+        * We specify up to 6 arguments, one argument per given rsync option
+        * and one argument per given source dir. We also need space for the
+        * terminating NULL pointer.
+        */
+       N = OPT_GIVEN(DSS, RSYNC_OPTION) + OPT_GIVEN(DSS, SOURCE_DIR);
+       *argv = dss_malloc((7 + N) * sizeof(char *));
        (*argv)[i++] = dss_strdup("rsync");
        (*argv)[i++] = dss_strdup("-a");
        (*argv)[i++] = dss_strdup("--delete");
                DSS_NOTICE_LOG(("adding --checksum to rsync options\n"));
                (*argv)[i++] = dss_strdup("--checksum");
        }
-       for (j = 0; j < N; j++)
+       for (j = 0; j < OPT_GIVEN(DSS, RSYNC_OPTION); j++)
                (*argv)[i++] = dss_strdup(lls_string_val(j,
                        OPT_RESULT(DSS, RSYNC_OPTION)));
        if (name_of_reference_snapshot) {
        } else
                DSS_INFO_LOG(("no suitable reference snapshot found\n"));
        logname = dss_logname();
-       if (use_rsync_locally(logname))
-               (*argv)[i++] = dss_strdup(OPT_STRING_VAL(DSS, SOURCE_DIR));
-       else
-               (*argv)[i++] = make_message("%s@%s:%s/",
-                       OPT_GIVEN(DSS, REMOTE_USER)?
-                               OPT_STRING_VAL(DSS, REMOTE_USER) : logname,
-                       OPT_STRING_VAL(DSS, REMOTE_HOST),
-                       OPT_STRING_VAL(DSS, SOURCE_DIR));
+       if (use_rsync_locally(logname)) {
+               for (j = 0; j < OPT_GIVEN(DSS, SOURCE_DIR); j++)
+                       (*argv)[i++] = dss_strdup(lls_string_val(j,
+                               OPT_RESULT(DSS, SOURCE_DIR)));
+       } else {
+               /*
+                * dss-1.0 and earlier did not support multiple source
+                * directories.  These versions appended a slash to the end of
+                * the source directory to make sure that only the contents of
+                * the single source directory, but not the directory itself,
+                * are copied to the destination. For multiple source
+                * directories, however, this is not a good idea because the
+                * source directories may well contain identical file names,
+                * which would then be copied to the same location on the
+                * destination, overwriting each other. Moreover, we want the
+                * directory on the destination match the source. To preserve
+                * the old behaviour, we thus have to special-case N=1.
+                */
+               for (j = 0; j < OPT_GIVEN(DSS, SOURCE_DIR); j++) {
+                       (*argv)[i++] = make_message("%s@%s:%s%s",
+                               OPT_GIVEN(DSS, REMOTE_USER)?
+                                       OPT_STRING_VAL(DSS, REMOTE_USER) : logname,
+                               OPT_STRING_VAL(DSS, REMOTE_HOST),
+                               lls_string_val(j, OPT_RESULT(DSS, SOURCE_DIR)),
+                               N == 1? "/" : ""
+                       );
+               }
+       }
        free(logname);
        *num = get_current_time();
        (*argv)[i++] = incomplete_name(*num);