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
41 #include <sys/socket.h>
43 #include <sys/utsname.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
51 #include <rpc/pmap_prot.h>
52 #include <rpc/pmap_clnt.h>
55 /* This is just a warning of a common mistake. Possibly this should be a
56 * uclibc faq entry rather than in busybox... */
57 #if ENABLE_FEATURE_MOUNT_NFS && defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
58 #error "You need to build uClibc with UCLIBC_HAS_RPC for NFS support."
63 * NFS stats. The good thing with these values is that NFSv3 errors are
64 * a superset of NFSv2 errors (with the exception of NFSERR_WFLUSH which
65 * no-one uses anyway), so we can happily mix code as long as we make sure
66 * no NFSv3 errors are returned to NFSv2 clients.
67 * Error codes that have a `--' in the v2 column are not part of the
68 * standard, but seem to be widely used nevertheless.
71 NFS_OK = 0, /* v2 v3 */
72 NFSERR_PERM = 1, /* v2 v3 */
73 NFSERR_NOENT = 2, /* v2 v3 */
74 NFSERR_IO = 5, /* v2 v3 */
75 NFSERR_NXIO = 6, /* v2 v3 */
76 NFSERR_EAGAIN = 11, /* v2 v3 */
77 NFSERR_ACCES = 13, /* v2 v3 */
78 NFSERR_EXIST = 17, /* v2 v3 */
79 NFSERR_XDEV = 18, /* v3 */
80 NFSERR_NODEV = 19, /* v2 v3 */
81 NFSERR_NOTDIR = 20, /* v2 v3 */
82 NFSERR_ISDIR = 21, /* v2 v3 */
83 NFSERR_INVAL = 22, /* v2 v3 that Sun forgot */
84 NFSERR_FBIG = 27, /* v2 v3 */
85 NFSERR_NOSPC = 28, /* v2 v3 */
86 NFSERR_ROFS = 30, /* v2 v3 */
87 NFSERR_MLINK = 31, /* v3 */
88 NFSERR_OPNOTSUPP = 45, /* v2 v3 */
89 NFSERR_NAMETOOLONG = 63, /* v2 v3 */
90 NFSERR_NOTEMPTY = 66, /* v2 v3 */
91 NFSERR_DQUOT = 69, /* v2 v3 */
92 NFSERR_STALE = 70, /* v2 v3 */
93 NFSERR_REMOTE = 71, /* v2 v3 */
94 NFSERR_WFLUSH = 99, /* v2 */
95 NFSERR_BADHANDLE = 10001, /* v3 */
96 NFSERR_NOT_SYNC = 10002, /* v3 */
97 NFSERR_BAD_COOKIE = 10003, /* v3 */
98 NFSERR_NOTSUPP = 10004, /* v3 */
99 NFSERR_TOOSMALL = 10005, /* v3 */
100 NFSERR_SERVERFAULT = 10006, /* v3 */
101 NFSERR_BADTYPE = 10007, /* v3 */
102 NFSERR_JUKEBOX = 10008 /* v3 */
105 #define NFS_PROGRAM 100003
117 /* Disable the nls stuff */
118 # undef bindtextdomain
119 # define bindtextdomain(Domain, Directory) /* empty */
121 # define textdomain(Domain) /* empty */
124 MS_MGC_VAL = 0xc0ed0000, /* Magic number indicatng "new" flags */
125 MS_RDONLY = 1, /* Mount read-only */
126 MS_NOSUID = 2, /* Ignore suid and sgid bits */
127 MS_NODEV = 4, /* Disallow access to device special files */
128 MS_NOEXEC = 8, /* Disallow program execution */
129 MS_SYNCHRONOUS = 16, /* Writes are synced at once */
130 MS_REMOUNT = 32, /* Alter flags of a mounted FS */
131 MS_MANDLOCK = 64, /* Allow mandatory locks on an FS */
132 S_QUOTA = 128, /* Quota initialized for file/directory/symlink */
133 S_APPEND = 256, /* Append-only file */
134 S_IMMUTABLE = 512, /* Immutable file */
135 MS_NOATIME = 1024, /* Do not update access times. */
136 MS_NODIRATIME = 2048 /* Do not update directory access times */
141 * We want to be able to compile mount on old kernels in such a way
142 * that the binary will work well on more recent kernels.
143 * Thus, if necessary we teach nfsmount.c the structure of new fields
144 * that will come later.
146 * Moreover, the new kernel includes conflict with glibc includes
147 * so it is easiest to ignore the kernel altogether (at compile time).
150 /* NOTE: Do not make this into a 'static const int' because the pre-processor
151 * needs to test this value in some #if statements. */
152 #define NFS_MOUNT_VERSION 4
159 unsigned char data[64];
162 struct nfs_mount_data {
165 struct nfs2_fh old_root; /* 1 */
171 int acregmin; /* 1 */
172 int acregmax; /* 1 */
173 int acdirmin; /* 1 */
174 int acdirmax; /* 1 */
175 struct sockaddr_in addr; /* 1 */
176 char hostname[256]; /* 1 */
178 unsigned int bsize; /* 3 */
179 struct nfs3_fh root; /* 4 */
182 /* bits in the flags field */
184 NFS_MOUNT_SOFT = 0x0001, /* 1 */
185 NFS_MOUNT_INTR = 0x0002, /* 1 */
186 NFS_MOUNT_SECURE = 0x0004, /* 1 */
187 NFS_MOUNT_POSIX = 0x0008, /* 1 */
188 NFS_MOUNT_NOCTO = 0x0010, /* 1 */
189 NFS_MOUNT_NOAC = 0x0020, /* 1 */
190 NFS_MOUNT_TCP = 0x0040, /* 2 */
191 NFS_MOUNT_VER3 = 0x0080, /* 3 */
192 NFS_MOUNT_KERBEROS = 0x0100, /* 3 */
193 NFS_MOUNT_NONLM = 0x0200 /* 3 */
197 #define UTIL_LINUX_VERSION "2.10m"
198 #define util_linux_version "util-linux-2.10m"
200 #define HAVE_inet_aton
205 #define HAVE_locale_h
206 #define HAVE_libintl_h
208 #define HAVE_langinfo_h
209 #define HAVE_progname
211 #define HAVE_nanosleep
212 #define HAVE_personality
213 #define HAVE_tm_gmtoff
215 static char *nfs_strerror(int status);
217 #define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2)
220 EX_FAIL = 32, /* mount failure */
221 EX_BG = 256 /* retry in background (internal only) */
226 * nfs_mount_version according to the sources seen at compile time.
228 static int nfs_mount_version;
231 * Unfortunately, the kernel prints annoying console messages
232 * in case of an unexpected nfs mount version (instead of
233 * just returning some error). Therefore we'll have to try
234 * and figure out what version the kernel expects.
237 * KERNEL_NFS_MOUNT_VERSION: kernel sources at compile time
238 * NFS_MOUNT_VERSION: these nfsmount sources at compile time
239 * nfs_mount_version: version this source and running kernel can handle
242 find_kernel_nfs_mount_version(void)
244 static int kernel_version = 0;
249 nfs_mount_version = NFS_MOUNT_VERSION; /* default */
251 kernel_version = get_linux_version_code();
252 if (kernel_version) {
253 if (kernel_version < KERNEL_VERSION(2,1,32))
254 nfs_mount_version = 1;
255 else if (kernel_version < KERNEL_VERSION(2,2,18) ||
256 (kernel_version >= KERNEL_VERSION(2,3,0) &&
257 kernel_version < KERNEL_VERSION(2,3,99)))
258 nfs_mount_version = 3;
260 nfs_mount_version = 4; /* since 2.3.99pre4 */
262 if (nfs_mount_version > NFS_MOUNT_VERSION)
263 nfs_mount_version = NFS_MOUNT_VERSION;
267 get_mountport(struct sockaddr_in *server_addr,
269 long unsigned version,
273 struct pmaplist *pmap;
274 static struct pmap p = {0, 0, 0, 0};
276 server_addr->sin_port = PMAPPORT;
277 pmap = pmap_getmaps(server_addr);
279 if (version > MAX_NFSPROT)
280 version = MAX_NFSPROT;
289 if (pmap->pml_map.pm_prog != prog)
291 if (!version && p.pm_vers > pmap->pml_map.pm_vers)
293 if (version > 2 && pmap->pml_map.pm_vers != version)
295 if (version && version <= 2 && pmap->pml_map.pm_vers > 2)
297 if (pmap->pml_map.pm_vers > MAX_NFSPROT ||
298 (proto && p.pm_prot && pmap->pml_map.pm_prot != proto) ||
299 (port && pmap->pml_map.pm_port != port))
301 memcpy(&p, &pmap->pml_map, sizeof(p));
303 pmap = pmap->pml_next;
306 p.pm_vers = MOUNTVERS;
308 p.pm_port = MOUNTPORT;
310 p.pm_prot = IPPROTO_TCP;
314 int nfsmount(const char *spec, const char *node, int *flags,
315 char **mount_opts, int running_bg)
317 static char *prev_bg_host;
323 char *mounthost=NULL;
325 struct timeval total_timeout;
326 enum clnt_stat clnt_stat;
327 struct nfs_mount_data data;
331 struct sockaddr_in server_addr;
332 struct sockaddr_in mount_server_addr;
335 struct timeval retry_timeout;
337 struct fhstatus nfsv2;
338 struct mountres3 nfsv3;
363 find_kernel_nfs_mount_version();
368 if (strlen(spec) >= sizeof(hostdir)) {
369 bb_error_msg("excessively long host:dir argument");
372 strcpy(hostdir, spec);
373 if ((s = strchr(hostdir, ':'))) {
377 /* Ignore all but first hostname in replicated mounts
378 until they can be fully supported. (mack@sgi.com) */
379 if ((s = strchr(hostdir, ','))) {
381 bb_error_msg("warning: multiple hostnames not supported");
384 bb_error_msg("directory to mount not in host:dir format");
388 server_addr.sin_family = AF_INET;
389 #ifdef HAVE_inet_aton
390 if (!inet_aton(hostname, &server_addr.sin_addr))
393 if ((hp = gethostbyname(hostname)) == NULL) {
394 bb_herror_msg("%s", hostname);
397 if (hp->h_length > sizeof(struct in_addr)) {
398 bb_error_msg("got bad hp->h_length");
399 hp->h_length = sizeof(struct in_addr);
401 memcpy(&server_addr.sin_addr,
402 hp->h_addr, hp->h_length);
406 memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr));
408 /* add IP address to mtab options for use when unmounting */
410 s = inet_ntoa(server_addr.sin_addr);
411 old_opts = *mount_opts;
414 if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
415 bb_error_msg("excessively long option argument");
418 sprintf(new_opts, "%s%saddr=%s",
419 old_opts, *old_opts ? "," : "", s);
420 *mount_opts = bb_xstrdup(new_opts);
422 /* Set default options.
423 * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to
424 * let the kernel decide.
425 * timeo is filled in after we know whether it'll be TCP or UDP. */
426 memset(&data, 0, sizeof(data));
432 #if NFS_MOUNT_VERSION >= 2
433 data.namlen = NAME_MAX;
443 retry = 10000; /* 10000 minutes ~ 1 week */
446 mountprog = MOUNTPROG;
450 nfsprog = NFS_PROGRAM;
455 for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
456 if ((opteq = strchr(opt, '='))) {
457 val = atoi(opteq + 1);
459 if (!strcmp(opt, "rsize"))
461 else if (!strcmp(opt, "wsize"))
463 else if (!strcmp(opt, "timeo"))
465 else if (!strcmp(opt, "retrans"))
467 else if (!strcmp(opt, "acregmin"))
469 else if (!strcmp(opt, "acregmax"))
471 else if (!strcmp(opt, "acdirmin"))
473 else if (!strcmp(opt, "acdirmax"))
475 else if (!strcmp(opt, "actimeo")) {
481 else if (!strcmp(opt, "retry"))
483 else if (!strcmp(opt, "port"))
485 else if (!strcmp(opt, "mountport"))
487 else if (!strcmp(opt, "mounthost"))
488 mounthost=bb_xstrndup(opteq+1,
489 strcspn(opteq+1," \t\n\r,"));
490 else if (!strcmp(opt, "mountprog"))
492 else if (!strcmp(opt, "mountvers"))
494 else if (!strcmp(opt, "nfsprog"))
496 else if (!strcmp(opt, "nfsvers") ||
497 !strcmp(opt, "vers"))
499 else if (!strcmp(opt, "proto")) {
500 if (!strncmp(opteq+1, "tcp", 3))
502 else if (!strncmp(opteq+1, "udp", 3))
505 printf("Warning: Unrecognized proto= option.\n");
506 } else if (!strcmp(opt, "namlen")) {
507 #if NFS_MOUNT_VERSION >= 2
508 if (nfs_mount_version >= 2)
512 printf("Warning: Option namlen is not supported.\n");
513 } else if (!strcmp(opt, "addr"))
516 printf("unknown nfs mount parameter: %s=%d\n", opt, val);
522 if (!strncmp(opt, "no", 2)) {
526 if (!strcmp(opt, "bg"))
528 else if (!strcmp(opt, "fg"))
530 else if (!strcmp(opt, "soft"))
532 else if (!strcmp(opt, "hard"))
534 else if (!strcmp(opt, "intr"))
536 else if (!strcmp(opt, "posix"))
538 else if (!strcmp(opt, "cto"))
540 else if (!strcmp(opt, "ac"))
542 else if (!strcmp(opt, "tcp"))
544 else if (!strcmp(opt, "udp"))
546 else if (!strcmp(opt, "lock")) {
547 if (nfs_mount_version >= 3)
550 printf("Warning: option nolock is not supported.\n");
552 printf("unknown nfs mount option: %s%s\n", val ? "" : "no", opt);
557 proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP;
559 data.flags = (soft ? NFS_MOUNT_SOFT : 0)
560 | (intr ? NFS_MOUNT_INTR : 0)
561 | (posix ? NFS_MOUNT_POSIX : 0)
562 | (nocto ? NFS_MOUNT_NOCTO : 0)
563 | (noac ? NFS_MOUNT_NOAC : 0);
564 #if NFS_MOUNT_VERSION >= 2
565 if (nfs_mount_version >= 2)
566 data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
568 #if NFS_MOUNT_VERSION >= 3
569 if (nfs_mount_version >= 3)
570 data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
572 if (nfsvers > MAX_NFSPROT || mountvers > MAX_NFSPROT) {
573 bb_error_msg("NFSv%d not supported!", nfsvers);
576 if (nfsvers && !mountvers)
577 mountvers = (nfsvers < 3) ? 1 : nfsvers;
578 if (nfsvers && nfsvers < mountvers) {
582 /* Adjust options if none specified */
584 data.timeo = tcp ? 70 : 7;
586 #ifdef NFS_MOUNT_DEBUG
587 printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
588 data.rsize, data.wsize, data.timeo, data.retrans);
589 printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
590 data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
591 printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
592 port, bg, retry, data.flags);
593 printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",
594 mountprog, mountvers, nfsprog, nfsvers);
595 printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n",
596 (data.flags & NFS_MOUNT_SOFT) != 0,
597 (data.flags & NFS_MOUNT_INTR) != 0,
598 (data.flags & NFS_MOUNT_POSIX) != 0,
599 (data.flags & NFS_MOUNT_NOCTO) != 0,
600 (data.flags & NFS_MOUNT_NOAC) != 0);
601 #if NFS_MOUNT_VERSION >= 2
603 (data.flags & NFS_MOUNT_TCP) != 0);
607 data.version = nfs_mount_version;
609 if (*flags & MS_REMOUNT)
610 goto copy_data_and_return;
613 * If the previous mount operation on the same host was
614 * backgrounded, and the "bg" for this mount is also set,
615 * give up immediately, to avoid the initial timeout.
617 if (bg && !running_bg &&
618 prev_bg_host && strcmp(hostname, prev_bg_host) == 0) {
624 /* create mount daemon client */
625 /* See if the nfs host = mount host. */
627 if (mounthost[0] >= '0' && mounthost[0] <= '9') {
628 mount_server_addr.sin_family = AF_INET;
629 mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
631 if ((hp = gethostbyname(mounthost)) == NULL) {
632 bb_herror_msg("%s", mounthost);
635 if (hp->h_length > sizeof(struct in_addr)) {
636 bb_error_msg("got bad hp->h_length?");
637 hp->h_length = sizeof(struct in_addr);
639 mount_server_addr.sin_family = AF_INET;
640 memcpy(&mount_server_addr.sin_addr,
641 hp->h_addr, hp->h_length);
647 * The following loop implements the mount retries. On the first
648 * call, "running_bg" is 0. When the mount times out, and the
649 * "bg" option is set, the exit status EX_BG will be returned.
650 * For a backgrounded mount, there will be a second call by the
651 * child process with "running_bg" set to 1.
653 * The case where the mount point is not present and the "bg"
654 * option is set, is treated as a timeout. This is done to
655 * support nested mounts.
657 * The "retry" count specified by the user is the number of
658 * minutes to retry before giving up.
660 * Only the first error message will be displayed.
662 retry_timeout.tv_sec = 3;
663 retry_timeout.tv_usec = 0;
664 total_timeout.tv_sec = 20;
665 total_timeout.tv_usec = 0;
666 timeout = time(NULL) + 60 * retry;
671 if (bg && stat(node, &statbuf) == -1) {
673 sleep(val); /* 1, 2, 4, 8, 16, 30, ... */
679 /* be careful not to use too many CPU cycles */
683 pm_mnt = get_mountport(&mount_server_addr,
689 /* contact the mount daemon via TCP */
690 mount_server_addr.sin_port = htons(pm_mnt->pm_port);
693 switch (pm_mnt->pm_prot) {
695 mclient = clntudp_create(&mount_server_addr,
702 mount_server_addr.sin_port = htons(pm_mnt->pm_port);
705 mclient = clnttcp_create(&mount_server_addr,
714 /* try to mount hostname:pathname */
715 mclient->cl_auth = authunix_create_default();
717 /* make pointers in xdr_mountres3 NULL so
718 * that xdr_array allocates memory for us
720 memset(&status, 0, sizeof(status));
722 if (pm_mnt->pm_vers == 3)
723 clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT,
724 (xdrproc_t) xdr_dirpath,
726 (xdrproc_t) xdr_mountres3,
730 clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
731 (xdrproc_t) xdr_dirpath,
733 (xdrproc_t) xdr_fhstatus,
737 if (clnt_stat == RPC_SUCCESS)
738 break; /* we're done */
739 if (errno != ECONNREFUSED) {
740 clnt_perror(mclient, "mount");
741 goto fail; /* don't retry */
743 if (!running_bg && prevt == 0)
744 clnt_perror(mclient, "mount");
745 auth_destroy(mclient->cl_auth);
746 clnt_destroy(mclient);
750 if (!running_bg && prevt == 0)
751 clnt_pcreateerror("mount");
758 prev_bg_host = bb_xstrdup(hostname);
767 nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers;
770 if (status.nfsv2.fhs_status != 0) {
771 bb_error_msg("%s:%s failed, reason given by server: %s",
773 nfs_strerror(status.nfsv2.fhs_status));
776 memcpy(data.root.data,
777 (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
779 #if NFS_MOUNT_VERSION >= 4
780 data.root.size = NFS_FHSIZE;
781 memcpy(data.old_root.data,
782 (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
786 #if NFS_MOUNT_VERSION >= 4
787 fhandle3 *my_fhandle;
788 if (status.nfsv3.fhs_status != 0) {
789 bb_error_msg("%s:%s failed, reason given by server: %s",
791 nfs_strerror(status.nfsv3.fhs_status));
794 my_fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle;
795 memset(data.old_root.data, 0, NFS_FHSIZE);
796 memset(&data.root, 0, sizeof(data.root));
797 data.root.size = my_fhandle->fhandle3_len;
798 memcpy(data.root.data,
799 (char *) my_fhandle->fhandle3_val,
800 my_fhandle->fhandle3_len);
802 data.flags |= NFS_MOUNT_VER3;
806 /* create nfs socket for kernel */
809 if (nfs_mount_version < 3) {
810 printf("NFS over TCP is not supported.\n");
813 fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
815 fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
817 perror("nfs socket");
820 if (bindresvport(fsock, 0) < 0) {
821 perror("nfs bindresvport");
825 server_addr.sin_port = PMAPPORT;
826 port = pmap_getport(&server_addr, nfsprog, nfsvers,
827 tcp ? IPPROTO_TCP : IPPROTO_UDP);
830 #ifdef NFS_MOUNT_DEBUG
832 printf("used portmapper to find NFS port\n");
835 #ifdef NFS_MOUNT_DEBUG
836 printf("using port %d for nfs daemon\n", port);
838 server_addr.sin_port = htons(port);
840 * connect() the socket for kernels 1.3.10 and below only,
841 * to avoid problems with multihomed hosts.
844 if (get_linux_version_code() <= KERNEL_VERSION(2,3,10)
845 && connect(fsock, (struct sockaddr *) &server_addr,
846 sizeof (server_addr)) < 0) {
847 perror("nfs connect");
851 /* prepare data structure for kernel */
854 memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
855 strncpy(data.hostname, hostname, sizeof(data.hostname));
859 auth_destroy(mclient->cl_auth);
860 clnt_destroy(mclient);
862 copy_data_and_return:
863 *mount_opts = xrealloc(*mount_opts, sizeof(data));
864 memcpy(*mount_opts, &data, sizeof(data));
872 auth_destroy(mclient->cl_auth);
873 clnt_destroy(mclient);
883 * We need to translate between nfs status return values and
884 * the local errno values which may not be the same.
886 * Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>: change errno:
887 * "after #include <errno.h> the symbol errno is reserved for any use,
888 * it cannot even be used as a struct tag or field name".
892 #define EDQUOT ENOSPC
895 static const struct {
900 { NFSERR_PERM, EPERM },
901 { NFSERR_NOENT, ENOENT },
903 { NFSERR_NXIO, ENXIO },
904 { NFSERR_ACCES, EACCES },
905 { NFSERR_EXIST, EEXIST },
906 { NFSERR_NODEV, ENODEV },
907 { NFSERR_NOTDIR, ENOTDIR },
908 { NFSERR_ISDIR, EISDIR },
910 { NFSERR_INVAL, EINVAL }, /* that Sun forgot */
912 { NFSERR_FBIG, EFBIG },
913 { NFSERR_NOSPC, ENOSPC },
914 { NFSERR_ROFS, EROFS },
915 { NFSERR_NAMETOOLONG, ENAMETOOLONG },
916 { NFSERR_NOTEMPTY, ENOTEMPTY },
917 { NFSERR_DQUOT, EDQUOT },
918 { NFSERR_STALE, ESTALE },
920 { NFSERR_WFLUSH, EWFLUSH },
922 /* Throw in some NFSv3 values for even more fun (HP returns these) */
928 static char *nfs_strerror(int status)
931 static char buf[256];
933 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
934 if (nfs_errtbl[i].stat == status)
935 return strerror(nfs_errtbl[i].errnum);
937 sprintf(buf, "unknown nfs status return value: %d", status);
942 xdr_fhandle (XDR *xdrs, fhandle objp)
944 if (!xdr_opaque (xdrs, objp, FHSIZE))
950 xdr_fhstatus (XDR *xdrs, fhstatus *objp)
952 if (!xdr_u_int (xdrs, &objp->fhs_status))
954 switch (objp->fhs_status) {
956 if (!xdr_fhandle (xdrs, objp->fhstatus_u.fhs_fhandle))
966 xdr_dirpath (XDR *xdrs, dirpath *objp)
968 if (!xdr_string (xdrs, objp, MNTPATHLEN))
974 xdr_fhandle3 (XDR *xdrs, fhandle3 *objp)
976 if (!xdr_bytes (xdrs, (char **)&objp->fhandle3_val, (unsigned int *) &objp->fhandle3_len, FHSIZE3))
982 xdr_mountres3_ok (XDR *xdrs, mountres3_ok *objp)
984 if (!xdr_fhandle3 (xdrs, &objp->fhandle))
986 if (!xdr_array (xdrs, (char **)&objp->auth_flavours.auth_flavours_val, (unsigned int *) &objp->auth_flavours.auth_flavours_len, ~0,
987 sizeof (int), (xdrproc_t) xdr_int))
993 xdr_mountstat3 (XDR *xdrs, mountstat3 *objp)
995 if (!xdr_enum (xdrs, (enum_t *) objp))
1001 xdr_mountres3 (XDR *xdrs, mountres3 *objp)
1003 if (!xdr_mountstat3 (xdrs, &objp->fhs_status))
1005 switch (objp->fhs_status) {
1007 if (!xdr_mountres3_ok (xdrs, &objp->mountres3_u.mountinfo))