Updated mountpoint to search for circular mount points when using

the -p parameter. This works around mountpoint not recognizing
circular mounts where /a/b/c/d and /a/b are the same location
(ie the same device and same inode).
Closes Savannah bug #37114.
This commit is contained in:
Jesse Smith 2018-03-07 16:25:53 -04:00
parent a3f38afc34
commit 8c8172349e
3 changed files with 78 additions and 2 deletions

View File

@ -1,6 +1,11 @@
sysvinit (2.89) UNRELEASED; urgency=low
[ Jesse Smith ]
* Updated mountpoint command with -p flag. The -p flag causes
mountpoint to search for circular mount points. For example, if
/a/b/c/d is a mount point for /a/b then the former is a valid
mount point. This only works on Linux since it uses /proc/mounts.
Updated manual page to match. This fix closes Savannah bug #37114.
* Removed two sleep calls when we are doing sync anyway to make sure
data is being written. Speeds up reboot time by about two seconds.
* Fixed Clang compiler warning regarding variable data parameters to sprintf().

View File

@ -48,6 +48,19 @@ The name of the command is misleading when the -x option is used,
but the option is useful for comparing if a directory and a device
match up, and there is no other command that can print the info easily.
.PP
The mountpoint command fails when a directory is binded to one of its grandparents.
For example, if /a/b/c/d is a mount point for /a/b then mountpoint will report
/a/b/c/d is not a valid mount point. This is because both the original directory and
its new mount point share the same inode and device number.
.PP
The circular mount problem can be worked around on Linux systems by using
the -p flag to check the /proc/mounts file for references to the circular mount bind.
When using the -p flag, make sure to specify the full path (ie /home/user/mp and
not just mp). Also, mountpoint may still fail if there are spaces in
the mount point's path, even when using the -p flag because of the way
/proc/mounts mangles the spaces in the path name. Of course, if the
admin is using circular mount points with spaces in the name, there
are bigger concerns.
.SH AUTHOR
Miquel van Smoorenburg, miquels@cistron.nl
.SH "SEE ALSO"

View File

@ -50,8 +50,55 @@ int dostat(char *path, struct stat *st, int do_lstat, int quiet)
return 0;
}
/*
This function checks to see if the passed path is listed in the
/proc/mounts file. If /proc/mounts does not exist or cannot
be read, we return false. If the path is nout found, we return false.
If the path is found we return true.
*/
int do_proc_check(char *path)
{
FILE *mounts;
char *found = NULL, *status;
char *target_string;
char line[512];
int last_character;
target_string = (char *) calloc( strlen(path) + 3, sizeof(char));
if (! target_string)
return 0;
mounts = fopen("/proc/mounts", "r");
if (! mounts)
{
free(target_string);
return 0;
}
/* copy path so we can adjust it without harming the original */
sprintf(target_string, "%s", path);
/* trim trailing slash */
last_character = strlen(target_string) - 1;
if ( (last_character >= 1) && (target_string[last_character] == '/') )
target_string[last_character] = '\0';
/* Search for path name in /proc/mounts file */
status = fgets(line, 512, mounts);
while ( (status) && (! found) )
{
found = strstr(line, target_string);
if (! found)
status = fgets(line, 512, mounts);
}
fclose(mounts);
free(target_string);
return found ? 1 : 0;
}
void usage(void) {
fprintf(stderr, "Usage: mountpoint [-q] [-d] [-x] path\n");
fprintf(stderr, "Usage: mountpoint [-p] [-q] [-d] [-x] path\n");
exit(1);
}
@ -64,11 +111,15 @@ int main(int argc, char **argv)
int showdev = 0;
int xdev = 0;
int c, r;
int check_proc = 0;
while ((c = getopt(argc, argv, "dqx")) != EOF) switch(c) {
while ((c = getopt(argc, argv, "dpqx")) != EOF) switch(c) {
case 'd':
showdev = 1;
break;
case 'p':
check_proc = 1;
break;
case 'q':
quiet = 1;
break;
@ -118,6 +169,13 @@ int main(int argc, char **argv)
r = (st.st_dev != st2.st_dev) ||
(st.st_dev == st2.st_dev && st.st_ino == st2.st_ino);
/* Mount point was not found yet. If we have access
to /proc we can check there too. */
if ( (!r) && (check_proc) )
{
if ( do_proc_check(path) )
r = 1;
}
if (!quiet && !showdev)
printf("%s is %sa mountpoint\n", path, r ? "" : "not ");