diff options
Diffstat (limited to 'mount/umount.c')
-rw-r--r-- | mount/umount.c | 56 |
1 files changed, 49 insertions, 7 deletions
diff --git a/mount/umount.c b/mount/umount.c index 9901a809..a695f0c6 100644 --- a/mount/umount.c +++ b/mount/umount.c @@ -14,6 +14,7 @@ #include "mount_constants.h" #include "sundries.h" #include "getusername.h" +#include "pathnames.h" #include "lomount.h" #include "loop.h" #include "fstab.h" @@ -393,9 +394,9 @@ static struct option longopts[] = static void usage (FILE *fp, int n) { - fprintf (fp, _("Usage: umount [-hV]\n" - " umount -a [-f] [-r] [-n] [-v] [-t vfstypes] [-O opts]\n" - " umount [-f] [-r] [-n] [-v] special | node...\n")); + fprintf (fp, _("Usage: umount -h | -V\n" + " umount -a [-d] [-f] [-r] [-n] [-v] [-t vfstypes] [-O opts]\n" + " umount [-d] [-f] [-r] [-n] [-v] special | node...\n")); exit (n); } @@ -406,7 +407,7 @@ static int contains(const char *list, const char *s) { int n = strlen(s); - while (*list) { + while (list && *list) { if (strncmp(list, s, n) == 0 && (list[n] == 0 || list[n] == ',')) return 1; @@ -423,7 +424,7 @@ get_value(const char *list, const char *s) { const char *t; int n = strlen(s); - while (*list) { + while (list && *list) { if (strncmp(list, s, n) == 0) { s = t = list+n; while (*s && *s != ',') @@ -432,6 +433,44 @@ get_value(const char *list, const char *s) { } while (*list && *list++ != ',') ; } + return NULL; +} + +/* check if @mc contains a loop device which is associated + * with the @file in fs + */ +static int +is_valid_loop(struct mntentchn *mc, struct mntentchn *fs) +{ + unsigned long long offset = 0; + char *p; + + /* check if it begins with /dev/loop */ + if (strncmp(mc->m.mnt_fsname, _PATH_DEV_LOOP, + sizeof(_PATH_DEV_LOOP) - 1)) + return 0; + + /* check for loop option in fstab */ + if (!contains(fs->m.mnt_opts, "loop")) + return 0; + + /* check for offset option in fstab */ + p = get_value(fs->m.mnt_opts, "offset="); + if (p) + offset = strtoull(p, NULL, 10); + + /* check association */ + if (loopfile_used_with((char *) mc->m.mnt_fsname, + fs->m.mnt_fsname, offset) == 1) { + if (verbose > 1) + printf(_("device %s is associated with %s\n"), + mc->m.mnt_fsname, fs->m.mnt_fsname); + return 1; + } + + if (verbose > 1) + printf(_("device %s is not associated with %s\n"), + mc->m.mnt_fsname, fs->m.mnt_fsname); return 0; } @@ -516,12 +555,15 @@ umount_file (char *arg) { the pair (dev,file) in fstab. */ fs = getfs_by_devdir(mc->m.mnt_fsname, mc->m.mnt_dir); if (!fs) { - if (!getfs_by_spec (file) && !getfs_by_dir (file)) + fs = getfs_by_dir(file); + if (!fs && !getfs_by_spec(file)) die (2, _("umount: %s is not in the fstab " "(and you are not root)"), file); - else + + /* spec could be a file which is loop mounted */ + if (fs && !is_valid_loop(mc, fs)) die (2, _("umount: %s mount disagrees with " "the fstab"), file); } |