1 /* vi: set sw=4 ts=4: */
3 * nfsmount.c -- Linux NFS mount
4 * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * Wed Feb 8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port
17 * numbers to be specified on the command line.
19 * Fri, 8 Mar 1996 18:01:39, Swen Thuemmler <swen@uni-paderborn.de>:
20 * Omit the call to connect() for Linux version 1.3.11 or later.
22 * Wed Oct 1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com>
23 * Implemented the "bg", "fg" and "retry" mount options for NFS.
25 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
26 * - added Native Language Support
28 * Modified by Olaf Kirch and Trond Myklebust for new NFS code,
33 * nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
45 #include <rpc/pmap_prot.h>
46 #include <rpc/pmap_clnt.h>
47 #include <sys/socket.h>
49 #include <sys/utsname.h>
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
54 #include <linux/nfs.h> /* For the kernels nfs stuff */
63 /* Disable the nls stuff */
64 # undef bindtextdomain
65 # define bindtextdomain(Domain, Directory) /* empty */
67 # define textdomain(Domain) /* empty */
68 # define _(Text) (Text)
69 # define N_(Text) (Text)
71 #define MS_MGC_VAL 0xc0ed0000 /* Magic number indicatng "new" flags */
72 #define MS_RDONLY 1 /* Mount read-only */
73 #define MS_NOSUID 2 /* Ignore suid and sgid bits */
74 #define MS_NODEV 4 /* Disallow access to device special files */
75 #define MS_NOEXEC 8 /* Disallow program execution */
76 #define MS_SYNCHRONOUS 16 /* Writes are synced at once */
77 #define MS_REMOUNT 32 /* Alter flags of a mounted FS */
78 #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
79 #define S_QUOTA 128 /* Quota initialized for file/directory/symlink */
80 #define S_APPEND 256 /* Append-only file */
81 #define S_IMMUTABLE 512 /* Immutable file */
82 #define MS_NOATIME 1024 /* Do not update access times. */
83 #define MS_NODIRATIME 2048 /* Do not update directory access times */
87 * We want to be able to compile mount on old kernels in such a way
88 * that the binary will work well on more recent kernels.
89 * Thus, if necessary we teach nfsmount.c the structure of new fields
90 * that will come later.
92 * Moreover, the new kernel includes conflict with glibc includes
93 * so it is easiest to ignore the kernel altogether (at compile time).
96 #define NFS_MOUNT_VERSION 4
103 unsigned char data[64];
106 struct nfs_mount_data {
109 struct nfs2_fh old_root; /* 1 */
115 int acregmin; /* 1 */
116 int acregmax; /* 1 */
117 int acdirmin; /* 1 */
118 int acdirmax; /* 1 */
119 struct sockaddr_in addr; /* 1 */
120 char hostname[256]; /* 1 */
122 unsigned int bsize; /* 3 */
123 struct nfs3_fh root; /* 4 */
126 /* bits in the flags field */
128 #define NFS_MOUNT_SOFT 0x0001 /* 1 */
129 #define NFS_MOUNT_INTR 0x0002 /* 1 */
130 #define NFS_MOUNT_SECURE 0x0004 /* 1 */
131 #define NFS_MOUNT_POSIX 0x0008 /* 1 */
132 #define NFS_MOUNT_NOCTO 0x0010 /* 1 */
133 #define NFS_MOUNT_NOAC 0x0020 /* 1 */
134 #define NFS_MOUNT_TCP 0x0040 /* 2 */
135 #define NFS_MOUNT_VER3 0x0080 /* 3 */
136 #define NFS_MOUNT_KERBEROS 0x0100 /* 3 */
137 #define NFS_MOUNT_NONLM 0x0200 /* 3 */
140 #define UTIL_LINUX_VERSION "2.10m"
141 #define util_linux_version "util-linux-2.10m"
143 #define HAVE_inet_aton
148 #define HAVE_locale_h
149 #define HAVE_libintl_h
151 #define HAVE_langinfo_h
152 #define HAVE_progname
154 #define HAVE_nanosleep
155 #define HAVE_personality
156 #define HAVE_tm_gmtoff
158 static char *nfs_strerror(int stat);
160 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
161 #define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2)
163 #define EX_FAIL 32 /* mount failure */
164 #define EX_BG 256 /* retry in background (internal only) */
168 * nfs_mount_version according to the sources seen at compile time.
170 int nfs_mount_version = NFS_MOUNT_VERSION;
173 * Unfortunately, the kernel prints annoying console messages
174 * in case of an unexpected nfs mount version (instead of
175 * just returning some error). Therefore we'll have to try
176 * and figure out what version the kernel expects.
179 * KERNEL_NFS_MOUNT_VERSION: kernel sources at compile time
180 * NFS_MOUNT_VERSION: these nfsmount sources at compile time
181 * nfs_mount_version: version this source and running kernel can handle
184 find_kernel_nfs_mount_version(void) {
185 static int kernel_version = 0;
190 kernel_version = get_kernel_revision();
192 if (kernel_version) {
193 if (kernel_version < MAKE_VERSION(2,1,32))
194 nfs_mount_version = 1;
195 else if (kernel_version < MAKE_VERSION(2,3,99))
196 nfs_mount_version = 3;
198 nfs_mount_version = 4; /* since 2.3.99pre4 */
200 if (nfs_mount_version > NFS_MOUNT_VERSION)
201 nfs_mount_version = NFS_MOUNT_VERSION;
205 get_mountport(struct sockaddr_in *server_addr,
207 long unsigned version,
211 struct pmaplist *pmap;
212 static struct pmap p = {0, 0, 0, 0};
214 server_addr->sin_port = PMAPPORT;
215 pmap = pmap_getmaps(server_addr);
217 if (version > MAX_NFSPROT)
218 version = MAX_NFSPROT;
227 if (pmap->pml_map.pm_prog != prog)
229 if (!version && p.pm_vers > pmap->pml_map.pm_vers)
231 if (version > 2 && pmap->pml_map.pm_vers != version)
233 if (version && version <= 2 && pmap->pml_map.pm_vers > 2)
235 if (pmap->pml_map.pm_vers > MAX_NFSPROT ||
236 (proto && p.pm_prot && pmap->pml_map.pm_prot != proto) ||
237 (port && pmap->pml_map.pm_port != port))
239 memcpy(&p, &pmap->pml_map, sizeof(p));
241 pmap = pmap->pml_next;
244 p.pm_vers = MOUNTVERS;
246 p.pm_port = MOUNTPORT;
248 p.pm_prot = IPPROTO_TCP;
252 int nfsmount(const char *spec, const char *node, int *flags,
253 char **extra_opts, char **mount_opts, int running_bg)
255 static char *prev_bg_host;
261 char *mounthost=NULL;
263 struct timeval total_timeout;
264 enum clnt_stat clnt_stat;
265 static struct nfs_mount_data data;
269 struct sockaddr_in server_addr;
270 struct sockaddr_in mount_server_addr;
273 struct timeval retry_timeout;
275 struct fhstatus nfsv2;
276 struct mountres3 nfsv3;
301 find_kernel_nfs_mount_version();
306 if (strlen(spec) >= sizeof(hostdir)) {
307 error_msg("excessively long host:dir argument\n");
310 strcpy(hostdir, spec);
311 if ((s = strchr(hostdir, ':'))) {
315 /* Ignore all but first hostname in replicated mounts
316 until they can be fully supported. (mack@sgi.com) */
317 if ((s = strchr(hostdir, ','))) {
319 error_msg("warning: multiple hostnames not supported\n");
322 error_msg("directory to mount not in host:dir format\n");
326 server_addr.sin_family = AF_INET;
327 #ifdef HAVE_inet_aton
328 if (!inet_aton(hostname, &server_addr.sin_addr))
331 if ((hp = gethostbyname(hostname)) == NULL) {
332 error_msg("can't get address for %s\n", hostname);
335 if (hp->h_length > sizeof(struct in_addr)) {
336 error_msg("got bad hp->h_length\n");
337 hp->h_length = sizeof(struct in_addr);
339 memcpy(&server_addr.sin_addr,
340 hp->h_addr, hp->h_length);
344 memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr));
346 /* add IP address to mtab options for use when unmounting */
348 s = inet_ntoa(server_addr.sin_addr);
349 old_opts = *extra_opts;
352 if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
353 error_msg("excessively long option argument\n");
356 sprintf(new_opts, "%s%saddr=%s",
357 old_opts, *old_opts ? "," : "", s);
358 *extra_opts = xstrdup(new_opts);
360 /* Set default options.
361 * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to
362 * let the kernel decide.
363 * timeo is filled in after we know whether it'll be TCP or UDP. */
364 memset(&data, 0, sizeof(data));
370 #if NFS_MOUNT_VERSION >= 2
371 data.namlen = NAME_MAX;
381 retry = 10000; /* 10000 minutes ~ 1 week */
384 mountprog = MOUNTPROG;
388 nfsprog = NFS_PROGRAM;
393 for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
394 if ((opteq = strchr(opt, '='))) {
395 val = atoi(opteq + 1);
397 if (!strcmp(opt, "rsize"))
399 else if (!strcmp(opt, "wsize"))
401 else if (!strcmp(opt, "timeo"))
403 else if (!strcmp(opt, "retrans"))
405 else if (!strcmp(opt, "acregmin"))
407 else if (!strcmp(opt, "acregmax"))
409 else if (!strcmp(opt, "acdirmin"))
411 else if (!strcmp(opt, "acdirmax"))
413 else if (!strcmp(opt, "actimeo")) {
419 else if (!strcmp(opt, "retry"))
421 else if (!strcmp(opt, "port"))
423 else if (!strcmp(opt, "mountport"))
425 else if (!strcmp(opt, "mounthost"))
426 mounthost=xstrndup(opteq+1,
427 strcspn(opteq+1," \t\n\r,"));
428 else if (!strcmp(opt, "mountprog"))
430 else if (!strcmp(opt, "mountvers"))
432 else if (!strcmp(opt, "nfsprog"))
434 else if (!strcmp(opt, "nfsvers") ||
435 !strcmp(opt, "vers"))
437 else if (!strcmp(opt, "proto")) {
438 if (!strncmp(opteq+1, "tcp", 3))
440 else if (!strncmp(opteq+1, "udp", 3))
443 printf(_("Warning: Unrecognized proto= option.\n"));
444 } else if (!strcmp(opt, "namlen")) {
445 #if NFS_MOUNT_VERSION >= 2
446 if (nfs_mount_version >= 2)
450 printf(_("Warning: Option namlen is not supported.\n"));
451 } else if (!strcmp(opt, "addr"))
454 printf(_("unknown nfs mount parameter: "
455 "%s=%d\n"), opt, val);
461 if (!strncmp(opt, "no", 2)) {
465 if (!strcmp(opt, "bg"))
467 else if (!strcmp(opt, "fg"))
469 else if (!strcmp(opt, "soft"))
471 else if (!strcmp(opt, "hard"))
473 else if (!strcmp(opt, "intr"))
475 else if (!strcmp(opt, "posix"))
477 else if (!strcmp(opt, "cto"))
479 else if (!strcmp(opt, "ac"))
481 else if (!strcmp(opt, "tcp"))
483 else if (!strcmp(opt, "udp"))
485 else if (!strcmp(opt, "lock")) {
486 if (nfs_mount_version >= 3)
489 printf(_("Warning: option nolock is not supported.\n"));
491 printf(_("unknown nfs mount option: "
492 "%s%s\n"), val ? "" : "no", opt);
497 proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP;
499 data.flags = (soft ? NFS_MOUNT_SOFT : 0)
500 | (intr ? NFS_MOUNT_INTR : 0)
501 | (posix ? NFS_MOUNT_POSIX : 0)
502 | (nocto ? NFS_MOUNT_NOCTO : 0)
503 | (noac ? NFS_MOUNT_NOAC : 0);
504 #if NFS_MOUNT_VERSION >= 2
505 if (nfs_mount_version >= 2)
506 data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
508 #if NFS_MOUNT_VERSION >= 3
509 if (nfs_mount_version >= 3)
510 data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
512 if (nfsvers > MAX_NFSPROT) {
513 error_msg("NFSv%d not supported!\n", nfsvers);
516 if (mountvers > MAX_NFSPROT) {
517 error_msg("NFSv%d not supported!\n", nfsvers);
520 if (nfsvers && !mountvers)
521 mountvers = (nfsvers < 3) ? 1 : nfsvers;
522 if (nfsvers && nfsvers < mountvers) {
526 /* Adjust options if none specified */
528 data.timeo = tcp ? 70 : 7;
530 #ifdef NFS_MOUNT_DEBUG
531 printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
532 data.rsize, data.wsize, data.timeo, data.retrans);
533 printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
534 data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
535 printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
536 port, bg, retry, data.flags);
537 printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",
538 mountprog, mountvers, nfsprog, nfsvers);
539 printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n",
540 (data.flags & NFS_MOUNT_SOFT) != 0,
541 (data.flags & NFS_MOUNT_INTR) != 0,
542 (data.flags & NFS_MOUNT_POSIX) != 0,
543 (data.flags & NFS_MOUNT_NOCTO) != 0,
544 (data.flags & NFS_MOUNT_NOAC) != 0);
545 #if NFS_MOUNT_VERSION >= 2
547 (data.flags & NFS_MOUNT_TCP) != 0);
551 data.version = nfs_mount_version;
552 *mount_opts = (char *) &data;
554 if (*flags & MS_REMOUNT)
558 * If the previous mount operation on the same host was
559 * backgrounded, and the "bg" for this mount is also set,
560 * give up immediately, to avoid the initial timeout.
562 if (bg && !running_bg &&
563 prev_bg_host && strcmp(hostname, prev_bg_host) == 0) {
569 /* create mount deamon client */
570 /* See if the nfs host = mount host. */
572 if (mounthost[0] >= '0' && mounthost[0] <= '9') {
573 mount_server_addr.sin_family = AF_INET;
574 mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
576 if ((hp = gethostbyname(mounthost)) == NULL) {
577 error_msg("can't get address for %s\n", hostname);
580 if (hp->h_length > sizeof(struct in_addr)) {
581 error_msg("got bad hp->h_length?\n");
582 hp->h_length = sizeof(struct in_addr);
584 mount_server_addr.sin_family = AF_INET;
585 memcpy(&mount_server_addr.sin_addr,
586 hp->h_addr, hp->h_length);
592 * The following loop implements the mount retries. On the first
593 * call, "running_bg" is 0. When the mount times out, and the
594 * "bg" option is set, the exit status EX_BG will be returned.
595 * For a backgrounded mount, there will be a second call by the
596 * child process with "running_bg" set to 1.
598 * The case where the mount point is not present and the "bg"
599 * option is set, is treated as a timeout. This is done to
600 * support nested mounts.
602 * The "retry" count specified by the user is the number of
603 * minutes to retry before giving up.
605 * Only the first error message will be displayed.
607 retry_timeout.tv_sec = 3;
608 retry_timeout.tv_usec = 0;
609 total_timeout.tv_sec = 20;
610 total_timeout.tv_usec = 0;
611 timeout = time(NULL) + 60 * retry;
616 if (bg && stat(node, &statbuf) == -1) {
618 sleep(val); /* 1, 2, 4, 8, 16, 30, ... */
624 /* be careful not to use too many CPU cycles */
628 pm_mnt = get_mountport(&mount_server_addr,
634 /* contact the mount daemon via TCP */
635 mount_server_addr.sin_port = htons(pm_mnt->pm_port);
638 switch (pm_mnt->pm_prot) {
640 mclient = clntudp_create(&mount_server_addr,
647 mount_server_addr.sin_port = htons(pm_mnt->pm_port);
650 mclient = clnttcp_create(&mount_server_addr,
659 /* try to mount hostname:dirname */
660 mclient->cl_auth = authunix_create_default();
662 /* make pointers in xdr_mountres3 NULL so
663 * that xdr_array allocates memory for us
665 memset(&status, 0, sizeof(status));
667 if (pm_mnt->pm_vers == 3)
668 clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT,
669 (xdrproc_t) xdr_dirpath,
671 (xdrproc_t) xdr_mountres3,
675 clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
676 (xdrproc_t) xdr_dirpath,
678 (xdrproc_t) xdr_fhstatus,
682 if (clnt_stat == RPC_SUCCESS)
683 break; /* we're done */
684 if (errno != ECONNREFUSED) {
685 clnt_perror(mclient, "mount");
686 goto fail; /* don't retry */
688 if (!running_bg && prevt == 0)
689 clnt_perror(mclient, "mount");
690 auth_destroy(mclient->cl_auth);
691 clnt_destroy(mclient);
695 if (!running_bg && prevt == 0)
696 clnt_pcreateerror("mount");
703 prev_bg_host = xstrdup(hostname);
712 nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers;
715 if (status.nfsv2.fhs_status != 0) {
716 error_msg("%s:%s failed, reason given by server: %s\n",
718 nfs_strerror(status.nfsv2.fhs_status));
721 memcpy(data.root.data,
722 (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
724 #if NFS_MOUNT_VERSION >= 4
725 data.root.size = NFS_FHSIZE;
726 memcpy(data.old_root.data,
727 (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
731 #if NFS_MOUNT_VERSION >= 4
733 if (status.nfsv3.fhs_status != 0) {
734 error_msg("%s:%s failed, reason given by server: %s\n",
736 nfs_strerror(status.nfsv3.fhs_status));
739 fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle;
740 memset(data.old_root.data, 0, NFS_FHSIZE);
741 memset(&data.root, 0, sizeof(data.root));
742 data.root.size = fhandle->fhandle3_len;
743 memcpy(data.root.data,
744 (char *) fhandle->fhandle3_val,
745 fhandle->fhandle3_len);
747 data.flags |= NFS_MOUNT_VER3;
751 /* create nfs socket for kernel */
754 if (nfs_mount_version < 3) {
755 printf(_("NFS over TCP is not supported.\n"));
758 fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
760 fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
762 perror(_("nfs socket"));
765 if (bindresvport(fsock, 0) < 0) {
766 perror(_("nfs bindresvport"));
770 server_addr.sin_port = PMAPPORT;
771 port = pmap_getport(&server_addr, nfsprog, nfsvers,
772 tcp ? IPPROTO_TCP : IPPROTO_UDP);
775 #ifdef NFS_MOUNT_DEBUG
777 printf(_("used portmapper to find NFS port\n"));
780 #ifdef NFS_MOUNT_DEBUG
781 printf(_("using port %d for nfs deamon\n"), port);
783 server_addr.sin_port = htons(port);
785 * connect() the socket for kernels 1.3.10 and below only,
786 * to avoid problems with multihomed hosts.
789 if (get_kernel_revision() <= 66314
790 && connect(fsock, (struct sockaddr *) &server_addr,
791 sizeof (server_addr)) < 0) {
792 perror(_("nfs connect"));
796 /* prepare data structure for kernel */
799 memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
800 strncpy(data.hostname, hostname, sizeof(data.hostname));
804 auth_destroy(mclient->cl_auth);
805 clnt_destroy(mclient);
814 auth_destroy(mclient->cl_auth);
815 clnt_destroy(mclient);
825 * We need to translate between nfs status return values and
826 * the local errno values which may not be the same.
828 * Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>: change errno:
829 * "after #include <errno.h> the symbol errno is reserved for any use,
830 * it cannot even be used as a struct tag or field name".
834 #define EDQUOT ENOSPC
842 { NFSERR_PERM, EPERM },
843 { NFSERR_NOENT, ENOENT },
845 { NFSERR_NXIO, ENXIO },
846 { NFSERR_ACCES, EACCES },
847 { NFSERR_EXIST, EEXIST },
848 { NFSERR_NODEV, ENODEV },
849 { NFSERR_NOTDIR, ENOTDIR },
850 { NFSERR_ISDIR, EISDIR },
852 { NFSERR_INVAL, EINVAL }, /* that Sun forgot */
854 { NFSERR_FBIG, EFBIG },
855 { NFSERR_NOSPC, ENOSPC },
856 { NFSERR_ROFS, EROFS },
857 { NFSERR_NAMETOOLONG, ENAMETOOLONG },
858 { NFSERR_NOTEMPTY, ENOTEMPTY },
859 { NFSERR_DQUOT, EDQUOT },
860 { NFSERR_STALE, ESTALE },
862 { NFSERR_WFLUSH, EWFLUSH },
864 /* Throw in some NFSv3 values for even more fun (HP returns these) */
870 static char *nfs_strerror(int stat)
873 static char buf[256];
875 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
876 if (nfs_errtbl[i].stat == stat)
877 return strerror(nfs_errtbl[i].errnum);
879 sprintf(buf, _("unknown nfs status return value: %d"), stat);
884 xdr_fhandle (XDR *xdrs, fhandle objp)
886 //register int32_t *buf;
888 if (!xdr_opaque (xdrs, objp, FHSIZE))
894 xdr_fhstatus (XDR *xdrs, fhstatus *objp)
896 //register int32_t *buf;
898 if (!xdr_u_int (xdrs, &objp->fhs_status))
900 switch (objp->fhs_status) {
902 if (!xdr_fhandle (xdrs, objp->fhstatus_u.fhs_fhandle))
912 xdr_dirpath (XDR *xdrs, dirpath *objp)
914 //register int32_t *buf;
916 if (!xdr_string (xdrs, objp, MNTPATHLEN))
922 xdr_fhandle3 (XDR *xdrs, fhandle3 *objp)
924 //register int32_t *buf;
926 if (!xdr_bytes (xdrs, (char **)&objp->fhandle3_val, (u_int *) &objp->fhandle3_len, FHSIZE3))
932 xdr_mountres3_ok (XDR *xdrs, mountres3_ok *objp)
934 //register int32_t *buf;
936 if (!xdr_fhandle3 (xdrs, &objp->fhandle))
938 if (!xdr_array (xdrs, (char **)&objp->auth_flavours.auth_flavours_val, (u_int *) &objp->auth_flavours.auth_flavours_len, ~0,
939 sizeof (int), (xdrproc_t) xdr_int))
945 xdr_mountstat3 (XDR *xdrs, mountstat3 *objp)
947 //register int32_t *buf;
949 if (!xdr_enum (xdrs, (enum_t *) objp))
955 xdr_mountres3 (XDR *xdrs, mountres3 *objp)
957 //register int32_t *buf;
959 if (!xdr_mountstat3 (xdrs, &objp->fhs_status))
961 switch (objp->fhs_status) {
963 if (!xdr_mountres3_ok (xdrs, &objp->mountres3_u.mountinfo))