New option: --mountpoint.
authorAndre Noll <maan@tuebingen.mpg.de>
Mon, 16 Oct 2017 15:19:08 +0000 (17:19 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Sat, 21 Oct 2017 11:06:45 +0000 (13:06 +0200)
The new option applies to run, create, ls and prune. The feature
could be implemented as a pre-create hook, but since it is so common,
it makes sense to add it to dss proper.

As for the implementation we simply check that "." and ".." are on
different devices (or are identical).

dss.c
dss.suite
err.h

diff --git a/dss.c b/dss.c
index 3e626ab..3d234ff 100644 (file)
--- a/dss.c
+++ b/dss.c
@@ -1053,17 +1053,36 @@ 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)
index e69cc28..1e62acf 100644 (file)
--- a/dss.suite
+++ b/dss.suite
@@ -79,6 +79,18 @@ caption = Subcommands
 
                        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
diff --git a/err.h b/err.h
index 3d4e136..e747bf3 100644 (file)
--- a/err.h
+++ b/err.h
@@ -48,6 +48,7 @@ static inline char *dss_strerror(int num)
        DSS_ERROR(INVALID_NUMBER, "invalid number"), \
        DSS_ERROR(STRFTIME, "strftime() failed"), \
        DSS_ERROR(LOCALTIME, "localtime() failed"), \
+       DSS_ERROR(MOUNTPOINT, "destination directory is no mountpoint"), \
        DSS_ERROR(NULL_OPEN, "can not open /dev/null"), \
        DSS_ERROR(DUP_PIPE, "exec error: can not create pipe"), \
        DSS_ERROR(INVOLUNTARY_EXIT, "unexpected termination cause"), \