* 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()) {
}
}
+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
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) {
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;
*
* 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);