From 6d56251220954f4937c9fafbcdb427d4aa50d330 Mon Sep 17 00:00:00 2001 From: Sami Kerola Date: Fri, 2 Aug 2019 19:39:05 +0100 Subject: mountpoint: add --nofollow option 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 --- bash-completion/mountpoint | 2 +- sys-utils/mountpoint.1 | 7 ++++++- sys-utils/mountpoint.c | 19 ++++++++++++++++--- tests/expected/misc/mountpoint | 9 +++++++++ tests/ts/misc/mountpoint | 27 +++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 tests/expected/misc/mountpoint create mode 100755 tests/ts/misc/mountpoint diff --git a/bash-completion/mountpoint b/bash-completion/mountpoint index f14327ce2..15c6d2314 100644 --- a/bash-completion/mountpoint +++ b/bash-completion/mountpoint @@ -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 ;; diff --git a/sys-utils/mountpoint.1 b/sys-utils/mountpoint.1 index afc469ebc..6669b13eb 100644 --- a/sys-utils/mountpoint.1 +++ b/sys-utils/mountpoint.1 @@ -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 diff --git a/sys-utils/mountpoint.c b/sys-utils/mountpoint.c index 985130cba..052440bd4 100644 --- a/sys-utils/mountpoint.c +++ b/sys-utils/mountpoint.c @@ -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 index 000000000..e7c20cd25 --- /dev/null +++ b/tests/expected/misc/mountpoint @@ -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 index 000000000..0b93a9c36 --- /dev/null +++ b/tests/ts/misc/mountpoint @@ -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 -- cgit v1.2.3-55-g7522