+ ret = wait_for_remove_process();
+ if (ret < 0)
+ goto out;
+ if (snapshot_removal_status != HS_SUCCESS)
+ goto out;
+ post_remove_hook();
+ if (snapshot_removal_status != HS_POST_RUNNING)
+ goto out;
+ ret = wait_for_remove_process();
+ if (ret < 0)
+ goto out;
+ ret = 1;
+out:
+ free_snapshot_list(&sl);
+ return ret;
+}
+
+static int com_create(void)
+{
+ int ret, status;
+ char **rsync_argv;
+
+ lock_dss_or_die();
+ if (conf.dry_run_given) {
+ int i;
+ char *msg = NULL;
+ create_rsync_argv(&rsync_argv, ¤t_snapshot_creation_time);
+ for (i = 0; rsync_argv[i]; i++) {
+ char *tmp = msg;
+ msg = make_message("%s%s%s", tmp? tmp : "",
+ tmp? " " : "", rsync_argv[i]);
+ free(tmp);
+ }
+ free_rsync_argv(rsync_argv);
+ dss_msg("%s\n", msg);
+ free(msg);
+ return 1;
+ }
+ pre_create_hook();
+ if (create_pid) {
+ ret = wait_for_process(create_pid, &status);
+ if (ret < 0)
+ return ret;
+ ret = handle_pre_create_hook_exit(status);
+ if (ret <= 0) /* error, or pre-create failed */
+ return ret;
+ }
+ create_rsync_argv(&rsync_argv, ¤t_snapshot_creation_time);
+ ret = create_snapshot(rsync_argv);
+ if (ret < 0)
+ goto out;
+ ret = wait_for_process(create_pid, &status);
+ if (ret < 0)
+ goto out;
+ ret = handle_rsync_exit(status);
+ if (ret < 0)
+ goto out;
+ post_create_hook();
+ if (create_pid)
+ ret = wait_for_process(create_pid, &status);
+out:
+ free_rsync_argv(rsync_argv);
+ return ret;
+}
+
+static int com_ls(void)
+{
+ int i;
+ struct snapshot_list sl;
+ struct snapshot *s;
+
+ dss_get_snapshot_list(&sl);
+ FOR_EACH_SNAPSHOT(s, i, &sl) {
+ int64_t d = 0;
+ if (s->flags & SS_COMPLETE)
+ d = (s->completion_time - s->creation_time) / 60;
+ dss_msg("%u\t%s\t%3" PRId64 ":%02" PRId64 "\n", s->interval, s->name, d/60, d%60);
+ }
+ free_snapshot_list(&sl);
+ return 1;
+}
+
+static int setup_signal_handling(void)
+{
+ int ret;
+
+ DSS_INFO_LOG(("setting up signal handlers\n"));
+ signal_pipe = signal_init(); /* always successful */
+ ret = install_sighandler(SIGINT);
+ if (ret < 0)
+ return ret;
+ ret = install_sighandler(SIGTERM);
+ if (ret < 0)
+ return ret;
+ return install_sighandler(SIGCHLD);
+}
+
+/**
+ * The main function of dss.
+ *
+ * \param argc Usual argument count.
+ * \param argv Usual argument vector.
+ */
+int main(int argc, char **argv)
+{
+ int ret;
+ struct cmdline_parser_params params;
+
+ params.override = 0;
+ params.initialize = 1;
+ params.check_required = 0;
+ params.check_ambiguity = 0;
+ params.print_errors = 1;
+
+ cmdline_parser_ext(argc, argv, &conf, ¶ms); /* aborts on errors */
+ ret = parse_config_file(0);
+ if (ret < 0)
+ goto out;
+ if (ret == 0) { /* no config file given */
+ /*
+ * Parse the command line options again, but this time check
+ * that all required options are given.
+ */
+ struct cmdline_parser_params params;
+ params.override = 1;
+ params.initialize = 1;
+ params.check_required = 1;
+ params.check_ambiguity = 1;
+ params.print_errors = 1;
+ cmdline_parser_ext(argc, argv, &conf, ¶ms); /* aborts on errors */