From: Andre Noll Date: Wed, 15 Nov 2017 18:09:06 +0000 (+0100) Subject: Merge branch 'refs/heads/t/mountpoint' X-Git-Tag: v1.0.0~10 X-Git-Url: http://git.tuebingen.mpg.de/dss.git/log?a=commitdiff_plain;h=c9fd9f2239319b95c46e49b1b7040e1a898cdcf7;hp=-c;p=dss.git Merge branch 'refs/heads/t/mountpoint' A new main option which aborts dss if the destination file system is not mounted. Cooking for two weeks. * refs/heads/t/mountpoint: New option: --mountpoint. --- c9fd9f2239319b95c46e49b1b7040e1a898cdcf7 diff --combined NEWS index fc80e8e,755cad2..75fe3a2 --- a/NEWS +++ b/NEWS @@@ -7,13 -7,10 +7,16 @@@ x.y.z (to be announced - The --no-resume option has been removed. - The gengetopt option parser has been replaced by the - [lopsub](http://people.tuebingen.mpg.de/~maan/lopsub) library. Hence + [lopsub](http://people.tuebingen.mpg.de/maan/lopsub) library. Hence lopsub must be installed to compile this package. Also help2man is no longer required since lopsub has built-in roff support. + - New subcommand "configtest" to check the command line options and + the configuration file for syntactic correctness. + ++ - New option: --mountpoint. If this option is given, dss aborts if ++ no file system is mounted on the destination directory. ++ - "make install" will install the executable and the man page. - In run mode, dss no longer exits successfully if another instance @@@ -24,11 -21,6 +27,11 @@@ - CFLAGS, CPPFLAGS and LDFLAGS can now be used to override the flags of the build system. + - For all subcommands other than "run", timestamps and function names + are omitted from the log output. + + - The dss logo is now created with ImageMagick rather than dia. + ------------------ 0.1.7 (2017-04-17) ------------------ diff --combined dss.c index 6353fbe,3d234ff..bd9e577 --- a/dss.c +++ b/dss.c @@@ -63,8 -63,6 +63,8 @@@ static struct lls_parse_result *cmdline /** Parsed subcommand options. */ static struct lls_parse_result *cmdline_sublpr, *sublpr; +/* The executing subcommand (NULL at startup). */ +static const struct lls_command *subcmd; /** Wether daemon_init() was called. */ static bool daemonized; /** Non-NULL if we log to a file. */ @@@ -244,19 -242,16 +244,19 @@@ __printf_1_2 void dss_log(const char* f if (loglevel < lpr_ll) 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 (lpr_ll <= INFO) - fprintf(outfd, "%i: ", loglevel); + if (subcmd == CMD_PTR(RUN)) { + time(&t1); + tm = localtime(&t1); + strftime(str, sizeof(str), "%b %d %H:%M:%S", tm); + fprintf(outfd, "%s ", str); + if (lpr_ll <= INFO) + fprintf(outfd, "%i: ", loglevel); + } + if (subcmd == CMD_PTR(RUN)) #ifdef DSS_NO_FUNC_NAMES - fprintf(outfd, "%s:%d: ", location_file, location_line); + fprintf(outfd, "%s:%d: ", location_file, location_line); #else - fprintf(outfd, "%s: ", location_func); + fprintf(outfd, "%s: ", location_func); #endif va_start(argp, fmt); vfprintf(outfd, fmt, argp); @@@ -300,7 -295,6 +300,7 @@@ static int send_signal(int sig dss_msg("%d\n", (int)pid); return 0; } + DSS_NOTICE_LOG(("sending signal %d to pid %d\n", sig, (int)pid)); ret = kill(pid, sig); if (ret < 0) return -ERRNO_TO_DSS_ERROR(errno); @@@ -521,7 -515,7 +521,7 @@@ static struct snapshot *find_orphaned_s struct snapshot *s; int i; - DSS_DEBUG_LOG(("looking for orphaned snapshots\n")); + DSS_DEBUG_LOG(("looking for old incomplete snapshots\n")); FOR_EACH_SNAPSHOT(s, i, sl) { if (snapshot_is_being_created(s)) continue; @@@ -735,7 -729,6 +735,7 @@@ static int try_to_free_disk_space(void if (!low_disk_space) goto out; DSS_WARNING_LOG(("disk space low and nothing obvious to remove\n")); + why = "oldest"; victim = find_oldest_removable_snapshot(&sl); if (victim) goto remove; @@@ -1060,20 -1053,39 +1060,39 @@@ static int handle_sigchld(void return -E_BUG; } + /* also checks if . is a mountpoint, if --mountpoint was given */ static int change_to_dest_dir(void) { int ret; const char *dd = OPT_STRING_VAL(DSS, DEST_DIR); + struct stat dot, dotdot; DSS_INFO_LOG(("changing cwd to %s\n", dd)); - if (chdir(dd) >= 0) - return 1; - ret = -ERRNO_TO_DSS_ERROR(errno); - DSS_ERROR_LOG(("could not change cwd to %s\n", dd)); - return ret; + if (chdir(dd) < 0) { + ret = -ERRNO_TO_DSS_ERROR(errno); + DSS_ERROR_LOG(("could not change cwd to %s\n", dd)); + return ret; + } + if (!OPT_GIVEN(DSS, MOUNTPOINT)) + return 0; + if (stat(".", &dot) < 0) { + ret = -ERRNO_TO_DSS_ERROR(errno); + DSS_ERROR_LOG(("could not stat .\n")); + return ret; + } + if (stat("..", &dotdot) < 0) { + ret = -ERRNO_TO_DSS_ERROR(errno); + DSS_ERROR_LOG(("could not stat ..\n")); + return ret; + } + if (dot.st_dev == dotdot.st_dev && dot.st_ino != dotdot.st_ino) { + DSS_ERROR_LOG(("mountpoint check failed for %s\n", dd)); + return -E_MOUNTPOINT; + } + return 1; } -static int check_config(const struct lls_command *cmd) +static int check_config(void) { int ret; uint32_t unit_interval = OPT_UINT32_VAL(DSS, UNIT_INTERVAL); @@@ -1089,13 -1101,13 +1108,13 @@@ DSS_ERROR_LOG(("bad number of intervals: %i\n", num_intervals)); return -E_INVALID_NUMBER; } - if (cmd == CMD_PTR(RUN) || cmd == CMD_PTR(CREATE)) + if (subcmd == CMD_PTR(RUN) || subcmd == CMD_PTR(CREATE)) if (!OPT_GIVEN(DSS, SOURCE_DIR)) { DSS_ERROR_LOG(("--source-dir required\n")); return -E_SYNTAX; } - if (cmd == CMD_PTR(RUN) || cmd == CMD_PTR(CREATE) - || cmd == CMD_PTR(LS) || cmd == CMD_PTR(PRUNE)) { + if (subcmd == CMD_PTR(RUN) || subcmd == CMD_PTR(CREATE) + || subcmd == CMD_PTR(LS) || subcmd == CMD_PTR(PRUNE)) { if (!OPT_GIVEN(DSS, DEST_DIR)) { DSS_ERROR_LOG(("--dest-dir required\n")); return -E_SYNTAX; @@@ -1233,7 -1245,7 +1252,7 @@@ static int handle_sighup(void ret = parse_config_file(true /* SIGHUP */, CMD_PTR(RUN)); if (ret < 0) return ret; - ret = check_config(CMD_PTR(RUN)); + ret = check_config(); if (ret < 0) return ret; close_log(logfile); @@@ -1703,13 -1715,6 +1722,13 @@@ static int com_ls(void } EXPORT_CMD_HANDLER(ls); +static int com_configtest(void) +{ + printf("Syntax Ok\n"); + return 0; +} +EXPORT_CMD_HANDLER(configtest); + static int setup_signal_handling(void) { int ret; @@@ -1751,7 -1756,7 +1770,7 @@@ static void show_subcommand_summary(voi for (i = 1; (cmd = lls_cmd(i, dss_suite)); i++) { const char *name = lls_command_name(cmd); const char *purpose = lls_purpose(cmd); - printf("%-10s%s\n", name, purpose); + printf("%-11s%s\n", name, purpose); } exit(EXIT_SUCCESS); } @@@ -1759,17 -1764,18 +1778,17 @@@ int main(int argc, char **argv) { int ret; - const struct lls_command *cmd = CMD_PTR(DSS); char *errctx = NULL; unsigned num_inputs; - const struct dss_user_data *ud = NULL; + const struct dss_user_data *ud; - ret = lls_parse(argc, argv, cmd, &cmdline_lpr, &errctx); + ret = lls_parse(argc, argv, CMD_PTR(DSS), &cmdline_lpr, &errctx); if (ret < 0) { ret = lopsub_error(ret, &errctx); goto out; } lpr = cmdline_lpr; - ret = parse_config_file(false /* no SIGHUP */, cmd); + ret = parse_config_file(false /* no SIGHUP */, CMD_PTR(DSS)); if (ret < 0) goto out; handle_version_and_help(); @@@ -1781,24 -1787,24 +1800,24 @@@ ret = lopsub_error(ret, &errctx); goto out; } - cmd = lls_cmd(ret, dss_suite); - ret = lls_parse(num_inputs, argv + argc - num_inputs, cmd, + subcmd = lls_cmd(ret, dss_suite); + ret = lls_parse(num_inputs, argv + argc - num_inputs, subcmd, &cmdline_sublpr, &errctx); if (ret < 0) { ret = lopsub_error(ret, &errctx); goto out; } sublpr = cmdline_sublpr; - ret = parse_config_file(false /* no SIGHUP */, cmd); + ret = parse_config_file(false /* no SIGHUP */, subcmd); if (ret < 0) goto out; - ret = check_config(cmd); + ret = check_config(); if (ret < 0) goto out; ret = setup_signal_handling(); if (ret < 0) goto out; - ud = lls_user_data(cmd); + ud = lls_user_data(subcmd); ret = ud->handler(); signal_shutdown(); out: @@@ -1811,8 -1817,8 +1830,8 @@@ lls_free_parse_result(lpr, CMD_PTR(DSS)); if (lpr != cmdline_lpr) lls_free_parse_result(cmdline_lpr, CMD_PTR(DSS)); - lls_free_parse_result(sublpr, cmd); + lls_free_parse_result(sublpr, subcmd); if (sublpr != cmdline_sublpr) - lls_free_parse_result(cmdline_sublpr, cmd); + lls_free_parse_result(cmdline_sublpr, subcmd); exit(ret >= 0? EXIT_SUCCESS : EXIT_FAILURE); } diff --combined dss.suite index 95dd30f,1e62acf..1e79870 --- a/dss.suite +++ b/dss.suite @@@ -34,7 -34,7 +34,7 @@@ caption = Subcommand However, there is one exception to this rule: The run subcommand re-reads the configuration file when it receives the HUP signal. In this case the options in the config file override any options that - were previously given at the command line. This allows to change the + were previously given at the command line. This allows changing the configuration of a running dss process by sending SIGHUP. [/help] [option loglevel] @@@ -79,6 -79,18 +79,18 @@@ This option is mandatory for all subcommands except kill. [/help] + [option mountpoint] + summary = abort if destination directory is not a mountpoint + [help] + This option checks whether a file system is mounted on the directory + specified as the argument to --dest-dir. Operation proceeds only + if this is the case. Otherwise dss exits unsuccessfully without + performing any action. Use this option to prevent snapshot creation + if the snapshot file system is not mounted. + + This option is silently ignored for subcommands which do not depend + on the destination directory. + [/help] [option Rsync-options] summary = Controlling how rsync is run flag ignored @@@ -312,8 -324,8 +324,8 @@@ typestr = percent default_val = 2 [help] - This is like --min-free-mb but allows to specify the amount of - free disk space as a percentage. It is not recommended to set both + This is like --min-free-mb but the amount of free disk space + is specified as a percentage. It is not recommended to set both --min-free-mb and --min-free-percent to zero as this will cause your file system to fill up quickly. [/help] @@@ -475,14 -487,6 +487,14 @@@ Sending SIGHUP causes the running dss process to reload its config file. [/help] +[subcommand configtest] + purpose = run a configuration file syntax test + [description] + This command checks the command line options and the configuration + file for syntactic correctness. It either reports "Syntax Ok" and + exits successfully or prints information about the first syntax error + detected and terminates with exit code 1. + [/description] [section copyright] Written by Andre Noll