X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fmount%2Fstropts.c;h=319be71aac195ca020ee01cd69f47ba419a81752;hp=43791e615edabc8d21b37a093b61e47f941e9320;hb=3163dabcf0a6b992859508368baf67c918d2c091;hpb=3f23f712477df48fd1d57376b65c44bb2a19ec16 diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c index 43791e6..319be71 100644 --- a/utils/mount/stropts.c +++ b/utils/mount/stropts.c @@ -224,9 +224,15 @@ static int nfs_fix_mounthost_option(const sa_family_t family, * Returns zero if the "lock" option is in effect, but statd * can't be started. Otherwise, returns 1. */ +static const char *nfs_lock_opttbl[] = { + "nolock", + "lock", + NULL, +}; + static int nfs_verify_lock_option(struct mount_options *options) { - if (po_rightmost(options, "nolock", "lock") == PO_KEY1_RIGHTMOST) + if (po_rightmost(options, nfs_lock_opttbl) == 1) return 1; if (!start_statd()) { @@ -303,6 +309,81 @@ static int nfs_is_permanent_error(int error) } } +static int nfs_construct_new_options(struct mount_options *options, + struct pmap *nfs_pmap, + struct pmap *mnt_pmap) +{ + char new_option[64]; + + po_remove_all(options, "nfsprog"); + po_remove_all(options, "mountprog"); + + po_remove_all(options, "v2"); + po_remove_all(options, "v3"); + po_remove_all(options, "vers"); + po_remove_all(options, "nfsvers"); + snprintf(new_option, sizeof(new_option) - 1, + "vers=%lu", nfs_pmap->pm_vers); + if (po_append(options, new_option) == PO_FAILED) + return 0; + + po_remove_all(options, "proto"); + po_remove_all(options, "udp"); + po_remove_all(options, "tcp"); + switch (nfs_pmap->pm_prot) { + case IPPROTO_TCP: + snprintf(new_option, sizeof(new_option) - 1, + "proto=tcp"); + if (po_append(options, new_option) == PO_FAILED) + return 0; + break; + case IPPROTO_UDP: + snprintf(new_option, sizeof(new_option) - 1, + "proto=udp"); + if (po_append(options, new_option) == PO_FAILED) + return 0; + break; + } + + po_remove_all(options, "port"); + if (nfs_pmap->pm_port != NFS_PORT) { + snprintf(new_option, sizeof(new_option) - 1, + "port=%lu", nfs_pmap->pm_port); + if (po_append(options, new_option) == PO_FAILED) + return 0; + } + + po_remove_all(options, "mountvers"); + snprintf(new_option, sizeof(new_option) - 1, + "mountvers=%lu", mnt_pmap->pm_vers); + if (po_append(options, new_option) == PO_FAILED) + return 0; + + po_remove_all(options, "mountproto"); + switch (mnt_pmap->pm_prot) { + case IPPROTO_TCP: + snprintf(new_option, sizeof(new_option) - 1, + "mountproto=tcp"); + if (po_append(options, new_option) == PO_FAILED) + return 0; + break; + case IPPROTO_UDP: + snprintf(new_option, sizeof(new_option) - 1, + "mountproto=udp"); + if (po_append(options, new_option) == PO_FAILED) + return 0; + break; + } + + po_remove_all(options, "mountport"); + snprintf(new_option, sizeof(new_option) - 1, + "mountport=%lu", mnt_pmap->pm_port); + if (po_append(options, new_option) == PO_FAILED) + return 0; + + return 1; +} + /* * Reconstruct the mount option string based on a portmapper probe * of the server. Returns one if the server's portmapper returned @@ -319,10 +400,9 @@ static int nfs_is_permanent_error(int error) static struct mount_options *nfs_rewrite_mount_options(char *str) { struct mount_options *options; - char *option, new_option[64]; + char *option; clnt_addr_t mnt_server = { }; clnt_addr_t nfs_server = { }; - int p; options = po_split(str); if (!options) { @@ -348,106 +428,25 @@ static struct mount_options *nfs_rewrite_mount_options(char *str) memcpy(&mnt_server.saddr, &nfs_server.saddr, sizeof(mnt_server.saddr)); - option = po_get(options, "mountport"); - if (option) - mnt_server.pmap.pm_port = atoi(option); - mnt_server.pmap.pm_prog = MOUNTPROG; - option = po_get(options, "mountvers"); - if (option) - mnt_server.pmap.pm_vers = atoi(option); - option = po_get(options, "mountproto"); - if (option) { - if (strcmp(option, "tcp") == 0) { - mnt_server.pmap.pm_prot = IPPROTO_TCP; - po_remove_all(options, "mountproto"); - } - if (strcmp(option, "udp") == 0) { - mnt_server.pmap.pm_prot = IPPROTO_UDP; - po_remove_all(options, "mountproto"); - } - } + nfs_options2pmap(options, &nfs_server.pmap, &mnt_server.pmap); - option = po_get(options, "port"); - if (option) { - nfs_server.pmap.pm_port = atoi(option); - po_remove_all(options, "port"); - } + /* The kernel NFS client doesn't support changing the RPC program + * number for these services, so reset these fields before probing + * the server's ports. */ nfs_server.pmap.pm_prog = NFS_PROGRAM; - - option = po_get(options, "nfsvers"); - if (option) { - nfs_server.pmap.pm_vers = atoi(option); - po_remove_all(options, "nfsvers"); - } - option = po_get(options, "vers"); - if (option) { - nfs_server.pmap.pm_vers = atoi(option); - po_remove_all(options, "vers"); - } - option = po_get(options, "proto"); - if (option) { - if (strcmp(option, "tcp") == 0) { - nfs_server.pmap.pm_prot = IPPROTO_TCP; - po_remove_all(options, "proto"); - } - if (strcmp(option, "udp") == 0) { - nfs_server.pmap.pm_prot = IPPROTO_UDP; - po_remove_all(options, "proto"); - } - } - p = po_rightmost(options, "tcp", "udp"); - switch (p) { - case PO_KEY2_RIGHTMOST: - nfs_server.pmap.pm_prot = IPPROTO_UDP; - break; - case PO_KEY1_RIGHTMOST: - nfs_server.pmap.pm_prot = IPPROTO_TCP; - break; - } - po_remove_all(options, "tcp"); - po_remove_all(options, "udp"); + mnt_server.pmap.pm_prog = MOUNTPROG; if (!probe_bothports(&mnt_server, &nfs_server)) { errno = ESPIPE; goto err; } - snprintf(new_option, sizeof(new_option) - 1, - "nfsvers=%lu", nfs_server.pmap.pm_vers); - if (po_append(options, new_option) == PO_FAILED) + if (!nfs_construct_new_options(options, + &nfs_server.pmap, &mnt_server.pmap)) { + errno = EINVAL; goto err; - - if (nfs_server.pmap.pm_prot == IPPROTO_TCP) - snprintf(new_option, sizeof(new_option) - 1, - "proto=tcp"); - else - snprintf(new_option, sizeof(new_option) - 1, - "proto=udp"); - if (po_append(options, new_option) == PO_FAILED) - goto err; - - if (nfs_server.pmap.pm_port != NFS_PORT) { - snprintf(new_option, sizeof(new_option) - 1, - "port=%lu", nfs_server.pmap.pm_port); - if (po_append(options, new_option) == PO_FAILED) - goto err; - } - if (mnt_server.pmap.pm_prot == IPPROTO_TCP) - snprintf(new_option, sizeof(new_option) - 1, - "mountproto=tcp"); - else - snprintf(new_option, sizeof(new_option) - 1, - "mountproto=udp"); - if (po_append(options, new_option) == PO_FAILED) - goto err; - - snprintf(new_option, sizeof(new_option) - 1, - "mountport=%lu", mnt_server.pmap.pm_port); - if (po_append(options, new_option) == PO_FAILED) - goto err; - errno = 0; return options; @@ -722,12 +721,18 @@ static int nfsmount_bg(struct nfsmount_info *mi) * * Returns a valid mount command exit code. */ +static const char *nfs_background_opttbl[] = { + "bg", + "fg", + NULL, +}; + static int nfsmount_start(struct nfsmount_info *mi) { if (!nfs_validate_options(mi)) return EX_FAIL; - if (po_rightmost(mi->options, "bg", "fg") == PO_KEY1_RIGHTMOST) + if (po_rightmost(mi->options, nfs_background_opttbl) == 1) return nfsmount_bg(mi); else return nfsmount_fg(mi);