+ dss_get_snapshot_list(&sl);
+ assert(!name_of_reference_snapshot);
+ name_of_reference_snapshot = name_of_newest_complete_snapshot(&sl);
+ free_snapshot_list(&sl);
+
+ /*
+ * 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");
+ if (!seeded) {
+ srandom((unsigned)time(NULL)); /* no need to be fancy here */
+ seeded = true;
+ }
+ if (1000 * (random() / (RAND_MAX + 1.0)) < OPT_UINT32_VAL(DSS, CHECKSUM)) {
+ DSS_NOTICE_LOG(("adding --checksum to rsync options\n"));
+ (*argv)[i++] = dss_strdup("--checksum");
+ }
+ 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) {
+ DSS_INFO_LOG(("using %s as reference\n", name_of_reference_snapshot));
+ (*argv)[i++] = make_message("--link-dest=../%s",
+ name_of_reference_snapshot);
+ } else
+ DSS_INFO_LOG(("no suitable reference snapshot found\n"));
+ logname = dss_logname();
+ 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);
+ (*argv)[i++] = NULL;
+ for (j = 0; j < i; j++)
+ DSS_DEBUG_LOG(("argv[%d] = %s\n", j, (*argv)[j]));
+}
+
+static void free_rsync_argv(char **argv)
+{
+ int i;
+
+ if (!argv)
+ return;
+ for (i = 0; argv[i]; i++)
+ free(argv[i]);
+ free(argv);