Fix a namespace aliasing problem wereby du and dutmp, or
[oweals/busybox.git] / nfsmount.c
1 /*
2  * nfsmount.c -- Linux NFS mount
3  * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * Wed Feb  8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port
16  * numbers to be specified on the command line.
17  *
18  * Fri, 8 Mar 1996 18:01:39, Swen Thuemmler <swen@uni-paderborn.de>:
19  * Omit the call to connect() for Linux version 1.3.11 or later.
20  *
21  * Wed Oct  1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com>
22  * Implemented the "bg", "fg" and "retry" mount options for NFS.
23  *
24  * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
25  * - added Native Language Support
26  * 
27  */
28
29 /*
30  * nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
31  */
32
33 #include <unistd.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <netdb.h>
38 #include <rpc/rpc.h>
39 #include <rpc/pmap_prot.h>
40 #include <rpc/pmap_clnt.h>
41 #include <sys/socket.h>
42 #include <sys/time.h>
43 #include <sys/utsname.h>
44 #include <sys/stat.h>
45 #include <netinet/in.h>
46 #include <arpa/inet.h>
47
48 #include "nfsmount.h"
49
50 #include <linux/nfs.h>
51 /* we suppose that libc-dev is providing NFSv3 headers (kernel >= 2.2) */
52 #include <linux/nfs_mount.h>
53
54 #define _
55 #define HAVE_inet_aton
56 #define MS_REMOUNT      32      /* Alter flags of a mounted FS */
57 #define sloppy 0
58 #define EX_FAIL 1
59 #define EX_BG 1
60 #define xstrdup strdup
61 #define xstrndup strndup
62
63
64 static char *nfs_strerror(int stat);
65
66 #define MAKE_VERSION(p,q,r)     (65536*(p) + 256*(q) + (r))
67
68 static int
69 linux_version_code(void) {
70         struct utsname my_utsname;
71         int p, q, r;
72
73         if (uname(&my_utsname) == 0) {
74                 p = atoi(strtok(my_utsname.release, "."));
75                 q = atoi(strtok(NULL, "."));
76                 r = atoi(strtok(NULL, "."));
77                 return MAKE_VERSION(p,q,r);
78         }
79         return 0;
80 }
81
82 /*
83  * nfs_mount_version according to the kernel sources seen at compile time.
84  */
85 static int nfs_mount_version = NFS_MOUNT_VERSION;
86
87 /*
88  * Unfortunately, the kernel prints annoying console messages
89  * in case of an unexpected nfs mount version (instead of
90  * just returning some error).  Therefore we'll have to try
91  * and figure out what version the kernel expects.
92  *
93  * Variables:
94  *      KERNEL_NFS_MOUNT_VERSION: kernel sources at compile time
95  *      NFS_MOUNT_VERSION: these nfsmount sources at compile time
96  *      nfs_mount_version: version this source and running kernel can handle
97  */
98 static void
99 find_kernel_nfs_mount_version(void) {
100         int kernel_version = linux_version_code();
101
102         if (kernel_version) {
103              if (kernel_version < MAKE_VERSION(2,1,32))
104                   nfs_mount_version = 1;
105              else
106                   nfs_mount_version = 3;
107         }
108         if (nfs_mount_version > NFS_MOUNT_VERSION)
109              nfs_mount_version = NFS_MOUNT_VERSION;
110 }
111
112 int nfsmount(const char *spec, const char *node, unsigned long *flags,
113              char **extra_opts, char **mount_opts, int running_bg)
114 {
115         static char *prev_bg_host;
116         char hostdir[1024];
117         CLIENT *mclient;
118         char *hostname;
119         char *dirname;
120         char *old_opts;
121         char *mounthost=NULL;
122         char new_opts[1024];
123         fhandle root_fhandle;
124         struct timeval total_timeout;
125         enum clnt_stat clnt_stat;
126         static struct nfs_mount_data data;
127         char *opt, *opteq;
128         int val;
129         struct hostent *hp;
130         struct sockaddr_in server_addr;
131         struct sockaddr_in mount_server_addr;
132         int msock, fsock;
133         struct timeval retry_timeout;
134         struct fhstatus status;
135         struct stat statbuf;
136         char *s;
137         int port;
138         int mountport;
139         int bg;
140         int soft;
141         int intr;
142         int posix;
143         int nocto;
144         int noac;
145         int nolock;
146         int retry;
147         int tcp;
148         int mountprog;
149         int mountvers;
150         int nfsprog;
151         int nfsvers;
152         int retval;
153         time_t t;
154         time_t prevt;
155         time_t timeout;
156
157         find_kernel_nfs_mount_version();
158
159         retval = EX_FAIL;
160         msock = fsock = -1;
161         mclient = NULL;
162         if (strlen(spec) >= sizeof(hostdir)) {
163                 fprintf(stderr, _("mount: "
164                         "excessively long host:dir argument\n"));
165                 goto fail;
166         }
167         strcpy(hostdir, spec);
168         if ((s = strchr(hostdir, ':'))) {
169                 hostname = hostdir;
170                 dirname = s + 1;
171                 *s = '\0';
172                 /* Ignore all but first hostname in replicated mounts
173                    until they can be fully supported. (mack@sgi.com) */
174                 if ((s = strchr(hostdir, ','))) {
175                         *s = '\0';
176                         fprintf(stderr, _("mount: warning: "
177                                 "multiple hostnames not supported\n"));
178                 }
179         } else {
180                 fprintf(stderr, _("mount: "
181                         "directory to mount not in host:dir format\n"));
182                 goto fail;
183         }
184
185         server_addr.sin_family = AF_INET;
186 #ifdef HAVE_inet_aton
187         if (!inet_aton(hostname, &server_addr.sin_addr))
188 #endif
189         {
190                 if ((hp = gethostbyname(hostname)) == NULL) {
191                         fprintf(stderr, _("mount: can't get address for %s\n"),
192                                 hostname);
193                         goto fail;
194                 } else {
195                         if (hp->h_length > sizeof(struct in_addr)) {
196                                 fprintf(stderr,
197                                         _("mount: got bad hp->h_length\n"));
198                                 hp->h_length = sizeof(struct in_addr);
199                         }
200                         memcpy(&server_addr.sin_addr,
201                                hp->h_addr, hp->h_length);
202                 }
203         }
204
205         memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr));
206
207         /* add IP address to mtab options for use when unmounting */
208
209         s = inet_ntoa(server_addr.sin_addr);
210         old_opts = *extra_opts;
211         if (!old_opts)
212                 old_opts = "";
213         if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
214                 fprintf(stderr, _("mount: "
215                         "excessively long option argument\n"));
216                 goto fail;
217         }
218         sprintf(new_opts, "%s%saddr=%s",
219                 old_opts, *old_opts ? "," : "", s);
220         *extra_opts = xstrdup(new_opts);
221
222         /* Set default options.
223          * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to
224          * let the kernel decide.
225          * timeo is filled in after we know whether it'll be TCP or UDP. */
226         memset(&data, 0, sizeof(data));
227         data.retrans    = 3;
228         data.acregmin   = 3;
229         data.acregmax   = 60;
230         data.acdirmin   = 30;
231         data.acdirmax   = 60;
232 #if NFS_MOUNT_VERSION >= 2
233         data.namlen     = NAME_MAX;
234 #endif
235
236         bg = 0;
237         soft = 0;
238         intr = 0;
239         posix = 0;
240         nocto = 0;
241         nolock = 0;
242         noac = 0;
243         retry = 10000;          /* 10000 minutes ~ 1 week */
244         tcp = 0;
245
246         mountprog = MOUNTPROG;
247         mountvers = MOUNTVERS;
248         port = 0;
249         mountport = 0;
250         nfsprog = NFS_PROGRAM;
251         nfsvers = NFS_VERSION;
252
253         /* parse options */
254
255         for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
256                 if ((opteq = strchr(opt, '='))) {
257                         val = atoi(opteq + 1);  
258                         *opteq = '\0';
259                         if (!strcmp(opt, "rsize"))
260                                 data.rsize = val;
261                         else if (!strcmp(opt, "wsize"))
262                                 data.wsize = val;
263                         else if (!strcmp(opt, "timeo"))
264                                 data.timeo = val;
265                         else if (!strcmp(opt, "retrans"))
266                                 data.retrans = val;
267                         else if (!strcmp(opt, "acregmin"))
268                                 data.acregmin = val;
269                         else if (!strcmp(opt, "acregmax"))
270                                 data.acregmax = val;
271                         else if (!strcmp(opt, "acdirmin"))
272                                 data.acdirmin = val;
273                         else if (!strcmp(opt, "acdirmax"))
274                                 data.acdirmax = val;
275                         else if (!strcmp(opt, "actimeo")) {
276                                 data.acregmin = val;
277                                 data.acregmax = val;
278                                 data.acdirmin = val;
279                                 data.acdirmax = val;
280                         }
281                         else if (!strcmp(opt, "retry"))
282                                 retry = val;
283                         else if (!strcmp(opt, "port"))
284                                 port = val;
285                         else if (!strcmp(opt, "mountport"))
286                                 mountport = val;
287                         else if (!strcmp(opt, "mounthost"))
288                                 mounthost=xstrndup(opteq+1,
289                                                   strcspn(opteq+1," \t\n\r,"));
290                         else if (!strcmp(opt, "mountprog"))
291                                 mountprog = val;
292                         else if (!strcmp(opt, "mountvers"))
293                                 mountvers = val;
294                         else if (!strcmp(opt, "nfsprog"))
295                                 nfsprog = val;
296                         else if (!strcmp(opt, "nfsvers") ||
297                                  !strcmp(opt, "vers"))
298                                 nfsvers = val;
299                         else if (!strcmp(opt, "proto")) {
300                                 if (!strncmp(opteq+1, "tcp", 3))
301                                         tcp = 1;
302                                 else if (!strncmp(opteq+1, "udp", 3))
303                                         tcp = 0;
304                                 else
305                                         printf(_("Warning: Unrecognized proto= option.\n"));
306                         } else if (!strcmp(opt, "namlen")) {
307 #if NFS_MOUNT_VERSION >= 2
308                                 if (nfs_mount_version >= 2)
309                                         data.namlen = val;
310                                 else
311 #endif
312                                 printf(_("Warning: Option namlen is not supported.\n"));
313                         } else if (!strcmp(opt, "addr"))
314                                 /* ignore */;
315                         else {
316                                 printf(_("unknown nfs mount parameter: "
317                                        "%s=%d\n"), opt, val);
318                                 goto fail;
319                         }
320                 }
321                 else {
322                         val = 1;
323                         if (!strncmp(opt, "no", 2)) {
324                                 val = 0;
325                                 opt += 2;
326                         }
327                         if (!strcmp(opt, "bg")) 
328                                 bg = val;
329                         else if (!strcmp(opt, "fg")) 
330                                 bg = !val;
331                         else if (!strcmp(opt, "soft"))
332                                 soft = val;
333                         else if (!strcmp(opt, "hard"))
334                                 soft = !val;
335                         else if (!strcmp(opt, "intr"))
336                                 intr = val;
337                         else if (!strcmp(opt, "posix"))
338                                 posix = val;
339                         else if (!strcmp(opt, "cto"))
340                                 nocto = !val;
341                         else if (!strcmp(opt, "ac"))
342                                 noac = !val;
343                         else if (!strcmp(opt, "tcp"))
344                                 tcp = val;
345                         else if (!strcmp(opt, "udp"))
346                                 tcp = !val;
347                         else if (!strcmp(opt, "lock")) {
348                                 if (nfs_mount_version >= 3)
349                                         nolock = !val;
350                                 else
351                                         printf(_("Warning: option nolock is not supported.\n"));
352                         } else {
353                                 if (!sloppy) {
354                                         printf(_("unknown nfs mount option: "
355                                                "%s%s\n"), val ? "" : "no", opt);
356                                         goto fail;
357                                 }
358                         }
359                 }
360         }
361         data.flags = (soft ? NFS_MOUNT_SOFT : 0)
362                 | (intr ? NFS_MOUNT_INTR : 0)
363                 | (posix ? NFS_MOUNT_POSIX : 0)
364                 | (nocto ? NFS_MOUNT_NOCTO : 0)
365                 | (noac ? NFS_MOUNT_NOAC : 0);
366 #if NFS_MOUNT_VERSION >= 2
367         if (nfs_mount_version >= 2)
368                 data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
369 #endif
370 #if NFS_MOUNT_VERSION >= 3
371         if (nfs_mount_version >= 3)
372                 data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
373 #endif
374
375         /* Adjust options if none specified */
376         if (!data.timeo)
377                 data.timeo = tcp ? 70 : 7;
378
379 #ifdef NFS_MOUNT_DEBUG
380         printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
381                 data.rsize, data.wsize, data.timeo, data.retrans);
382         printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
383                 data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
384         printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
385                 port, bg, retry, data.flags);
386         printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",
387                 mountprog, mountvers, nfsprog, nfsvers);
388         printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n",
389                 (data.flags & NFS_MOUNT_SOFT) != 0,
390                 (data.flags & NFS_MOUNT_INTR) != 0,
391                 (data.flags & NFS_MOUNT_POSIX) != 0,
392                 (data.flags & NFS_MOUNT_NOCTO) != 0,
393                 (data.flags & NFS_MOUNT_NOAC) != 0);
394 #if NFS_MOUNT_VERSION >= 2
395         printf("tcp = %d\n",
396                 (data.flags & NFS_MOUNT_TCP) != 0);
397 #endif
398 #endif
399
400         data.version = nfs_mount_version;
401         *mount_opts = (char *) &data;
402
403         if (*flags & MS_REMOUNT)
404                 return 0;
405
406         /*
407          * If the previous mount operation on the same host was
408          * backgrounded, and the "bg" for this mount is also set,
409          * give up immediately, to avoid the initial timeout.
410          */
411         if (bg && !running_bg &&
412             prev_bg_host && strcmp(hostname, prev_bg_host) == 0) {
413                 if (retry > 0)
414                         retval = EX_BG;
415                 return retval;
416         }
417
418         /* create mount deamon client */
419         /* See if the nfs host = mount host. */
420         if (mounthost) {
421           if (mounthost[0] >= '0' && mounthost[0] <= '9') {
422             mount_server_addr.sin_family = AF_INET;
423             mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
424           } else {
425                   if ((hp = gethostbyname(mounthost)) == NULL) {
426                           fprintf(stderr, _("mount: can't get address for %s\n"),
427                                   hostname);
428                           goto fail;
429                   } else {
430                           if (hp->h_length > sizeof(struct in_addr)) {
431                                   fprintf(stderr,
432                                           _("mount: got bad hp->h_length?\n"));
433                                   hp->h_length = sizeof(struct in_addr);
434                           }
435                           mount_server_addr.sin_family = AF_INET;
436                           memcpy(&mount_server_addr.sin_addr,
437                                  hp->h_addr, hp->h_length);
438                   }
439           }
440         }
441
442         /*
443          * The following loop implements the mount retries. On the first
444          * call, "running_bg" is 0. When the mount times out, and the
445          * "bg" option is set, the exit status EX_BG will be returned.
446          * For a backgrounded mount, there will be a second call by the
447          * child process with "running_bg" set to 1.
448          *
449          * The case where the mount point is not present and the "bg"
450          * option is set, is treated as a timeout. This is done to
451          * support nested mounts.
452          *
453          * The "retry" count specified by the user is the number of
454          * minutes to retry before giving up.
455          *
456          * Only the first error message will be displayed.
457          */
458         retry_timeout.tv_sec = 3;
459         retry_timeout.tv_usec = 0;
460         total_timeout.tv_sec = 20;
461         total_timeout.tv_usec = 0;
462         timeout = time(NULL) + 60 * retry;
463         prevt = 0;
464         t = 30;
465         val = 1;
466         for (;;) {
467                 if (bg && stat(node, &statbuf) == -1) {
468                         if (running_bg) {
469                                 sleep(val);     /* 1, 2, 4, 8, 16, 30, ... */
470                                 val *= 2;
471                                 if (val > 30)
472                                         val = 30;
473                         }
474                 } else {
475                         /* be careful not to use too many CPU cycles */
476                         if (t - prevt < 30)
477                                 sleep(30);
478
479                         /* contact the mount daemon via TCP */
480                         mount_server_addr.sin_port = htons(mountport);
481                         msock = RPC_ANYSOCK;
482                         mclient = clnttcp_create(&mount_server_addr,
483                                                  mountprog, mountvers,
484                                                  &msock, 0, 0);
485
486                         /* if this fails, contact the mount daemon via UDP */
487                         if (!mclient) {
488                                 mount_server_addr.sin_port = htons(mountport);
489                                 msock = RPC_ANYSOCK;
490                                 mclient = clntudp_create(&mount_server_addr,
491                                                          mountprog, mountvers,
492                                                          retry_timeout, &msock);
493                         }
494                         if (mclient) {
495                                 /* try to mount hostname:dirname */
496                                 mclient->cl_auth = authunix_create_default();
497                                 clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
498                                         (xdrproc_t) xdr_dirpath, (caddr_t) &dirname,
499                                         (xdrproc_t) xdr_fhstatus, (caddr_t) &status,
500                                         total_timeout);
501                                 if (clnt_stat == RPC_SUCCESS)
502                                         break;          /* we're done */
503                                 if (errno != ECONNREFUSED) {
504                                         clnt_perror(mclient, "mount");
505                                         goto fail;      /* don't retry */
506                                 }
507                                 if (!running_bg && prevt == 0)
508                                         clnt_perror(mclient, "mount");
509                                 auth_destroy(mclient->cl_auth);
510                                 clnt_destroy(mclient);
511                                 mclient = 0;
512                                 close(msock);
513                         } else {
514                                 if (!running_bg && prevt == 0)
515                                         clnt_pcreateerror("mount");
516                         }
517                         prevt = t;
518                 }
519                 if (!bg)
520                         goto fail;
521                 if (!running_bg) {
522                         prev_bg_host = xstrdup(hostname);
523                         if (retry > 0)
524                                 retval = EX_BG;
525                         goto fail;
526                 }
527                 t = time(NULL);
528                 if (t >= timeout)
529                         goto fail;
530         }
531
532         if (status.fhs_status != 0) {
533                 fprintf(stderr,
534                         _("mount: %s:%s failed, reason given by server: %s\n"),
535                         hostname, dirname, nfs_strerror(status.fhs_status));
536                 goto fail;
537         }
538         memcpy((char *) &root_fhandle, (char *) status.fhstatus_u.fhs_fhandle,
539                 sizeof (root_fhandle));
540
541         /* create nfs socket for kernel */
542
543         if (tcp) {
544                 if (nfs_mount_version < 3) {
545                         printf(_("NFS over TCP is not supported.\n"));
546                         goto fail;
547                 }
548                 fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
549         } else
550                 fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
551         if (fsock < 0) {
552                 perror(_("nfs socket"));
553                 goto fail;
554         }
555         if (bindresvport(fsock, 0) < 0) {
556                 perror(_("nfs bindresvport"));
557                 goto fail;
558         }
559         if (port == 0) {
560                 server_addr.sin_port = PMAPPORT;
561                 port = pmap_getport(&server_addr, nfsprog, nfsvers,
562                         tcp ? IPPROTO_TCP : IPPROTO_UDP);
563                 if (port == 0)
564                         port = NFS_PORT;
565 #ifdef NFS_MOUNT_DEBUG
566                 else
567                         printf(_("used portmapper to find NFS port\n"));
568 #endif
569         }
570 #ifdef NFS_MOUNT_DEBUG
571         printf(_("using port %d for nfs deamon\n"), port);
572 #endif
573         server_addr.sin_port = htons(port);
574          /*
575           * connect() the socket for kernels 1.3.10 and below only,
576           * to avoid problems with multihomed hosts.
577           * --Swen
578           */
579         if (linux_version_code() <= 66314
580             && connect(fsock, (struct sockaddr *) &server_addr,
581                        sizeof (server_addr)) < 0) {
582                 perror(_("nfs connect"));
583                 goto fail;
584         }
585
586         /* prepare data structure for kernel */
587
588         data.fd = fsock;
589         memcpy((char *) &data.root, (char *) &root_fhandle,
590                 sizeof (root_fhandle));
591         memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
592         strncpy(data.hostname, hostname, sizeof(data.hostname));
593
594         /* clean up */
595
596         auth_destroy(mclient->cl_auth);
597         clnt_destroy(mclient);
598         close(msock);
599         return 0;
600
601         /* abort */
602
603 fail:
604         if (msock != -1) {
605                 if (mclient) {
606                         auth_destroy(mclient->cl_auth);
607                         clnt_destroy(mclient);
608                 }
609                 close(msock);
610         }
611         if (fsock != -1)
612                 close(fsock);
613         return retval;
614 }       
615
616 /*
617  * We need to translate between nfs status return values and
618  * the local errno values which may not be the same.
619  *
620  * Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>: change errno:
621  * "after #include <errno.h> the symbol errno is reserved for any use,
622  *  it cannot even be used as a struct tag or field name".
623  */
624
625 #ifndef EDQUOT
626 #define EDQUOT  ENOSPC
627 #endif
628
629 static struct {
630         enum nfs_stat stat;
631         int errnum;
632 } nfs_errtbl[] = {
633         { NFS_OK,               0               },
634         { NFSERR_PERM,          EPERM           },
635         { NFSERR_NOENT,         ENOENT          },
636         { NFSERR_IO,            EIO             },
637         { NFSERR_NXIO,          ENXIO           },
638         { NFSERR_ACCES,         EACCES          },
639         { NFSERR_EXIST,         EEXIST          },
640         { NFSERR_NODEV,         ENODEV          },
641         { NFSERR_NOTDIR,        ENOTDIR         },
642         { NFSERR_ISDIR,         EISDIR          },
643 #ifdef NFSERR_INVAL
644         { NFSERR_INVAL,         EINVAL          },      /* that Sun forgot */
645 #endif
646         { NFSERR_FBIG,          EFBIG           },
647         { NFSERR_NOSPC,         ENOSPC          },
648         { NFSERR_ROFS,          EROFS           },
649         { NFSERR_NAMETOOLONG,   ENAMETOOLONG    },
650         { NFSERR_NOTEMPTY,      ENOTEMPTY       },
651         { NFSERR_DQUOT,         EDQUOT          },
652         { NFSERR_STALE,         ESTALE          },
653 #ifdef EWFLUSH
654         { NFSERR_WFLUSH,        EWFLUSH         },
655 #endif
656         /* Throw in some NFSv3 values for even more fun (HP returns these) */
657         { 71,                   EREMOTE         },
658
659         { -1,                   EIO             }
660 };
661
662 static char *nfs_strerror(int stat)
663 {
664         int i;
665         static char buf[256];
666
667         for (i = 0; nfs_errtbl[i].stat != -1; i++) {
668                 if (nfs_errtbl[i].stat == stat)
669                         return strerror(nfs_errtbl[i].errnum);
670         }
671         sprintf(buf, _("unknown nfs status return value: %d"), stat);
672         return buf;
673 }
674
675 #if 0
676 int
677 my_getport(struct in_addr server, struct timeval *timeo, ...)
678 {
679         struct sockaddr_in sin;
680         struct pmap     pmap;
681         CLIENT          *clnt;
682         int             sock = RPC_ANYSOCK, port;
683
684         pmap.pm_prog = prog;
685         pmap.pm_vers = vers;
686         pmap.pm_prot = prot;
687         pmap.pm_port = 0;
688         sin.sin_family = AF_INET;
689         sin.sin_addr = server;
690         sin.sin_port = htons(111);
691         clnt = clntudp_create(&sin, 100000, 2, *timeo, &sock);
692         status = clnt_call(clnt, PMAP_GETPORT,
693                                 &pmap, (xdrproc_t) xdr_pmap,
694                                 &port, (xdrproc_t) xdr_uint);
695         if (status != SUCCESS) {
696              /* natter */
697                 port = 0;
698         }
699
700         clnt_destroy(clnt);
701         close(sock);
702         return port;
703 }
704 #endif
705
706
707
708
709
710
711
712
713
714
715
716 /*
717  * Please do not edit this file.
718  * It was generated using rpcgen.
719  */
720
721 #include <rpc/types.h>
722 #include <rpc/xdr.h>
723
724 /*
725  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
726  * unrestricted use provided that this legend is included on all tape
727  * media and as a part of the software program in whole or part.  Users
728  * may copy or modify Sun RPC without charge, but are not authorized
729  * to license or distribute it to anyone else except as part of a product or
730  * program developed by the user or with the express written consent of
731  * Sun Microsystems, Inc.
732  *
733  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
734  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
735  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
736  *
737  * Sun RPC is provided with no support and without any obligation on the
738  * part of Sun Microsystems, Inc. to assist in its use, correction,
739  * modification or enhancement.
740  *
741  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
742  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
743  * OR ANY PART THEREOF.
744  *
745  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
746  * or profits or other special, indirect and consequential damages, even if
747  * Sun has been advised of the possibility of such damages.
748  *
749  * Sun Microsystems, Inc.
750  * 2550 Garcia Avenue
751  * Mountain View, California  94043
752  */
753 /*
754  * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
755  */
756
757 /* from @(#)mount.x     1.3 91/03/11 TIRPC 1.0 */
758
759 bool_t
760 xdr_fhandle(XDR *xdrs, fhandle objp)
761 {
762
763          if (!xdr_opaque(xdrs, objp, FHSIZE)) {
764                  return (FALSE);
765          }
766         return (TRUE);
767 }
768
769 bool_t
770 xdr_fhstatus(XDR *xdrs, fhstatus *objp)
771 {
772
773          if (!xdr_u_int(xdrs, &objp->fhs_status)) {
774                  return (FALSE);
775          }
776         switch (objp->fhs_status) {
777         case 0:
778                  if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) {
779                          return (FALSE);
780                  }
781                 break;
782         default:
783                 break;
784         }
785         return (TRUE);
786 }
787
788 bool_t
789 xdr_dirpath(XDR *xdrs, dirpath *objp)
790 {
791
792          if (!xdr_string(xdrs, objp, MNTPATHLEN)) {
793                  return (FALSE);
794          }
795         return (TRUE);
796 }
797
798 bool_t
799 xdr_name(XDR *xdrs, name *objp)
800 {
801
802          if (!xdr_string(xdrs, objp, MNTNAMLEN)) {
803                  return (FALSE);
804          }
805         return (TRUE);
806 }
807
808 bool_t
809 xdr_mountlist(XDR *xdrs, mountlist *objp)
810 {
811
812          if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct mountbody), (xdrproc_t)xdr_mountbody)) {
813                  return (FALSE);
814          }
815         return (TRUE);
816 }
817
818 bool_t
819 xdr_mountbody(XDR *xdrs, mountbody *objp)
820 {
821
822          if (!xdr_name(xdrs, &objp->ml_hostname)) {
823                  return (FALSE);
824          }
825          if (!xdr_dirpath(xdrs, &objp->ml_directory)) {
826                  return (FALSE);
827          }
828          if (!xdr_mountlist(xdrs, &objp->ml_next)) {
829                  return (FALSE);
830          }
831         return (TRUE);
832 }
833
834 bool_t
835 xdr_groups(XDR *xdrs, groups *objp)
836 {
837
838          if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct groupnode), (xdrproc_t)xdr_groupnode)) {
839                  return (FALSE);
840          }
841         return (TRUE);
842 }
843
844 bool_t
845 xdr_groupnode(XDR *xdrs, groupnode *objp)
846 {
847
848          if (!xdr_name(xdrs, &objp->gr_name)) {
849                  return (FALSE);
850          }
851          if (!xdr_groups(xdrs, &objp->gr_next)) {
852                  return (FALSE);
853          }
854         return (TRUE);
855 }
856
857 bool_t
858 xdr_exports(XDR *xdrs, exports *objp)
859 {
860
861          if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct exportnode), (xdrproc_t)xdr_exportnode)) {
862                  return (FALSE);
863          }
864         return (TRUE);
865 }
866
867 bool_t
868 xdr_exportnode(XDR *xdrs, exportnode *objp)
869 {
870
871          if (!xdr_dirpath(xdrs, &objp->ex_dir)) {
872                  return (FALSE);
873          }
874          if (!xdr_groups(xdrs, &objp->ex_groups)) {
875                  return (FALSE);
876          }
877          if (!xdr_exports(xdrs, &objp->ex_next)) {
878                  return (FALSE);
879          }
880         return (TRUE);
881 }
882
883 bool_t
884 xdr_ppathcnf(XDR *xdrs, ppathcnf *objp)
885 {
886
887          register long *buf;
888
889          int i;
890
891          if (xdrs->x_op == XDR_ENCODE) {
892          buf = (long*)XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT);
893            if (buf == NULL) {
894                  if (!xdr_int(xdrs, &objp->pc_link_max)) {
895                          return (FALSE);
896                  }
897                  if (!xdr_short(xdrs, &objp->pc_max_canon)) {
898                          return (FALSE);
899                  }
900                  if (!xdr_short(xdrs, &objp->pc_max_input)) {
901                          return (FALSE);
902                  }
903                  if (!xdr_short(xdrs, &objp->pc_name_max)) {
904                          return (FALSE);
905                  }
906                  if (!xdr_short(xdrs, &objp->pc_path_max)) {
907                          return (FALSE);
908                  }
909                  if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
910                          return (FALSE);
911                  }
912
913           }
914           else {
915                  IXDR_PUT_LONG(buf,objp->pc_link_max);
916                  IXDR_PUT_SHORT(buf,objp->pc_max_canon);
917                  IXDR_PUT_SHORT(buf,objp->pc_max_input);
918                  IXDR_PUT_SHORT(buf,objp->pc_name_max);
919                  IXDR_PUT_SHORT(buf,objp->pc_path_max);
920                  IXDR_PUT_SHORT(buf,objp->pc_pipe_buf);
921           }
922          if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
923                  return (FALSE);
924          }
925          if (!xdr_char(xdrs, &objp->pc_xxx)) {
926                  return (FALSE);
927          }
928                 buf = (long*)XDR_INLINE(xdrs,   2  * BYTES_PER_XDR_UNIT);
929                 if (buf == NULL) {
930                  if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) {
931                          return (FALSE);
932                  }
933
934           }
935           else {
936                 { register short *genp; 
937                   for ( i = 0,genp=objp->pc_mask;
938                         i < 2; i++){
939                                  IXDR_PUT_SHORT(buf,*genp++);
940                    }
941                  };
942           }
943
944          return (TRUE);
945         } else if (xdrs->x_op == XDR_DECODE) {
946          buf = (long*)XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT);
947            if (buf == NULL) {
948                  if (!xdr_int(xdrs, &objp->pc_link_max)) {
949                          return (FALSE);
950                  }
951                  if (!xdr_short(xdrs, &objp->pc_max_canon)) {
952                          return (FALSE);
953                  }
954                  if (!xdr_short(xdrs, &objp->pc_max_input)) {
955                          return (FALSE);
956                  }
957                  if (!xdr_short(xdrs, &objp->pc_name_max)) {
958                          return (FALSE);
959                  }
960                  if (!xdr_short(xdrs, &objp->pc_path_max)) {
961                          return (FALSE);
962                  }
963                  if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
964                          return (FALSE);
965                  }
966
967           }
968           else {
969                  objp->pc_link_max = IXDR_GET_LONG(buf);
970                  objp->pc_max_canon = IXDR_GET_SHORT(buf);
971                  objp->pc_max_input = IXDR_GET_SHORT(buf);
972                  objp->pc_name_max = IXDR_GET_SHORT(buf);
973                  objp->pc_path_max = IXDR_GET_SHORT(buf);
974                  objp->pc_pipe_buf = IXDR_GET_SHORT(buf);
975           }
976          if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
977                  return (FALSE);
978          }
979          if (!xdr_char(xdrs, &objp->pc_xxx)) {
980                  return (FALSE);
981          }
982                 buf = (long*)XDR_INLINE(xdrs,   2  * BYTES_PER_XDR_UNIT);
983                 if (buf == NULL) {
984                  if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) {
985                          return (FALSE);
986                  }
987
988           }
989           else {
990                 { register short *genp; 
991                   for ( i = 0,genp=objp->pc_mask;
992                         i < 2; i++){
993                                  *genp++ = IXDR_GET_SHORT(buf);
994                    }
995                  };
996           }
997          return(TRUE);
998         }
999
1000          if (!xdr_int(xdrs, &objp->pc_link_max)) {
1001                  return (FALSE);
1002          }
1003          if (!xdr_short(xdrs, &objp->pc_max_canon)) {
1004                  return (FALSE);
1005          }
1006          if (!xdr_short(xdrs, &objp->pc_max_input)) {
1007                  return (FALSE);
1008          }
1009          if (!xdr_short(xdrs, &objp->pc_name_max)) {
1010                  return (FALSE);
1011          }
1012          if (!xdr_short(xdrs, &objp->pc_path_max)) {
1013                  return (FALSE);
1014          }
1015          if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
1016                  return (FALSE);
1017          }
1018          if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
1019                  return (FALSE);
1020          }
1021          if (!xdr_char(xdrs, &objp->pc_xxx)) {
1022                  return (FALSE);
1023          }
1024          if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) {
1025                  return (FALSE);
1026          }
1027         return (TRUE);
1028 }
1029
1030
1031 /*
1032  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
1033  * unrestricted use provided that this legend is included on all tape
1034  * media and as a part of the software program in whole or part.  Users
1035  * may copy or modify Sun RPC without charge, but are not authorized
1036  * to license or distribute it to anyone else except as part of a product or
1037  * program developed by the user or with the express written consent of
1038  * Sun Microsystems, Inc.
1039  *
1040  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1041  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1042  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1043  *
1044  * Sun RPC is provided with no support and without any obligation on the
1045  * part of Sun Microsystems, Inc. to assist in its use, correction,
1046  * modification or enhancement.
1047  *
1048  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
1049  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
1050  * OR ANY PART THEREOF.
1051  *
1052  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
1053  * or profits or other special, indirect and consequential damages, even if
1054  * Sun has been advised of the possibility of such damages.
1055  *
1056  * Sun Microsystems, Inc.
1057  * 2550 Garcia Avenue
1058  * Mountain View, California  94043
1059  */
1060 /*
1061  * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
1062  */
1063
1064 /* from @(#)mount.x     1.3 91/03/11 TIRPC 1.0 */
1065
1066 #include <string.h>            /* for memset() */
1067
1068 /* Default timeout can be changed using clnt_control() */
1069 static struct timeval TIMEOUT = { 25, 0 };
1070
1071 void *
1072 mountproc_null_1(argp, clnt)
1073         void *argp;
1074         CLIENT *clnt;
1075 {
1076         static char clnt_res;
1077
1078         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1079         if (clnt_call(clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1080                 return (NULL);
1081         }
1082         return ((void *)&clnt_res);
1083 }
1084
1085 fhstatus *
1086 mountproc_mnt_1(argp, clnt)
1087         dirpath *argp;
1088         CLIENT *clnt;
1089 {
1090         static fhstatus clnt_res;
1091
1092         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1093         if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath,
1094                       (caddr_t) argp, (xdrproc_t) xdr_fhstatus,
1095                       (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1096                 return (NULL);
1097         }
1098         return (&clnt_res);
1099 }
1100
1101 mountlist *
1102 mountproc_dump_1(argp, clnt)
1103         void *argp;
1104         CLIENT *clnt;
1105 {
1106         static mountlist clnt_res;
1107
1108         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1109         if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void,
1110                       (caddr_t) argp, (xdrproc_t) xdr_mountlist,
1111                       (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1112                 return (NULL);
1113         }
1114         return (&clnt_res);
1115 }
1116
1117 void *
1118 mountproc_umnt_1(argp, clnt)
1119         dirpath *argp;
1120         CLIENT *clnt;
1121 {
1122         static char clnt_res;
1123
1124         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1125         if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath,
1126                       (caddr_t) argp, (xdrproc_t) xdr_void,
1127                       (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1128                 return (NULL);
1129         }
1130         return ((void *)&clnt_res);
1131 }
1132
1133 void *
1134 mountproc_umntall_1(argp, clnt)
1135         void *argp;
1136         CLIENT *clnt;
1137 {
1138         static char clnt_res;
1139
1140         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1141         if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void,
1142                       (caddr_t) argp, (xdrproc_t) xdr_void,
1143                       (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1144                 return (NULL);
1145         }
1146         return ((void *)&clnt_res);
1147 }
1148
1149 exports *
1150 mountproc_export_1(argp, clnt)
1151         void *argp;
1152         CLIENT *clnt;
1153 {
1154         static exports clnt_res;
1155
1156         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1157         if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void,
1158                       (caddr_t) argp, (xdrproc_t) xdr_exports,
1159                       (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1160                 return (NULL);
1161         }
1162         return (&clnt_res);
1163 }
1164
1165 exports *
1166 mountproc_exportall_1(argp, clnt)
1167         void *argp;
1168         CLIENT *clnt;
1169 {
1170         static exports clnt_res;
1171
1172         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1173         if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void,
1174                       (caddr_t) argp, (xdrproc_t) xdr_exports,
1175                       (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1176           return (NULL);
1177         }
1178         return (&clnt_res);
1179 }
1180
1181 void *
1182 mountproc_null_2(argp, clnt)
1183         void *argp;
1184         CLIENT *clnt;
1185 {
1186         static char clnt_res;
1187
1188         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1189         if (clnt_call(clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1190                 return (NULL);
1191         }
1192         return ((void *)&clnt_res);
1193 }
1194
1195 fhstatus *
1196 mountproc_mnt_2(argp, clnt)
1197         dirpath *argp;
1198         CLIENT *clnt;
1199 {
1200         static fhstatus clnt_res;
1201
1202         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1203         if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath,
1204                       (caddr_t) argp, (xdrproc_t) xdr_fhstatus,
1205                       (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1206                 return (NULL);
1207         }
1208         return (&clnt_res);
1209 }
1210
1211 mountlist *
1212 mountproc_dump_2(argp, clnt)
1213         void *argp;
1214         CLIENT *clnt;
1215 {
1216         static mountlist clnt_res;
1217
1218         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1219         if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp,
1220                       (xdrproc_t) xdr_mountlist, (caddr_t) &clnt_res,
1221                       TIMEOUT) != RPC_SUCCESS) {
1222                 return (NULL);
1223         }
1224         return (&clnt_res);
1225 }
1226
1227 void *
1228 mountproc_umnt_2(argp, clnt)
1229         dirpath *argp;
1230         CLIENT *clnt;
1231 {
1232         static char clnt_res;
1233
1234         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1235         if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath,
1236                       (caddr_t) argp, (xdrproc_t) xdr_void,
1237                       (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1238                 return (NULL);
1239         }
1240         return ((void *)&clnt_res);
1241 }
1242
1243 void *
1244 mountproc_umntall_2(argp, clnt)
1245         void *argp;
1246         CLIENT *clnt;
1247 {
1248         static char clnt_res;
1249
1250         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1251         if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void,
1252                       (caddr_t) argp, (xdrproc_t) xdr_void,
1253                       (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1254                 return (NULL);
1255         }
1256         return ((void *)&clnt_res);
1257 }
1258
1259 exports *
1260 mountproc_export_2(argp, clnt)
1261         void *argp;
1262         CLIENT *clnt;
1263 {
1264         static exports clnt_res;
1265
1266         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1267         if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void,
1268                       argp, (xdrproc_t) xdr_exports, (caddr_t) &clnt_res,
1269                       TIMEOUT) != RPC_SUCCESS) {
1270                 return (NULL);
1271         }
1272         return (&clnt_res);
1273 }
1274
1275 exports *
1276 mountproc_exportall_2(argp, clnt)
1277         void *argp;
1278         CLIENT *clnt;
1279 {
1280         static exports clnt_res;
1281
1282         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1283         if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp,
1284                       (xdrproc_t) xdr_exports, (caddr_t) &clnt_res,
1285                       TIMEOUT) != RPC_SUCCESS) {
1286                 return (NULL);
1287         }
1288         return (&clnt_res);
1289 }
1290
1291 ppathcnf *
1292 mountproc_pathconf_2(argp, clnt)
1293         dirpath *argp;
1294         CLIENT *clnt;
1295 {
1296         static ppathcnf clnt_res;
1297
1298         memset((char *)&clnt_res, 0, sizeof(clnt_res));
1299         if (clnt_call(clnt, MOUNTPROC_PATHCONF, (xdrproc_t) xdr_dirpath,
1300                       (caddr_t) argp, (xdrproc_t) xdr_ppathcnf,
1301                       (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) {
1302                 return (NULL);
1303         }
1304         return (&clnt_res);
1305 }
1306
1307
1308
1309