]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
mountpoint: add --nofollow option
authorSami Kerola <kerolasa@iki.fi>
Fri, 2 Aug 2019 18:39:05 +0000 (19:39 +0100)
committerSami Kerola <kerolasa@iki.fi>
Fri, 2 Aug 2019 18:39:05 +0000 (19:39 +0100)
The no follow option will allow user to distinct mount points from symbolic
links pointing to them.  Arguably this is pretty pedantic option, mounting a
device or bind mount to a directory via symlink does not have or cause any
issues.

Addresses: https://github.com/karelzak/util-linux/issues/832
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
bash-completion/mountpoint
sys-utils/mountpoint.1
sys-utils/mountpoint.c
tests/expected/misc/mountpoint [new file with mode: 0644]
tests/ts/misc/mountpoint [new file with mode: 0755]

index f14327ce20b4cb1fdfaf52bf96dba55123f49891..15c6d2314aaf31c42f389b616257dbc064e3a309 100644 (file)
@@ -11,7 +11,7 @@ _mountpoint_module()
        esac
        case $cur in
                -*)
-                       OPTS="--quiet --fs-devno --devno --help --version"
+                       OPTS="--quiet --nofollow --fs-devno --devno --help --version"
                        COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) )
                        return 0
                        ;;
index afc469ebcaa6686bb85507cacdb9281f605357bb..6669b13ebc9cdb942a50cbe9fe4c3d240f621818 100644 (file)
@@ -1,4 +1,4 @@
-.TH MOUNTPOINT 1 "July 2014" "util-linux" "User Commands"
+.TH MOUNTPOINT 1 "August 2019" "util-linux" "User Commands"
 .SH NAME
 mountpoint \- see if a directory or file is a mountpoint
 .SH SYNOPSIS
@@ -28,6 +28,11 @@ directory.
 .BR \-q , " \-\-quiet"
 Be quiet - don't print anything.
 .TP
+.B "\-\-nofollow"
+Do not follow symbolic link if it the last elemnt of the
+.I directory
+path.
+.TP
 .BR \-x , " \-\-devno"
 Show the major/minor numbers of the given blockdevice on standard output.
 .TP
index 985130cba279e02469f81ce375d499cf5c986083..052440bd4f43f49a1161f24aa73a330b405d0301 100644 (file)
@@ -47,6 +47,7 @@ struct mountpoint_control {
        unsigned int
                dev_devno:1,
                fs_devno:1,
+               nofollow:1,
                quiet:1;
 };
 
@@ -123,6 +124,7 @@ static void __attribute__((__noreturn__)) usage(void)
 
        fputs(USAGE_OPTIONS, out);
        fputs(_(" -q, --quiet        quiet mode - don't print anything\n"
+               "     --nofollow     do not follow symlink\n"
                " -d, --fs-devno     print maj:min device number of the filesystem\n"
                " -x, --devno        print maj:min device number of the block device\n"), out);
        fputs(USAGE_SEPARATOR, out);
@@ -137,8 +139,13 @@ int main(int argc, char **argv)
        int c;
        struct mountpoint_control ctl = { NULL };
 
+       enum {
+               OPT_NOFOLLOW = CHAR_MAX + 1
+       };
+
        static const struct option longopts[] = {
                { "quiet",    no_argument, NULL, 'q' },
+               { "nofollow", no_argument, NULL, OPT_NOFOLLOW },
                { "fs-devno", no_argument, NULL, 'd' },
                { "devno",    no_argument, NULL, 'x' },
                { "help",     no_argument, NULL, 'h' },
@@ -159,6 +166,9 @@ int main(int argc, char **argv)
                case 'q':
                        ctl.quiet = 1;
                        break;
+               case OPT_NOFOLLOW:
+                       ctl.nofollow = 1;
+                       break;
                case 'd':
                        ctl.fs_devno = 1;
                        break;
@@ -179,17 +189,20 @@ int main(int argc, char **argv)
                warnx(_("bad usage"));
                errtryhelp(EXIT_FAILURE);
        }
+       if (ctl.nofollow && ctl.dev_devno)
+               errx(EXIT_FAILURE, _("%s and %s are mutually exclusive"),
+                    "--devno", "--nofollow");
 
        ctl.path = argv[optind];
-
-       if (stat(ctl.path, &ctl.st)) {
+       c = ctl.nofollow ? lstat(ctl.path, &ctl.st) : stat(ctl.path, &ctl.st);
+       if (c) {
                if (!ctl.quiet)
                        err(EXIT_FAILURE, "%s", ctl.path);
                return EXIT_FAILURE;
        }
        if (ctl.dev_devno)
                return print_devno(&ctl) ? EXIT_FAILURE : EXIT_SUCCESS;
-       if (dir_to_device(&ctl)) {
+       if ((ctl.nofollow && S_ISLNK(ctl.st.st_mode)) || dir_to_device(&ctl)) {
                if (!ctl.quiet)
                        printf(_("%s is not a mountpoint\n"), ctl.path);
                return EXIT_FAILURE;
diff --git a/tests/expected/misc/mountpoint b/tests/expected/misc/mountpoint
new file mode 100644 (file)
index 0000000..e7c20cd
--- /dev/null
@@ -0,0 +1,9 @@
+default
+./symlink-to-root is a mountpoint
+0
+try --nofollow
+./symlink-to-root is not a mountpoint
+1
+mutually exclusive
+mountpoint: --devno and --nofollow are mutually exclusive
+1
diff --git a/tests/ts/misc/mountpoint b/tests/ts/misc/mountpoint
new file mode 100755 (executable)
index 0000000..0b93a9c
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="mountpoint"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_CMD_MOUNTPOINT"
+
+ln -s / ./symlink-to-root
+
+echo "default" >> $TS_OUTPUT 2>&1
+$TS_CMD_MOUNTPOINT ./symlink-to-root >> $TS_OUTPUT 2>&1
+echo $? >> $TS_OUTPUT 2>&1
+
+echo "try --nofollow" >> $TS_OUTPUT 2>&1
+$TS_CMD_MOUNTPOINT --nofollow ./symlink-to-root >> $TS_OUTPUT 2>&1
+echo $? >> $TS_OUTPUT 2>&1
+
+echo "mutually exclusive" >> $TS_OUTPUT 2>&1
+$TS_CMD_MOUNTPOINT --devno --nofollow / >> $TS_OUTPUT 2>&1
+echo $? >> $TS_OUTPUT 2>&1
+
+rm -f ./symlink-to-root
+
+ts_finalize