blob: f2bd2f49c05d9a202ee4d937753a5a506ce3757d [file] [log] [blame]
Eric Andersen1c43d0c1999-11-18 07:58:07 +00001/*
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
64static char *nfs_strerror(int stat);
65
66#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
67
68static int
69linux_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 */
85static 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 */
98static void
99find_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
112int 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
603fail:
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
629static 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
662static 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
676int
677my_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
759bool_t
760xdr_fhandle(XDR *xdrs, fhandle objp)
761{
762
763 if (!xdr_opaque(xdrs, objp, FHSIZE)) {
764 return (FALSE);
765 }
766 return (TRUE);
767}
768
769bool_t
770xdr_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
788bool_t
789xdr_dirpath(XDR *xdrs, dirpath *objp)
790{
791
792 if (!xdr_string(xdrs, objp, MNTPATHLEN)) {
793 return (FALSE);
794 }
795 return (TRUE);
796}
797
798bool_t
799xdr_name(XDR *xdrs, name *objp)
800{
801
802 if (!xdr_string(xdrs, objp, MNTNAMLEN)) {
803 return (FALSE);
804 }
805 return (TRUE);
806}
807
808bool_t
809xdr_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
818bool_t
819xdr_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
834bool_t
835xdr_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
844bool_t
845xdr_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
857bool_t
858xdr_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
867bool_t
868xdr_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
883bool_t
884xdr_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() */
1069static struct timeval TIMEOUT = { 25, 0 };
1070
1071void *
1072mountproc_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
1085fhstatus *
1086mountproc_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
1101mountlist *
1102mountproc_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
1117void *
1118mountproc_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
1133void *
1134mountproc_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
1149exports *
1150mountproc_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
1165exports *
1166mountproc_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
1181void *
1182mountproc_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
1195fhstatus *
1196mountproc_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
1211mountlist *
1212mountproc_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
1227void *
1228mountproc_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
1243void *
1244mountproc_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
1259exports *
1260mountproc_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
1275exports *
1276mountproc_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
1291ppathcnf *
1292mountproc_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