X-Git-Url: http://git.tuebingen.mpg.de/?p=dss.git;a=blobdiff_plain;f=dss.c;h=f65a29f37720d6dcb6c9ce44965c376d2afaafcf;hp=0913301386fefacfda2bcef9016cce9513983ebd;hb=a31c35b86e485c6c1feeaf9e1957e3d3ab52c7e5;hpb=c418d2188c9c2c542270023d6fc3bc6cf34f8d29 diff --git a/dss.c b/dss.c index 0913301..f65a29f 100644 --- a/dss.c +++ b/dss.c @@ -22,36 +22,34 @@ #include "error.h" #include "fd.h" #include "exec.h" +#include "daemon.h" struct gengetopt_args_info conf; char *dss_error_txt = NULL; +static FILE *logfile; DEFINE_DSS_ERRLIST; -/** Defines one dss command. */ -struct server_command { - /** The name of the command. */ - const char *name; - /** Pointer to the function that handles the command. */ - int (*handler)(int, char * const * const); -}; /* a litte cpp magic helps to DRY */ -#define SERVER_COMMANDS \ - SERVER_COMMAND(ls) \ - SERVER_COMMAND(create) \ - SERVER_COMMAND(prune) \ - SERVER_COMMAND(daemon) -#define SERVER_COMMAND(x) int com_ ##x(int, char * const * const); -SERVER_COMMANDS -#undef SERVER_COMMAND -#define SERVER_COMMAND(x) {.name = #x, .handler = com_ ## x}, -static struct server_command command_list[] = { - SERVER_COMMANDS - {.name = NULL, .handler = NULL} -}; -#undef SERVER_COMMAND +#define COMMANDS \ + COMMAND(ls) \ + COMMAND(create) \ + COMMAND(prune) \ + COMMAND(run) +#define COMMAND(x) int com_ ##x(void); +COMMANDS +#undef COMMAND +#define COMMAND(x) if (conf.x ##_given) return com_ ##x(); +int call_command_handler(void) +{ + COMMANDS + DSS_EMERG_LOG("BUG: did not find command handler\n"); + exit(EXIT_FAILURE); +} +#undef COMMAND +#undef COMMANDS /* * complete, not being deleted: 1204565370-1204565371.Sun_Mar_02_2008_14_33-Sun_Mar_02_2008_14_43 @@ -72,6 +70,40 @@ struct snapshot { unsigned interval; }; +__printf_2_3 void dss_log(int ll, const char* fmt,...) +{ + va_list argp; + FILE *outfd; + struct tm *tm; + time_t t1; + char str[255] = ""; + + if (ll < conf.loglevel_arg) + return; + outfd = logfile? logfile : stderr; + time(&t1); + tm = localtime(&t1); + strftime(str, sizeof(str), "%b %d %H:%M:%S", tm); + fprintf(outfd, "%s ", str); + if (conf.loglevel_arg <= INFO) + fprintf(outfd, "%i: ", ll); + va_start(argp, fmt); + vfprintf(outfd, fmt, argp); + va_end(argp); +} + +/** + * Print a message either to stdout or to the log file. + */ +__printf_1_2 void dss_msg(const char* fmt,...) +{ + FILE *outfd = conf.daemon_given? logfile : stdout; + va_list argp; + va_start(argp, fmt); + vfprintf(outfd, fmt, argp); + va_end(argp); +} + int is_snapshot(const char *dirname, int64_t now, struct snapshot *s) { int i, ret; @@ -312,8 +344,7 @@ out: return ret; } -int remove_redundant_snapshot(struct snapshot_list *sl, - int dry_run, pid_t *pid) +int remove_redundant_snapshot(struct snapshot_list *sl, pid_t *pid) { int ret, i, interval; struct snapshot *s; @@ -360,8 +391,8 @@ int remove_redundant_snapshot(struct snapshot_list *sl, prev = s; } assert(victim); - if (dry_run) { - printf("%s would be removed (interval = %i)\n", + if (conf.dry_run_given) { + dss_msg("%s would be removed (interval = %i)\n", victim->name, victim->interval); continue; } @@ -371,7 +402,7 @@ int remove_redundant_snapshot(struct snapshot_list *sl, return 0; } -int remove_old_snapshot(struct snapshot_list *sl, int dry_run, pid_t *pid) +int remove_old_snapshot(struct snapshot_list *sl, pid_t *pid) { int i, ret; struct snapshot *s; @@ -381,8 +412,8 @@ int remove_old_snapshot(struct snapshot_list *sl, int dry_run, pid_t *pid) FOR_EACH_SNAPSHOT(s, i, sl) { if (s->interval <= conf.num_intervals_arg) continue; - if (dry_run) { - printf("%s would be removed (interval = %i)\n", + if (conf.dry_run_given) { + dss_msg("%s would be removed (interval = %i)\n", s->name, s->interval); continue; } @@ -413,26 +444,24 @@ int wait_for_rm_process(pid_t pid) return 1; } -int com_prune(int argc, char * const * argv) +int com_run(void) { - int ret, dry_run = 0; + if (conf.dry_run_given) { + make_err_msg("dry_run not supported by this command"); + return -E_SYNTAX; + } + return 42; +} + +int com_prune(void) +{ + int ret; struct snapshot_list sl; pid_t pid; - if (argc > 2) { - make_err_msg("too many arguments"); - return -E_SYNTAX; - } - if (argc == 2) { - if (strcmp(argv[1], "-d")) { - make_err_msg("%s", argv[1]); - return -E_SYNTAX; - } - dry_run = 1; - } for (;;) { get_snapshot_list(&sl); - ret = remove_old_snapshot(&sl, dry_run, &pid); + ret = remove_old_snapshot(&sl, &pid); free_snapshot_list(&sl); if (ret < 0) return ret; @@ -444,7 +473,7 @@ int com_prune(int argc, char * const * argv) } for (;;) { get_snapshot_list(&sl); - ret = remove_redundant_snapshot(&sl, dry_run, &pid); + ret = remove_redundant_snapshot(&sl, &pid); free_snapshot_list(&sl); if (ret < 0) return ret; @@ -560,19 +589,27 @@ int rename_incomplete_snapshot(int64_t start) return ret; } -int com_create(int argc, __a_unused char * const * argv) +int com_create(void) { int ret, status, es; char **rsync_argv; int64_t snapshot_num; pid_t pid; - if (argc != 1) { - ret = -E_SYNTAX; - make_err_msg("create: no args expected, %d given", argc - 1); - return ret; - } create_rsync_argv(&rsync_argv, &snapshot_num); + if (conf.dry_run_given) { + int i; + char *msg = NULL; + for (i = 0; rsync_argv[i]; i++) { + char *tmp = msg; + msg = make_message("%s%s%s", tmp? tmp : "", + tmp? " " : "", rsync_argv[i]); + free(tmp); + } + dss_msg("%s\n", msg); + free(msg); + return 1; + } DSS_NOTICE_LOG("creating snapshot %lli\n", (long long)snapshot_num); ret = create_snapshot(rsync_argv, &pid); if (ret < 0) @@ -597,19 +634,14 @@ out: return ret; } -int com_ls(int argc, __a_unused char * const * argv) +int com_ls(void) { - int i, ret; + int i; struct snapshot_list sl; struct snapshot *s; - if (argc != 1) { - ret = -E_SYNTAX; - make_err_msg("ls: no args expected, %d given", argc - 1); - return ret; - } get_snapshot_list(&sl); FOR_EACH_SNAPSHOT(s, i, &sl) - printf("%u\t%s\n", s->interval, s->name); + dss_msg("%u\t%s\n", s->interval, s->name); free_snapshot_list(&sl); return 1; } @@ -622,16 +654,6 @@ __noreturn void clean_exit(int status) exit(status); } -__printf_2_3 void dss_log(int ll, const char* fmt,...) -{ - va_list argp; - if (ll < conf.loglevel_arg) - return; - va_start(argp, fmt); - vfprintf(stderr, fmt, argp); - va_end(argp); -} - int read_config_file(void) { int ret; @@ -688,12 +710,12 @@ int check_config(void) int main(int argc, char **argv) { - int i, ret; + int ret; cmdline_parser(argc, argv, &conf); /* aborts on errors */ - if (!conf.inputs_num) { + if (conf.inputs_num) { ret = -E_SYNTAX; - make_err_msg("no command given"); + make_err_msg("additional non-options given"); goto out; } ret = read_config_file(); @@ -702,17 +724,16 @@ int main(int argc, char **argv) ret = check_config(); if (ret < 0) goto out; + if (conf.logfile_given) { + logfile = open_log(conf.logfile_arg); + log_welcome(conf.loglevel_arg); + } + if (conf.daemon_given) + daemon_init(); ret = dss_chdir(conf.dest_dir_arg); if (ret < 0) goto out; - for (i = 0; command_list[i].name; i++) { - if (strcmp(command_list[i].name, conf.inputs[0])) - continue; - ret = command_list[i].handler(conf.inputs_num, conf.inputs); - goto out; - } - ret = -E_INVALID_COMMAND; - make_err_msg("%s", conf.inputs[0]); + ret = call_command_handler(); out: if (ret < 0) log_err_msg(EMERG, -ret);