/* * nfsmount.c -- Linux NFS mount * Copyright (C) 1993 Rick Sladkey * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Wed Feb 8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port * numbers to be specified on the command line. * * Fri, 8 Mar 1996 18:01:39, Swen Thuemmler : * Omit the call to connect() for Linux version 1.3.11 or later. * * Wed Oct 1 23:55:28 1997: Dick Streefland * Implemented the "bg", "fg" and "retry" mount options for NFS. * * 1999-02-22 Arkadiusz Mi¶kiewicz * - added Native Language Support * */ /* * nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nfsmount.h" #include /* we suppose that libc-dev is providing NFSv3 headers (kernel >= 2.2) */ #include #define _ #define HAVE_inet_aton #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ #define sloppy 0 #define EX_FAIL 1 #define EX_BG 1 #define xstrdup strdup #define xstrndup strndup static char *nfs_strerror(int stat); #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) static int linux_version_code(void) { struct utsname my_utsname; int p, q, r; if (uname(&my_utsname) == 0) { p = atoi(strtok(my_utsname.release, ".")); q = atoi(strtok(NULL, ".")); r = atoi(strtok(NULL, ".")); return MAKE_VERSION(p,q,r); } return 0; } /* * nfs_mount_version according to the kernel sources seen at compile time. */ static int nfs_mount_version = NFS_MOUNT_VERSION; /* * Unfortunately, the kernel prints annoying console messages * in case of an unexpected nfs mount version (instead of * just returning some error). Therefore we'll have to try * and figure out what version the kernel expects. * * Variables: * KERNEL_NFS_MOUNT_VERSION: kernel sources at compile time * NFS_MOUNT_VERSION: these nfsmount sources at compile time * nfs_mount_version: version this source and running kernel can handle */ static void find_kernel_nfs_mount_version(void) { int kernel_version = linux_version_code(); if (kernel_version) { if (kernel_version < MAKE_VERSION(2,1,32)) nfs_mount_version = 1; else nfs_mount_version = 3; } if (nfs_mount_version > NFS_MOUNT_VERSION) nfs_mount_version = NFS_MOUNT_VERSION; } int nfsmount(const char *spec, const char *node, unsigned long *flags, char **extra_opts, char **mount_opts, int running_bg) { static char *prev_bg_host; char hostdir[1024]; CLIENT *mclient; char *hostname; char *dirname; char *old_opts; char *mounthost=NULL; char new_opts[1024]; fhandle root_fhandle; struct timeval total_timeout; enum clnt_stat clnt_stat; static struct nfs_mount_data data; char *opt, *opteq; int val; struct hostent *hp; struct sockaddr_in server_addr; struct sockaddr_in mount_server_addr; int msock, fsock; struct timeval retry_timeout; struct fhstatus status; struct stat statbuf; char *s; int port; int mountport; int bg; int soft; int intr; int posix; int nocto; int noac; int nolock; int retry; int tcp; int mountprog; int mountvers; int nfsprog; int nfsvers; int retval; time_t t; time_t prevt; time_t timeout; find_kernel_nfs_mount_version(); retval = EX_FAIL; msock = fsock = -1; mclient = NULL; if (strlen(spec) >= sizeof(hostdir)) { fprintf(stderr, _("mount: " "excessively long host:dir argument\n")); goto fail; } strcpy(hostdir, spec); if ((s = strchr(hostdir, ':'))) { hostname = hostdir; dirname = s + 1; *s = '\0'; /* Ignore all but first hostname in replicated mounts until they can be fully supported. (mack@sgi.com) */ if ((s = strchr(hostdir, ','))) { *s = '\0'; fprintf(stderr, _("mount: warning: " "multiple hostnames not supported\n")); } } else { fprintf(stderr, _("mount: " "directory to mount not in host:dir format\n")); goto fail; } server_addr.sin_family = AF_INET; #ifdef HAVE_inet_aton if (!inet_aton(hostname, &server_addr.sin_addr)) #endif { if ((hp = gethostbyname(hostname)) == NULL) { fprintf(stderr, _("mount: can't get address for %s\n"), hostname); goto fail; } else { if (hp->h_length > sizeof(struct in_addr)) { fprintf(stderr, _("mount: got bad hp->h_length\n")); hp->h_length = sizeof(struct in_addr); } memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); } } memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr)); /* add IP address to mtab options for use when unmounting */ s = inet_ntoa(server_addr.sin_addr); old_opts = *extra_opts; if (!old_opts) old_opts = ""; if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) { fprintf(stderr, _("mount: " "excessively long option argument\n")); goto fail; } sprintf(new_opts, "%s%saddr=%s", old_opts, *old_opts ? "," : "", s); *extra_opts = xstrdup(new_opts); /* Set default options. * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to * let the kernel decide. * timeo is filled in after we know whether it'll be TCP or UDP. */ memset(&data, 0, sizeof(data)); data.retrans = 3; data.acregmin = 3; data.acregmax = 60; data.acdirmin = 30; data.acdirmax = 60; #if NFS_MOUNT_VERSION >= 2 data.namlen = NAME_MAX; #endif bg = 0; soft = 0; intr = 0; posix = 0; nocto = 0; nolock = 0; noac = 0; retry = 10000; /* 10000 minutes ~ 1 week */ tcp = 0; mountprog = MOUNTPROG; mountvers = MOUNTVERS; port = 0; mountport = 0; nfsprog = NFS_PROGRAM; nfsvers = NFS_VERSION; /* parse options */ for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) { if ((opteq = strchr(opt, '='))) { val = atoi(opteq + 1); *opteq = '\0'; if (!strcmp(opt, "rsize")) data.rsize = val; else if (!strcmp(opt, "wsize")) data.wsize = val; else if (!strcmp(opt, "timeo")) data.timeo = val; else if (!strcmp(opt, "retrans")) data.retrans = val; else if (!strcmp(opt, "acregmin")) data.acregmin = val; else if (!strcmp(opt, "acregmax")) data.acregmax = val; else if (!strcmp(opt, "acdirmin")) data.acdirmin = val; else if (!strcmp(opt, "acdirmax")) data.acdirmax = val; else if (!strcmp(opt, "actimeo")) { data.acregmin = val; data.acregmax = val; data.acdirmin = val; data.acdirmax = val; } else if (!strcmp(opt, "retry")) retry = val; else if (!strcmp(opt, "port")) port = val; else if (!strcmp(opt, "mountport")) mountport = val; else if (!strcmp(opt, "mounthost")) mounthost=xstrndup(opteq+1, strcspn(opteq+1," \t\n\r,")); else if (!strcmp(opt, "mountprog")) mountprog = val; else if (!strcmp(opt, "mountvers")) mountvers = val; else if (!strcmp(opt, "nfsprog")) nfsprog = val; else if (!strcmp(opt, "nfsvers") || !strcmp(opt, "vers")) nfsvers = val; else if (!strcmp(opt, "proto")) { if (!strncmp(opteq+1, "tcp", 3)) tcp = 1; else if (!strncmp(opteq+1, "udp", 3)) tcp = 0; else printf(_("Warning: Unrecognized proto= option.\n")); } else if (!strcmp(opt, "namlen")) { #if NFS_MOUNT_VERSION >= 2 if (nfs_mount_version >= 2) data.namlen = val; else #endif printf(_("Warning: Option namlen is not supported.\n")); } else if (!strcmp(opt, "addr")) /* ignore */; else { printf(_("unknown nfs mount parameter: " "%s=%d\n"), opt, val); goto fail; } } else { val = 1; if (!strncmp(opt, "no", 2)) { val = 0; opt += 2; } if (!strcmp(opt, "bg")) bg = val; else if (!strcmp(opt, "fg")) bg = !val; else if (!strcmp(opt, "soft")) soft = val; else if (!strcmp(opt, "hard")) soft = !val; else if (!strcmp(opt, "intr")) intr = val; else if (!strcmp(opt, "posix")) posix = val; else if (!strcmp(opt, "cto")) nocto = !val; else if (!strcmp(opt, "ac")) noac = !val; else if (!strcmp(opt, "tcp")) tcp = val; else if (!strcmp(opt, "udp")) tcp = !val; else if (!strcmp(opt, "lock")) { if (nfs_mount_version >= 3) nolock = !val; else printf(_("Warning: option nolock is not supported.\n")); } else { if (!sloppy) { printf(_("unknown nfs mount option: " "%s%s\n"), val ? "" : "no", opt); goto fail; } } } } data.flags = (soft ? NFS_MOUNT_SOFT : 0) | (intr ? NFS_MOUNT_INTR : 0) | (posix ? NFS_MOUNT_POSIX : 0) | (nocto ? NFS_MOUNT_NOCTO : 0) | (noac ? NFS_MOUNT_NOAC : 0); #if NFS_MOUNT_VERSION >= 2 if (nfs_mount_version >= 2) data.flags |= (tcp ? NFS_MOUNT_TCP : 0); #endif #if NFS_MOUNT_VERSION >= 3 if (nfs_mount_version >= 3) data.flags |= (nolock ? NFS_MOUNT_NONLM : 0); #endif /* Adjust options if none specified */ if (!data.timeo) data.timeo = tcp ? 70 : 7; #ifdef NFS_MOUNT_DEBUG printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", data.rsize, data.wsize, data.timeo, data.retrans); printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); printf("port = %d, bg = %d, retry = %d, flags = %.8x\n", port, bg, retry, data.flags); printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n", mountprog, mountvers, nfsprog, nfsvers); printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n", (data.flags & NFS_MOUNT_SOFT) != 0, (data.flags & NFS_MOUNT_INTR) != 0, (data.flags & NFS_MOUNT_POSIX) != 0, (data.flags & NFS_MOUNT_NOCTO) != 0, (data.flags & NFS_MOUNT_NOAC) != 0); #if NFS_MOUNT_VERSION >= 2 printf("tcp = %d\n", (data.flags & NFS_MOUNT_TCP) != 0); #endif #endif data.version = nfs_mount_version; *mount_opts = (char *) &data; if (*flags & MS_REMOUNT) return 0; /* * If the previous mount operation on the same host was * backgrounded, and the "bg" for this mount is also set, * give up immediately, to avoid the initial timeout. */ if (bg && !running_bg && prev_bg_host && strcmp(hostname, prev_bg_host) == 0) { if (retry > 0) retval = EX_BG; return retval; } /* create mount deamon client */ /* See if the nfs host = mount host. */ if (mounthost) { if (mounthost[0] >= '0' && mounthost[0] <= '9') { mount_server_addr.sin_family = AF_INET; mount_server_addr.sin_addr.s_addr = inet_addr(hostname); } else { if ((hp = gethostbyname(mounthost)) == NULL) { fprintf(stderr, _("mount: can't get address for %s\n"), hostname); goto fail; } else { if (hp->h_length > sizeof(struct in_addr)) { fprintf(stderr, _("mount: got bad hp->h_length?\n")); hp->h_length = sizeof(struct in_addr); } mount_server_addr.sin_family = AF_INET; memcpy(&mount_server_addr.sin_addr, hp->h_addr, hp->h_length); } } } /* * The following loop implements the mount retries. On the first * call, "running_bg" is 0. When the mount times out, and the * "bg" option is set, the exit status EX_BG will be returned. * For a backgrounded mount, there will be a second call by the * child process with "running_bg" set to 1. * * The case where the mount point is not present and the "bg" * option is set, is treated as a timeout. This is done to * support nested mounts. * * The "retry" count specified by the user is the number of * minutes to retry before giving up. * * Only the first error message will be displayed. */ retry_timeout.tv_sec = 3; retry_timeout.tv_usec = 0; total_timeout.tv_sec = 20; total_timeout.tv_usec = 0; timeout = time(NULL) + 60 * retry; prevt = 0; t = 30; val = 1; for (;;) { if (bg && stat(node, &statbuf) == -1) { if (running_bg) { sleep(val); /* 1, 2, 4, 8, 16, 30, ... */ val *= 2; if (val > 30) val = 30; } } else { /* be careful not to use too many CPU cycles */ if (t - prevt < 30) sleep(30); /* contact the mount daemon via TCP */ mount_server_addr.sin_port = htons(mountport); msock = RPC_ANYSOCK; mclient = clnttcp_create(&mount_server_addr, mountprog, mountvers, &msock, 0, 0); /* if this fails, contact the mount daemon via UDP */ if (!mclient) { mount_server_addr.sin_port = htons(mountport); msock = RPC_ANYSOCK; mclient = clntudp_create(&mount_server_addr, mountprog, mountvers, retry_timeout, &msock); } if (mclient) { /* try to mount hostname:dirname */ mclient->cl_auth = authunix_create_default(); clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, (caddr_t) &dirname, (xdrproc_t) xdr_fhstatus, (caddr_t) &status, total_timeout); if (clnt_stat == RPC_SUCCESS) break; /* we're done */ if (errno != ECONNREFUSED) { clnt_perror(mclient, "mount"); goto fail; /* don't retry */ } if (!running_bg && prevt == 0) clnt_perror(mclient, "mount"); auth_destroy(mclient->cl_auth); clnt_destroy(mclient); mclient = 0; close(msock); } else { if (!running_bg && prevt == 0) clnt_pcreateerror("mount"); } prevt = t; } if (!bg) goto fail; if (!running_bg) { prev_bg_host = xstrdup(hostname); if (retry > 0) retval = EX_BG; goto fail; } t = time(NULL); if (t >= timeout) goto fail; } if (status.fhs_status != 0) { fprintf(stderr, _("mount: %s:%s failed, reason given by server: %s\n"), hostname, dirname, nfs_strerror(status.fhs_status)); goto fail; } memcpy((char *) &root_fhandle, (char *) status.fhstatus_u.fhs_fhandle, sizeof (root_fhandle)); /* create nfs socket for kernel */ if (tcp) { if (nfs_mount_version < 3) { printf(_("NFS over TCP is not supported.\n")); goto fail; } fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); } else fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fsock < 0) { perror(_("nfs socket")); goto fail; } if (bindresvport(fsock, 0) < 0) { perror(_("nfs bindresvport")); goto fail; } if (port == 0) { server_addr.sin_port = PMAPPORT; port = pmap_getport(&server_addr, nfsprog, nfsvers, tcp ? IPPROTO_TCP : IPPROTO_UDP); if (port == 0) port = NFS_PORT; #ifdef NFS_MOUNT_DEBUG else printf(_("used portmapper to find NFS port\n")); #endif } #ifdef NFS_MOUNT_DEBUG printf(_("using port %d for nfs deamon\n"), port); #endif server_addr.sin_port = htons(port); /* * connect() the socket for kernels 1.3.10 and below only, * to avoid problems with multihomed hosts. * --Swen */ if (linux_version_code() <= 66314 && connect(fsock, (struct sockaddr *) &server_addr, sizeof (server_addr)) < 0) { perror(_("nfs connect")); goto fail; } /* prepare data structure for kernel */ data.fd = fsock; memcpy((char *) &data.root, (char *) &root_fhandle, sizeof (root_fhandle)); memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr)); strncpy(data.hostname, hostname, sizeof(data.hostname)); /* clean up */ auth_destroy(mclient->cl_auth); clnt_destroy(mclient); close(msock); return 0; /* abort */ fail: if (msock != -1) { if (mclient) { auth_destroy(mclient->cl_auth); clnt_destroy(mclient); } close(msock); } if (fsock != -1) close(fsock); return retval; } /* * We need to translate between nfs status return values and * the local errno values which may not be the same. * * Andreas Schwab : change errno: * "after #include the symbol errno is reserved for any use, * it cannot even be used as a struct tag or field name". */ #ifndef EDQUOT #define EDQUOT ENOSPC #endif static struct { enum nfs_stat stat; int errnum; } nfs_errtbl[] = { { NFS_OK, 0 }, { NFSERR_PERM, EPERM }, { NFSERR_NOENT, ENOENT }, { NFSERR_IO, EIO }, { NFSERR_NXIO, ENXIO }, { NFSERR_ACCES, EACCES }, { NFSERR_EXIST, EEXIST }, { NFSERR_NODEV, ENODEV }, { NFSERR_NOTDIR, ENOTDIR }, { NFSERR_ISDIR, EISDIR }, #ifdef NFSERR_INVAL { NFSERR_INVAL, EINVAL }, /* that Sun forgot */ #endif { NFSERR_FBIG, EFBIG }, { NFSERR_NOSPC, ENOSPC }, { NFSERR_ROFS, EROFS }, { NFSERR_NAMETOOLONG, ENAMETOOLONG }, { NFSERR_NOTEMPTY, ENOTEMPTY }, { NFSERR_DQUOT, EDQUOT }, { NFSERR_STALE, ESTALE }, #ifdef EWFLUSH { NFSERR_WFLUSH, EWFLUSH }, #endif /* Throw in some NFSv3 values for even more fun (HP returns these) */ { 71, EREMOTE }, { -1, EIO } }; static char *nfs_strerror(int stat) { int i; static char buf[256]; for (i = 0; nfs_errtbl[i].stat != -1; i++) { if (nfs_errtbl[i].stat == stat) return strerror(nfs_errtbl[i].errnum); } sprintf(buf, _("unknown nfs status return value: %d"), stat); return buf; } #if 0 int my_getport(struct in_addr server, struct timeval *timeo, ...) { struct sockaddr_in sin; struct pmap pmap; CLIENT *clnt; int sock = RPC_ANYSOCK, port; pmap.pm_prog = prog; pmap.pm_vers = vers; pmap.pm_prot = prot; pmap.pm_port = 0; sin.sin_family = AF_INET; sin.sin_addr = server; sin.sin_port = htons(111); clnt = clntudp_create(&sin, 100000, 2, *timeo, &sock); status = clnt_call(clnt, PMAP_GETPORT, &pmap, (xdrproc_t) xdr_pmap, &port, (xdrproc_t) xdr_uint); if (status != SUCCESS) { /* natter */ port = 0; } clnt_destroy(clnt); close(sock); return port; } #endif /* * Please do not edit this file. * It was generated using rpcgen. */ #include #include /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user or with the express written consent of * Sun Microsystems, Inc. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* * Copyright (c) 1985, 1990 by Sun Microsystems, Inc. */ /* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */ bool_t xdr_fhandle(XDR *xdrs, fhandle objp) { if (!xdr_opaque(xdrs, objp, FHSIZE)) { return (FALSE); } return (TRUE); } bool_t xdr_fhstatus(XDR *xdrs, fhstatus *objp) { if (!xdr_u_int(xdrs, &objp->fhs_status)) { return (FALSE); } switch (objp->fhs_status) { case 0: if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) { return (FALSE); } break; default: break; } return (TRUE); } bool_t xdr_dirpath(XDR *xdrs, dirpath *objp) { if (!xdr_string(xdrs, objp, MNTPATHLEN)) { return (FALSE); } return (TRUE); } bool_t xdr_name(XDR *xdrs, name *objp) { if (!xdr_string(xdrs, objp, MNTNAMLEN)) { return (FALSE); } return (TRUE); } bool_t xdr_mountlist(XDR *xdrs, mountlist *objp) { if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct mountbody), (xdrproc_t)xdr_mountbody)) { return (FALSE); } return (TRUE); } bool_t xdr_mountbody(XDR *xdrs, mountbody *objp) { if (!xdr_name(xdrs, &objp->ml_hostname)) { return (FALSE); } if (!xdr_dirpath(xdrs, &objp->ml_directory)) { return (FALSE); } if (!xdr_mountlist(xdrs, &objp->ml_next)) { return (FALSE); } return (TRUE); } bool_t xdr_groups(XDR *xdrs, groups *objp) { if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct groupnode), (xdrproc_t)xdr_groupnode)) { return (FALSE); } return (TRUE); } bool_t xdr_groupnode(XDR *xdrs, groupnode *objp) { if (!xdr_name(xdrs, &objp->gr_name)) { return (FALSE); } if (!xdr_groups(xdrs, &objp->gr_next)) { return (FALSE); } return (TRUE); } bool_t xdr_exports(XDR *xdrs, exports *objp) { if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct exportnode), (xdrproc_t)xdr_exportnode)) { return (FALSE); } return (TRUE); } bool_t xdr_exportnode(XDR *xdrs, exportnode *objp) { if (!xdr_dirpath(xdrs, &objp->ex_dir)) { return (FALSE); } if (!xdr_groups(xdrs, &objp->ex_groups)) { return (FALSE); } if (!xdr_exports(xdrs, &objp->ex_next)) { return (FALSE); } return (TRUE); } bool_t xdr_ppathcnf(XDR *xdrs, ppathcnf *objp) { register long *buf; int i; if (xdrs->x_op == XDR_ENCODE) { buf = (long*)XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT); if (buf == NULL) { if (!xdr_int(xdrs, &objp->pc_link_max)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_max_canon)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_max_input)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_name_max)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_path_max)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_pipe_buf)) { return (FALSE); } } else { IXDR_PUT_LONG(buf,objp->pc_link_max); IXDR_PUT_SHORT(buf,objp->pc_max_canon); IXDR_PUT_SHORT(buf,objp->pc_max_input); IXDR_PUT_SHORT(buf,objp->pc_name_max); IXDR_PUT_SHORT(buf,objp->pc_path_max); IXDR_PUT_SHORT(buf,objp->pc_pipe_buf); } if (!xdr_u_char(xdrs, &objp->pc_vdisable)) { return (FALSE); } if (!xdr_char(xdrs, &objp->pc_xxx)) { return (FALSE); } buf = (long*)XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); if (buf == NULL) { if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) { return (FALSE); } } else { { register short *genp; for ( i = 0,genp=objp->pc_mask; i < 2; i++){ IXDR_PUT_SHORT(buf,*genp++); } }; } return (TRUE); } else if (xdrs->x_op == XDR_DECODE) { buf = (long*)XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT); if (buf == NULL) { if (!xdr_int(xdrs, &objp->pc_link_max)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_max_canon)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_max_input)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_name_max)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_path_max)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_pipe_buf)) { return (FALSE); } } else { objp->pc_link_max = IXDR_GET_LONG(buf); objp->pc_max_canon = IXDR_GET_SHORT(buf); objp->pc_max_input = IXDR_GET_SHORT(buf); objp->pc_name_max = IXDR_GET_SHORT(buf); objp->pc_path_max = IXDR_GET_SHORT(buf); objp->pc_pipe_buf = IXDR_GET_SHORT(buf); } if (!xdr_u_char(xdrs, &objp->pc_vdisable)) { return (FALSE); } if (!xdr_char(xdrs, &objp->pc_xxx)) { return (FALSE); } buf = (long*)XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); if (buf == NULL) { if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) { return (FALSE); } } else { { register short *genp; for ( i = 0,genp=objp->pc_mask; i < 2; i++){ *genp++ = IXDR_GET_SHORT(buf); } }; } return(TRUE); } if (!xdr_int(xdrs, &objp->pc_link_max)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_max_canon)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_max_input)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_name_max)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_path_max)) { return (FALSE); } if (!xdr_short(xdrs, &objp->pc_pipe_buf)) { return (FALSE); } if (!xdr_u_char(xdrs, &objp->pc_vdisable)) { return (FALSE); } if (!xdr_char(xdrs, &objp->pc_xxx)) { return (FALSE); } if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) { return (FALSE); } return (TRUE); } /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user or with the express written consent of * Sun Microsystems, Inc. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* * Copyright (c) 1985, 1990 by Sun Microsystems, Inc. */ /* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */ #include /* for memset() */ /* Default timeout can be changed using clnt_control() */ static struct timeval TIMEOUT = { 25, 0 }; void * mountproc_null_1(argp, clnt) void *argp; CLIENT *clnt; { static char clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return ((void *)&clnt_res); } fhstatus * mountproc_mnt_1(argp, clnt) dirpath *argp; CLIENT *clnt; { static fhstatus clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, (caddr_t) argp, (xdrproc_t) xdr_fhstatus, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); } mountlist * mountproc_dump_1(argp, clnt) void *argp; CLIENT *clnt; { static mountlist clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, (caddr_t) argp, (xdrproc_t) xdr_mountlist, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); } void * mountproc_umnt_1(argp, clnt) dirpath *argp; CLIENT *clnt; { static char clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, (caddr_t) argp, (xdrproc_t) xdr_void, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return ((void *)&clnt_res); } void * mountproc_umntall_1(argp, clnt) void *argp; CLIENT *clnt; { static char clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, (caddr_t) argp, (xdrproc_t) xdr_void, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return ((void *)&clnt_res); } exports * mountproc_export_1(argp, clnt) void *argp; CLIENT *clnt; { static exports clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, (caddr_t) argp, (xdrproc_t) xdr_exports, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); } exports * mountproc_exportall_1(argp, clnt) void *argp; CLIENT *clnt; { static exports clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, (caddr_t) argp, (xdrproc_t) xdr_exports, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); } void * mountproc_null_2(argp, clnt) void *argp; CLIENT *clnt; { static char clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return ((void *)&clnt_res); } fhstatus * mountproc_mnt_2(argp, clnt) dirpath *argp; CLIENT *clnt; { static fhstatus clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, (caddr_t) argp, (xdrproc_t) xdr_fhstatus, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); } mountlist * mountproc_dump_2(argp, clnt) void *argp; CLIENT *clnt; { static mountlist clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_mountlist, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); } void * mountproc_umnt_2(argp, clnt) dirpath *argp; CLIENT *clnt; { static char clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, (caddr_t) argp, (xdrproc_t) xdr_void, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return ((void *)&clnt_res); } void * mountproc_umntall_2(argp, clnt) void *argp; CLIENT *clnt; { static char clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, (caddr_t) argp, (xdrproc_t) xdr_void, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return ((void *)&clnt_res); } exports * mountproc_export_2(argp, clnt) void *argp; CLIENT *clnt; { static exports clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); } exports * mountproc_exportall_2(argp, clnt) void *argp; CLIENT *clnt; { static exports clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); } ppathcnf * mountproc_pathconf_2(argp, clnt) dirpath *argp; CLIENT *clnt; { static ppathcnf clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call(clnt, MOUNTPROC_PATHCONF, (xdrproc_t) xdr_dirpath, (caddr_t) argp, (xdrproc_t) xdr_ppathcnf, (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); }