+ DSS_ERROR_LOG("%s\n", dss_strerror(-ret));
+ return ret;
+}
+
+/*
+ * We can not use rsync locally if the local user is different from the remote
+ * user or if the src dir is not on the local host (or both).
+ */
+static int use_rsync_locally(char *logname)
+{
+ char *h = conf.remote_host_arg;
+
+ if (strcmp(h, "localhost") && strcmp(h, "127.0.0.1"))
+ return 0;
+ if (conf.remote_user_given && strcmp(conf.remote_user_arg, logname))
+ return 0;
+ return 1;
+}
+
+static void create_rsync_argv(char ***argv, int64_t *num)
+{
+ char *logname, *newest;
+ int i = 0, j;
+ struct snapshot_list sl;
+
+ dss_get_snapshot_list(&sl);
+ newest = name_of_newest_complete_snapshot(&sl);
+ free_snapshot_list(&sl);
+
+ *argv = dss_malloc((15 + conf.rsync_option_given) * sizeof(char *));
+ (*argv)[i++] = dss_strdup("rsync");
+ (*argv)[i++] = dss_strdup("-aq");
+ (*argv)[i++] = dss_strdup("--delete");
+ for (j = 0; j < conf.rsync_option_given; j++)
+ (*argv)[i++] = dss_strdup(conf.rsync_option_arg[j]);
+ if (newest) {
+ DSS_INFO_LOG("using %s as reference snapshot\n", newest);
+ (*argv)[i++] = make_message("--link-dest=../%s", newest);
+ free(newest);
+ } else
+ DSS_INFO_LOG("no previous snapshot found\n");
+ logname = dss_logname();
+ if (use_rsync_locally(logname))
+ (*argv)[i++] = dss_strdup(conf.source_dir_arg);
+ else
+ (*argv)[i++] = make_message("%s@%s:%s/", conf.remote_user_given?
+ conf.remote_user_arg : logname,
+ conf.remote_host_arg, conf.source_dir_arg);
+ 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);
+}
+
+static int create_snapshot(char **argv)
+{
+ int ret, fds[3] = {0, 0, 0};
+ char *name;
+
+ name = incomplete_name(current_snapshot_creation_time);
+ DSS_NOTICE_LOG("creating new snapshot %s\n", name);
+ free(name);
+ ret = dss_exec(&create_pid, argv[0], argv, fds);