X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fmount%2Fnfsmount.c;h=3d2ebb1066137a2733fe4616c36d097b821e3092;hp=4b862f05a3f7f8aee7dfa2b4f5534450b874260d;hb=0f3172012919d36e2a7e5bf46c388f8c028fc93e;hpb=13b5fbc6cb4e41cd6a4d80e224ee2feaade65ce1 diff --git a/utils/mount/nfsmount.c b/utils/mount/nfsmount.c index 4b862f0..3d2ebb1 100644 --- a/utils/mount/nfsmount.c +++ b/utils/mount/nfsmount.c @@ -23,7 +23,7 @@ * * 1999-02-22 Arkadiusz Mi¶kiewicz * - added Native Language Support - * + * * Modified by Olaf Kirch and Trond Myklebust for new NFS code, * plus NFSv3 stuff. * @@ -56,14 +56,13 @@ #include #include -#include "conn.h" #include "xcommon.h" #include "mount.h" -#include "nfsumount.h" #include "nfs_mount.h" #include "mount_constants.h" #include "nls.h" #include "error.h" +#include "network.h" #ifndef NFS_PORT #define NFS_PORT 2049 @@ -88,273 +87,11 @@ typedef union { } mntres_t; extern int nfs_mount_data_version; +extern char *progname; extern int verbose; extern int sloppy; -extern int linux_version_code(); - -static const unsigned int probe_udp_only[] = { - IPPROTO_UDP, - 0, -}; - -static const unsigned int probe_udp_first[] = { - IPPROTO_UDP, - IPPROTO_TCP, - 0, -}; - -static const unsigned int probe_tcp_first[] = { - IPPROTO_TCP, - IPPROTO_UDP, - 0, -}; - -static const unsigned long probe_nfs2_only[] = { - 2, - 0, -}; - -static const unsigned long probe_nfs3_first[] = { - 3, - 2, - 0, -}; - -static const unsigned long probe_mnt1_first[] = { - 1, - 2, - 0, -}; - -static const unsigned long probe_mnt3_first[] = { - 3, - 1, - 2, - 0, -}; - -int nfs_gethostbyname(const char *, struct sockaddr_in *); -int nfs_gethostbyname(const char *hostname, struct sockaddr_in *saddr) -{ - struct hostent *hp; - - saddr->sin_family = AF_INET; - if (!inet_aton(hostname, &saddr->sin_addr)) { - if ((hp = gethostbyname(hostname)) == NULL) { - fprintf(stderr, _("mount: can't get address for %s\n"), - hostname); - return 0; - } else { - if (hp->h_length > sizeof(*saddr)) { - fprintf(stderr, - _("mount: got bad hp->h_length\n")); - hp->h_length = sizeof(*saddr); - } - memcpy(&saddr->sin_addr, hp->h_addr, hp->h_length); - } - } - return 1; -} - -/* - * getport() is very similar to pmap_getport() with - * the exception this version uses a non-reserve ports - * instead of reserve ports since reserve ports - * are not needed for pmap requests. - */ -u_short -getport( - struct sockaddr_in *saddr, - u_long prog, - u_long vers, - u_int prot) -{ - u_short port = 0; - int socket; - CLIENT *clnt = NULL; - struct pmap parms; - enum clnt_stat stat; - - saddr->sin_port = htons (PMAPPORT); - socket = get_socket(saddr, prot, FALSE, FALSE); - - switch (prot) { - case IPPROTO_UDP: - clnt = clntudp_bufcreate(saddr, - PMAPPROG, PMAPVERS, TIMEOUT, &socket, - UDPMSGSIZE, UDPMSGSIZE); - break; - case IPPROTO_TCP: - clnt = clnttcp_create(saddr, - PMAPPROG, PMAPVERS, &socket, 50, 500); - break; - } - if (clnt != NULL) { - parms.pm_prog = prog; - parms.pm_vers = vers; - parms.pm_prot = prot; - parms.pm_port = 0; /* not needed or used */ - - stat = clnt_call(clnt, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap, - (caddr_t)&parms, (xdrproc_t)xdr_u_short, (caddr_t)&port, TIMEOUT); - if (stat) { - clnt_geterr(clnt, &rpc_createerr.cf_error); - rpc_createerr.cf_stat = stat; - } - clnt_destroy(clnt); - if (stat != RPC_SUCCESS) - port = 0; - else if (port == 0) - rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; - } - if (socket != 1) - close(socket); - - return port; -} - -/* - * Use the portmapper to discover whether or not the service we want is - * available. The lists 'versions' and 'protos' define ordered sequences - * of service versions and udp/tcp protocols to probe for. - */ -static int -probe_port(clnt_addr_t *server, - const u_long *versions, - const u_int *protos) -{ - struct sockaddr_in *saddr = &server->saddr; - struct pmap *pmap = &server->pmap; - const u_long prog = pmap->pm_prog, *p_vers; - const u_int prot = (u_int)pmap->pm_prot, - *p_prot; - const u_short port = (u_short) pmap->pm_port; - u_long vers = pmap->pm_vers; - u_short p_port; - p_prot = prot ? &prot : protos; - p_vers = vers ? &vers : versions; - rpc_createerr.cf_stat = 0; - for (;;) { - saddr->sin_port = htons(PMAPPORT); - p_port = getport(saddr, prog, *p_vers, *p_prot); - if (p_port) { - if (!port || port == p_port) { - saddr->sin_port = htons(p_port); - if (verbose) { - fprintf(stderr, - "mount: trying %s prog %ld vers %ld prot %s port %d\n", - inet_ntoa(saddr->sin_addr), prog, *p_vers, - *p_prot == IPPROTO_UDP ? "udp" : "tcp", p_port); - } - if (clnt_ping(saddr, prog, *p_vers, *p_prot, NULL)) - goto out_ok; - if (rpc_createerr.cf_stat == RPC_TIMEDOUT) - goto out_bad; - } - } - if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED) - goto out_bad; - - if (!prot) { - if (*++p_prot) - continue; - p_prot = protos; - } - if (vers == pmap->pm_vers) { - p_vers = versions; - vers = 0; - } - if (vers || !*++p_vers) - break; - } -out_bad: - return 0; - - out_ok: - if (!vers) - pmap->pm_vers = *p_vers; - if (!prot) - pmap->pm_prot = *p_prot; - if (!port) - pmap->pm_port = p_port; - rpc_createerr.cf_stat = 0; - return 1; -} - -static int probe_nfsport(clnt_addr_t *nfs_server) -{ - struct pmap *pmap = &nfs_server->pmap; - - if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port) - return 1; - - if (nfs_mount_data_version >= 4) - return probe_port(nfs_server, probe_nfs3_first, probe_tcp_first); - else - return probe_port(nfs_server, probe_nfs2_only, probe_udp_only); -} - -int probe_mntport(clnt_addr_t *mnt_server) -{ - struct pmap *pmap = &mnt_server->pmap; - - if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port) - return 1; - - if (nfs_mount_data_version >= 4) - return probe_port(mnt_server, probe_mnt3_first, probe_udp_first); - else - return probe_port(mnt_server, probe_mnt1_first, probe_udp_only); -} - -static int -probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server) -{ - struct pmap *nfs_pmap = &nfs_server->pmap; - struct pmap *mnt_pmap = &mnt_server->pmap; - struct pmap save_nfs, save_mnt; - int res; - const unsigned long *probe_vers; - - if (mnt_pmap->pm_vers && !nfs_pmap->pm_vers) - nfs_pmap->pm_vers = mntvers_to_nfs(mnt_pmap->pm_vers); - else if (nfs_pmap->pm_vers && !mnt_pmap->pm_vers) - mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers); - if (nfs_pmap->pm_vers) - goto version_fixed; - - memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs)); - memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt)); - probe_vers = (nfs_mount_data_version >= 4) ? - probe_mnt3_first : probe_mnt1_first; - - for (; *probe_vers; probe_vers++) { - nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers); - if ((res = probe_nfsport(nfs_server) != 0)) { - mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers); - if ((res = probe_mntport(mnt_server)) != 0) - return 1; - memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap)); - } - switch (rpc_createerr.cf_stat) { - case RPC_PROGVERSMISMATCH: - case RPC_PROGNOTREGISTERED: - break; - default: - goto out_bad; - } - memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap)); - } - -out_bad: - return 0; - -version_fixed: - if (!probe_nfsport(nfs_server)) - goto out_bad; - return probe_mntport(mnt_server); -} +extern int linux_version_code(void); static inline enum clnt_stat nfs3_mount(CLIENT *clnt, mnt3arg_t *mnt3arg, mnt3res_t *mnt3res) @@ -453,7 +190,6 @@ parse_options(char *old_opts, struct nfs_mount_data *data, if ((opteq = strchr(opt, '=')) && isdigit(opteq[1])) { int val = atoi(opteq + 1); *opteq = '\0'; -/* printf("opt=%s\n", opt); */ if (!strcmp(opt, "rsize")) data->rsize = val; else if (!strcmp(opt, "wsize")) @@ -534,7 +270,8 @@ parse_options(char *old_opts, struct nfs_mount_data *data, char *secflavor = opteq+1; /* see RFC 2623 */ if (nfs_mount_data_version < 5) { - printf(_("Warning: ignoring sec=%s option\n"), secflavor); + printf(_("Warning: ignoring sec=%s option\n"), + secflavor); continue; } else if (!strcmp(secflavor, "none")) data->pseudoflavor = AUTH_NONE; @@ -575,8 +312,9 @@ parse_options(char *old_opts, struct nfs_mount_data *data, int ctxlen = strlen(context); if (ctxlen > NFS_MAX_CONTEXT_LEN) { - printf(_("context parameter exceeds limit of %d\n"), - NFS_MAX_CONTEXT_LEN); + nfs_error(_("context parameter exceeds" + " limit of %d"), + NFS_MAX_CONTEXT_LEN); goto bad_parameter; } /* The context string is in the format of @@ -600,9 +338,9 @@ parse_options(char *old_opts, struct nfs_mount_data *data, val = 0; opt += 2; } - if (!strcmp(opt, "bg")) + if (!strcmp(opt, "bg")) *bg = val; - else if (!strcmp(opt, "fg")) + else if (!strcmp(opt, "fg")) *bg = !val; else if (!strcmp(opt, "soft")) { data->flags &= ~NFS_MOUNT_SOFT; @@ -688,15 +426,17 @@ parse_options(char *old_opts, struct nfs_mount_data *data, bad_option: if (sloppy) continue; - printf(_("Unsupported nfs mount option: " - "%s%s\n"), val ? "" : "no", opt); + nfs_error(_("%s: Unsupported nfs mount option:" + " %s%s"), progname, + val ? "" : "no", opt); goto out_bad; } - sprintf(cbuf, val ? "%s,":"no%s,", opt); + sprintf(cbuf, val ? "%s," : "no%s,", opt); } len += strlen(cbuf); if (len >= opt_size) { - printf(_("mount: excessively long option argument\n")); + nfs_error(_("%s: excessively long option argument"), + progname); goto out_bad; } strcat(new_opts, cbuf); @@ -709,7 +449,7 @@ parse_options(char *old_opts, struct nfs_mount_data *data, } return 1; bad_parameter: - printf(_("Bad nfs mount parameter: %s\n"), opt); + nfs_error(_("%s: Bad nfs mount parameter: %s\n"), progname, opt); out_bad: return 0; } @@ -721,22 +461,22 @@ static int nfsmnt_check_compat(const struct pmap *nfs_pmap, unsigned int max_mnt_vers = (nfs_mount_data_version >= 4) ? 3 : 2; if (nfs_pmap->pm_vers == 4) { - fprintf(stderr, _("Please use '-t nfs4' " - "instead of '-o vers=4'.\n")); + nfs_error(_("%s: Please use '-t nfs4' " + "instead of '-o vers=4'"), progname); goto out_bad; } if (nfs_pmap->pm_vers) { if (nfs_pmap->pm_vers > max_nfs_vers || nfs_pmap->pm_vers < 2) { - fprintf(stderr, _("NFS version %ld is not supported.\n"), - nfs_pmap->pm_vers); + nfs_error(_("%s: NFS version %ld is not supported"), + progname, nfs_pmap->pm_vers); goto out_bad; } } if (mnt_pmap->pm_vers > max_mnt_vers) { - fprintf(stderr, _("NFS mount version %ld s not supported.\n"), - mnt_pmap->pm_vers); + nfs_error(_("%s: NFS mount version %ld s not supported"), + progname, mnt_pmap->pm_vers); goto out_bad; } @@ -747,9 +487,8 @@ out_bad: } int -nfsmount(const char *spec, const char *node, int *flags, - char **extra_opts, char **mount_opts, - int running_bg, int *need_statd) +nfsmount(const char *spec, const char *node, int flags, + char **extra_opts, int fake, int running_bg) { static char *prev_bg_host; char hostdir[1024]; @@ -762,7 +501,7 @@ nfsmount(const char *spec, const char *node, int *flags, clnt_addr_t mnt_server = { &mounthost, }; clnt_addr_t nfs_server = { &hostname, }; struct sockaddr_in *nfs_saddr = &nfs_server.saddr; - struct pmap *mnt_pmap = &mnt_server.pmap, + struct pmap *mnt_pmap = &mnt_server.pmap, *nfs_pmap = &nfs_server.pmap; struct pmap save_mnt, save_nfs; @@ -779,8 +518,8 @@ nfsmount(const char *spec, const char *node, int *flags, time_t timeout; if (strlen(spec) >= sizeof(hostdir)) { - fprintf(stderr, _("mount: " - "excessively long host:dir argument\n")); + nfs_error(_("%s: excessively long host:dir argument"), + progname); goto fail; } strcpy(hostdir, spec); @@ -792,14 +531,13 @@ nfsmount(const char *spec, const char *node, int *flags, until they can be fully supported. (mack@sgi.com) */ if ((s = strchr(hostdir, ','))) { *s = '\0'; - fprintf(stderr, - _("mount: warning: " - "multiple hostnames not supported\n")); + nfs_error(_("%s: warning: " + "multiple hostnames not supported"), + progname); } } else { - fprintf(stderr, - _("mount: " - "directory to mount not in host:dir format\n")); + nfs_error(_("%s: directory to mount not in host:dir format"), + progname); goto fail; } @@ -846,42 +584,40 @@ nfsmount(const char *spec, const char *node, int *flags, if (retry == 10000 && !bg) retry = 2; /* reset for fg mounts */ - #ifdef NFS_MOUNT_DEBUG - printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", + printf(_("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n"), data.rsize, data.wsize, data.timeo, data.retrans); - printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", + printf(_("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n"), data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); - printf("port = %d, bg = %d, retry = %d, flags = %.8x\n", + printf(_("port = %lu, bg = %d, retry = %d, flags = %.8x\n"), nfs_pmap->pm_port, bg, retry, data.flags); - printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n", + printf(_("mountprog = %lu, mountvers = %lu, nfsprog = %lu, nfsvers = %lu\n"), mnt_pmap->pm_prog, mnt_pmap->pm_vers, nfs_pmap->pm_prog, nfs_pmap->pm_vers); - printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d ", + printf(_("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d"), (data.flags & NFS_MOUNT_SOFT) != 0, (data.flags & NFS_MOUNT_INTR) != 0, (data.flags & NFS_MOUNT_POSIX) != 0, (data.flags & NFS_MOUNT_NOCTO) != 0, (data.flags & NFS_MOUNT_NOAC) != 0); #if NFS_MOUNT_VERSION >= 2 - printf("tcp = %d ", + printf(_(", tcp = %d"), (data.flags & NFS_MOUNT_TCP) != 0); #endif #if NFS_MOUNT_VERSION >= 4 - printf("noacl = %d ", (data.flags & NFS_MOUNT_NOACL) != 0); + printf(_(", noacl = %d"), (data.flags & NFS_MOUNT_NOACL) != 0); #endif #if NFS_MOUNT_VERSION >= 5 - printf("sec = %u ", data.pseudoflavor); - printf("readdirplus = %d ", (data.flags & NFS_MOUNT_NORDIRPLUS) != 0); + printf(_(", sec = %u"), data.pseudoflavor); + printf(_(", readdirplus = %d"), (data.flags & NFS_MOUNT_NORDIRPLUS) != 0); #endif printf("\n"); #endif data.version = nfs_mount_data_version; - *mount_opts = (char *) &data; - if (*flags & MS_REMOUNT) + if (flags & MS_REMOUNT) goto out_ok; /* @@ -952,15 +688,15 @@ nfsmount(const char *spec, const char *node, int *flags, if (errno == ETIMEDOUT) break; default: - mount_errors(*nfs_server.hostname, 0, bg); + rpc_mount_errors(*nfs_server.hostname, 0, bg); goto fail; } t = time(NULL); if (t >= timeout) { - mount_errors(*nfs_server.hostname, 0, bg); + rpc_mount_errors(*nfs_server.hostname, 0, bg); goto fail; } - mount_errors(*nfs_server.hostname, 1, bg); + rpc_mount_errors(*nfs_server.hostname, 1, bg); continue; } if (!running_bg) { @@ -971,19 +707,18 @@ nfsmount(const char *spec, const char *node, int *flags, } t = time(NULL); if (t >= timeout) { - mount_errors(*nfs_server.hostname, 0, bg); + rpc_mount_errors(*nfs_server.hostname, 0, bg); goto fail; } if (doonce++ < 1) - mount_errors(*nfs_server.hostname, 1, bg); + rpc_mount_errors(*nfs_server.hostname, 1, bg); } if (nfs_pmap->pm_vers == 2) { if (mntres.nfsv2.fhs_status != 0) { - fprintf(stderr, - _("mount: %s:%s failed, reason given by server: %s\n"), - hostname, dirname, - nfs_strerror(mntres.nfsv2.fhs_status)); + nfs_error(_("%s: %s:%s failed, reason given by server: %s"), + progname, hostname, dirname, + nfs_strerror(mntres.nfsv2.fhs_status)); goto fail; } memcpy(data.root.data, @@ -1001,16 +736,15 @@ nfsmount(const char *spec, const char *node, int *flags, fhandle3 *fhandle; int i, *flavor, yum = 0; if (mntres.nfsv3.fhs_status != 0) { - fprintf(stderr, - _("mount: %s:%s failed, reason given by server: %s\n"), - hostname, dirname, - nfs_strerror(mntres.nfsv3.fhs_status)); + nfs_error(_("%s: %s:%s failed, reason given by server: %s"), + progname, hostname, dirname, + nfs_strerror(mntres.nfsv3.fhs_status)); goto fail; } #if NFS_MOUNT_VERSION >= 5 mountres = &mntres.nfsv3.mountres3_u.mountinfo; i = mountres->auth_flavors.auth_flavors_len; - if (i <= 0) + if (i <= 0) goto noauth_flavors; flavor = mountres->auth_flavors.auth_flavors_val; @@ -1027,15 +761,13 @@ nfsmount(const char *spec, const char *node, int *flags, if (flavor[i] == data.pseudoflavor) yum = 1; #ifdef NFS_MOUNT_DEBUG - printf("auth flavor %d: %d\n", - i, flavor[i]); + printf(_("auth flavor %d: %d\n"), i, flavor[i]); #endif } if (!yum) { - fprintf(stderr, - "mount: %s:%s failed, " - "security flavor not supported\n", - hostname, dirname); + nfs_error(_("%s: %s:%s failed, security flavor " + "not supported"), + progname, hostname, dirname); /* server has registered us in rmtab, send umount */ nfs_call_umount(&mnt_server, &dirname); goto fail; @@ -1071,7 +803,7 @@ noauth_flavors: } #ifdef NFS_MOUNT_DEBUG - printf(_("using port %d for nfs deamon\n"), nfs_pmap->pm_port); + printf(_("using port %lu for nfs deamon\n"), nfs_pmap->pm_port); #endif nfs_saddr->sin_port = htons(nfs_pmap->pm_port); /* @@ -1102,8 +834,8 @@ noauth_flavors: out_ok: /* Ensure we have enough padding for the following strcat()s */ if (strlen(new_opts) + strlen(s) + 30 >= sizeof(new_opts)) { - fprintf(stderr, _("mount: " - "excessively long option argument\n")); + nfs_error(_("%s: excessively long option argument"), + progname); goto fail; } @@ -1111,8 +843,27 @@ noauth_flavors: strcat(new_opts, cbuf); *extra_opts = xstrdup(new_opts); - *need_statd = ! (data.flags & NFS_MOUNT_NONLM); - return 0; + + if (!fake && !(data.flags & NFS_MOUNT_NONLM)) { + if (!start_statd()) { + nfs_error(_("%s: rpc.statd is not running but is " + "required for remote locking.\n" + " Either use '-o nolock' to keep " + "locks local, or start statd."), + progname); + goto fail; + } + } + + if (!fake) { + if (mount(spec, node, "nfs", + flags & ~(MS_USER|MS_USERS), &data)) { + mount_error(spec, node, errno); + goto fail; + } + } + + return EX_SUCCESS; /* abort */ fail: