From 3564ebbf04b70188cda3fe679294ca7ad5f2a927 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Mon, 29 Aug 2011 12:29:36 -0400 Subject: [PATCH] umount.nfs: fix nfs4 check From: Ian Kent nfs_umount_is_vers4() doesn't take acount of the escaping of characters seen in /proc/mounts and /etc/mtab as the functions in fstab.c do. This leads to an inability to umount a mount containing any of these escaped characters (like spaces). This patch changes nfs_umount_is_vers4() to use functions in fstab.c and adds a function to fstab.c to read /proc/mounts specifically, as it was used for the check in nfs_umount_is_vers4() previously. Signed-off-by: Ian Kent Signed-off-by: Steve Dickson --- utils/mount/fstab.c | 52 ++++++++++++++++++++++++++++ utils/mount/fstab.h | 1 + utils/mount/nfsumount.c | 75 +++++++++++++++++------------------------ 3 files changed, 84 insertions(+), 44 deletions(-) diff --git a/utils/mount/fstab.c b/utils/mount/fstab.c index 1fc9efe..eedbdda 100644 --- a/utils/mount/fstab.c +++ b/utils/mount/fstab.c @@ -86,10 +86,13 @@ mtab_is_writable() { struct mntentchn mounttable; static int got_mtab = 0; +struct mntentchn procmounts; +static int got_procmounts = 0; struct mntentchn fstab; static int got_fstab = 0; static void read_mounttable(void); +static void read_procmounts(void); static void read_fstab(void); static struct mntentchn * @@ -100,6 +103,14 @@ mtab_head(void) return &mounttable; } +static struct mntentchn * +procmounts_head(void) +{ + if (!got_procmounts) + read_procmounts(); + return &procmounts; +} + static struct mntentchn * fstab_head(void) { @@ -186,6 +197,30 @@ read_mounttable() { read_mntentchn(mfp, fnam, mc); } +/* + * Read /proc/mounts. + * This produces a linked list. The list head procmounts is a dummy. + * Return 0 on success. + */ +static void +read_procmounts() { + mntFILE *mfp; + const char *fnam; + struct mntentchn *mc = &procmounts; + + got_procmounts = 1; + mc->nxt = mc->prev = NULL; + + fnam = PROC_MOUNTS; + mfp = nfs_setmntent(fnam, "r"); + if (mfp == NULL || mfp->mntent_fp == NULL) { + nfs_error(_("warning: can't open %s: %s"), + PROC_MOUNTS, strerror (errno)); + return; + } + read_mntentchn(mfp, fnam, mc); +} + static void read_fstab() { @@ -224,6 +259,23 @@ getmntdirbackward (const char *name, struct mntentchn *mcprev) { return NULL; } +/* + * Given the directory name NAME, and the place MCPREV we found it last time, + * try to find more occurrences. + */ +struct mntentchn * +getprocmntdirbackward (const char *name, struct mntentchn *mcprev) { + struct mntentchn *mc, *mc0; + + mc0 = procmounts_head(); + if (!mcprev) + mcprev = mc0; + for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev) + if (streq(mc->m.mnt_dir, name)) + return mc; + return NULL; +} + /* * Given the device name NAME, and the place MCPREV we found it last time, * try to find more occurrences. diff --git a/utils/mount/fstab.h b/utils/mount/fstab.h index dc7c9fc..313bf9b 100644 --- a/utils/mount/fstab.h +++ b/utils/mount/fstab.h @@ -18,6 +18,7 @@ struct mntentchn { struct mntentchn *getmntoptfile (const char *file); struct mntentchn *getmntdirbackward (const char *dir, struct mntentchn *mc); +struct mntentchn *getprocmntdirbackward (const char *name, struct mntentchn *mc); struct mntentchn *getmntdevbackward (const char *dev, struct mntentchn *mc); struct mntentchn *getfsfile (const char *file); diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c index 8cd2852..b846564 100644 --- a/utils/mount/nfsumount.c +++ b/utils/mount/nfsumount.c @@ -151,65 +151,50 @@ static int del_mtab(const char *spec, const char *node) */ static int nfs_umount_is_vers4(const struct mntentchn *mc) { - char buffer[LINELEN], *next; + struct mntentchn *pmc; + struct mount_options *options; int retval; - FILE *f; - - if ((f = fopen(MOUNTSFILE, "r")) == NULL) { - fprintf(stderr, "%s: %s\n", - MOUNTSFILE, strerror(errno)); - return -1; - } retval = -1; - while (fgets(buffer, sizeof(buffer), f) != NULL) { - char *device, *mntdir, *type, *flags; - struct mount_options *options; - char *line = buffer; - - next = strchr(line, '\n'); - if (next != NULL) - *next = '\0'; - - device = strtok(line, " \t"); - if (device == NULL) - continue; - mntdir = strtok(NULL, " \t"); - if (mntdir == NULL) - continue; - if (strcmp(device, mc->m.mnt_fsname) != 0 && - strcmp(mntdir, mc->m.mnt_dir) != 0) + pmc = getprocmntdirbackward(mc->m.mnt_dir, NULL); + if (!pmc) + goto not_found; + + do { + int nlen = strlen(pmc->m.mnt_fsname); + /* + * It's possible the mount location string in /proc/mounts + * ends with a '/'. In this case, if the entry came from + * /etc/mtab, it won't have the trailing '/' so deal with + * it. + */ + while (pmc->m.mnt_fsname[nlen - 1] == '/') + nlen--; + if (strncmp(pmc->m.mnt_fsname, mc->m.mnt_fsname, nlen) != 0) continue; - type = strtok(NULL, " \t"); - if (type == NULL) - continue; - if (strcmp(type, "nfs4") == 0) + if (strcmp(pmc->m.mnt_type, "nfs4") == 0) goto out_nfs4; - flags = strtok(NULL, " \t"); - if (flags == NULL) - continue; - options = po_split(flags); + options = po_split(pmc->m.mnt_opts); if (options != NULL) { unsigned long version; - int rc; - - rc = nfs_nfs_version(options, &version); + int rc = nfs_nfs_version(options, &version); po_destroy(options); if (rc && version == 4) goto out_nfs4; } - goto out_nfs; - } - if (retval == -1) + if (strcmp(pmc->m.mnt_type, "nfs") == 0) + goto out_nfs; + } while ((pmc = getprocmntdirbackward(mc->m.mnt_dir, pmc)) != NULL); + + if (retval == -1) { +not_found: fprintf(stderr, "%s was not found in %s\n", mc->m.mnt_dir, MOUNTSFILE); - -out: - fclose(f); - return retval; + goto out; + } out_nfs4: if (verbose) @@ -221,7 +206,9 @@ out_nfs: if (verbose) fprintf(stderr, "Legacy NFS mount point detected\n"); retval = 0; - goto out; + +out: + return retval; } static struct option umount_longopts[] = -- 2.39.2