X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fmount%2Fnfsumount.c;h=8902f0088a0533abdd3a0d64a06ac938d4231d86;hp=fd4194faf6d196e1e572e53beeadf29a50dec718;hb=97fed3061fd5c742ebd1f685e3e6dcb62e835b74;hpb=f5bab6c03c5205ef9d062f167cc30060f90fedc4 diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c index fd4194f..8902f00 100644 --- a/utils/mount/nfsumount.c +++ b/utils/mount/nfsumount.c @@ -29,11 +29,9 @@ #include "xcommon.h" #include "fstab.h" #include "nls.h" -#include "conn.h" #include "mount_constants.h" #include "mount.h" -#include "nfsumount.h" #include "error.h" #include "network.h" @@ -53,74 +51,97 @@ int force; int lazy; int remount; + +static int try_remount(const char *spec, const char *node) +{ + int res; + + res = mount(spec, node, NULL, + MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); + if (res == 0) { + struct mntent remnt; + nfs_error(_("%s: %s busy - remounted read-only"), + progname, spec); + remnt.mnt_type = remnt.mnt_fsname = NULL; + remnt.mnt_dir = xstrdup(node); + remnt.mnt_opts = xstrdup("ro"); + if (!nomtab) + update_mtab(node, &remnt); + } else if (errno != EBUSY) { /* hmm ... */ + perror(_("remount")); + nfs_error(_("%s: could not remount %s read-only"), + progname, spec); + } + return res; +} + static int del_mtab(const char *spec, const char *node) { int umnt_err, res; - umnt_err = 0; - if (lazy) { - res = umount2 (node, MNT_DETACH); - if (res < 0) - umnt_err = errno; - goto writemtab; - } - - if (force) { - res = umount2 (node, MNT_FORCE); - if (res == -1) { - int errsv = errno; - perror("umount2"); - errno = errsv; - if (errno == ENOSYS) { - if (verbose) - printf(_("no umount2, trying umount...\n")); - res = umount (node); - } - } - } else - res = umount (node); - - if (res < 0 && remount && errno == EBUSY && spec) { - /* Umount failed - let us try a remount */ - res = mount(spec, node, NULL, - MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); - if (res == 0) { - struct mntent remnt; - nfs_error(_("%s: %s busy - remounted read-only"), - progname, spec); - remnt.mnt_type = remnt.mnt_fsname = NULL; - remnt.mnt_dir = xstrdup(node); - remnt.mnt_opts = xstrdup("ro"); - if (!nomtab) - update_mtab(node, &remnt); - return 0; - } else if (errno != EBUSY) { /* hmm ... */ - perror("remount"); - nfs_error(_("%s: could not remount %s read-only"), - progname, spec); - } - } - - if (res >= 0) { - /* Umount succeeded */ - if (verbose) - printf (_("%s umounted\n"), spec ? spec : node); - } + umnt_err = 0; + if (lazy) { + res = umount2 (node, MNT_DETACH); + if (res < 0) + umnt_err = errno; + goto writemtab; + } + + if (force) { + res = umount2 (node, MNT_FORCE); + if (res == -1) { + int errsv = errno; + perror(_("umount2")); + errno = errsv; + if (errno == ENOSYS) { + if (verbose) + printf(_("no umount2, trying umount...\n")); + res = umount (node); + } + } + } else + res = umount (node); + + if (res < 0) { + if (remount && errno == EBUSY && spec) { + res = try_remount(spec, node); + if (res) + goto writemtab; + return 0; + } else + umnt_err = errno; + } + + if (res >= 0) { + /* Umount succeeded */ + if (verbose) + printf(_("%s umounted\n"), spec ? spec : node); + } writemtab: - if (!nomtab && - (umnt_err == 0 || umnt_err == EINVAL || umnt_err == ENOENT)) { - update_mtab(node, NULL); - } + if (!nomtab && + (umnt_err == 0 || umnt_err == EINVAL || umnt_err == ENOENT)) { + update_mtab(node, NULL); + } - if (res >= 0) - return 0; + if (res >= 0) + return 0; - if (umnt_err) - umount_error(umnt_err, node); - return EX_FILEIO; + if (umnt_err) + umount_error(umnt_err, node); + return EX_FILEIO; } +/* + * Pick up certain mount options used during the original mount + * from /etc/mtab. The basics include the server's IP address and + * the server pathname of the share to unregister. + * + * These options might also describe the mount port, mount protocol + * version, and transport protocol used to punch through a firewall. + * We will need this information to get through the firewall again + * to do the umount. + */ static int do_nfs_umount(const char *spec, char *opts) { char *hostname; @@ -186,6 +207,8 @@ static int do_nfs_umount(const char *spec, char *opts) pmap->pm_vers = atoi(p+10); if (opts && (hasmntopt(&mnt, "udp") || hasmntopt(&mnt, "proto=udp"))) pmap->pm_prot = IPPROTO_UDP; + if (opts && (hasmntopt(&mnt, "tcp") || hasmntopt(&mnt, "proto=tcp"))) + pmap->pm_prot = IPPROTO_TCP; if (!nfs_gethostbyname(hostname, &mnt_server.saddr)) { nfs_error(_("%s: '%s' does not contain a recognized hostname"), @@ -199,7 +222,7 @@ static int do_nfs_umount(const char *spec, char *opts) return EX_USAGE; } - return 0; + return EX_SUCCESS; } static struct option umount_longopts[] = @@ -214,13 +237,13 @@ static struct option umount_longopts[] = static void umount_usage(void) { - printf("usage: %s dir [-fvnrlh]\n", progname); - printf("options:\n\t-f\t\tforce unmount\n"); - printf("\t-v\t\tverbose\n"); - printf("\t-n\t\tDo not update /etc/mtab\n"); - printf("\t-r\t\tremount\n"); - printf("\t-l\t\tlazy unmount\n"); - printf("\t-h\t\tprint this help\n\n"); + printf(_("usage: %s dir [-fvnrlh]\n"), progname); + printf(_("options:\n\t-f\t\tforce unmount\n")); + printf(_("\t-v\tverbose\n")); + printf(_("\t-n\tDo not update /etc/mtab\n")); + printf(_("\t-r\tremount\n")); + printf(_("\t-l\tlazy unmount\n")); + printf(_("\t-h\tprint this help\n\n")); } int nfsumount(int argc, char *argv[]) @@ -284,7 +307,7 @@ int nfsumount(int argc, char *argv[]) if (mc && strcmp(mc->m.mnt_type, "nfs") != 0 && strcmp(mc->m.mnt_type, "nfs4") != 0) { - nfs_error(_("%s: %s on %s it not an nfs filesystem"), + nfs_error(_("%s: %s on %s is not an NFS filesystem"), progname, mc->m.mnt_fsname, mc->m.mnt_dir); return EX_USAGE; } @@ -295,7 +318,7 @@ int nfsumount(int argc, char *argv[]) /* umount might call us twice. The second time there will * be no entry in mtab and we should just exit quietly */ - return 0; + return EX_SUCCESS; only_root: nfs_error(_("%s: You are not permitted to unmount %s"), @@ -325,12 +348,13 @@ int nfsumount(int argc, char *argv[]) ret = 0; if (mc) { - if (!lazy) - do_nfs_umount(mc->m.mnt_fsname, mc->m.mnt_opts); - ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir); + if (!lazy && strcmp(mc->m.mnt_type, "nfs4") != 0) + ret = do_nfs_umount(mc->m.mnt_fsname, mc->m.mnt_opts); + if (!ret || force) + ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir); } else if (*spec != '/') { if (!lazy) - do_nfs_umount(spec, "tcp,v3"); + ret = do_nfs_umount(spec, "tcp,v3"); } else ret = del_mtab(NULL, spec);