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 <kerolasa@iki.fi>
This commit is contained in:
Sami Kerola 2019-08-02 19:39:05 +01:00
parent 3661aab4cf
commit 6d56251220
No known key found for this signature in database
GPG Key ID: 0D46FEF7E61DBB46
5 changed files with 59 additions and 5 deletions

View 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
;;

View 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

View 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;

View File

@ -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

27
tests/ts/misc/mountpoint Executable file
View File

@ -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