diff options
author | Erik Troan <ewt@redhat.com> | 1999-05-03 20:03:50 +0000 |
---|---|---|
committer | Erik Troan <ewt@redhat.com> | 1999-05-03 20:03:50 +0000 |
commit | 6c0a6bd2cdf0f5efaaa54fa3ae5e8dcbfd105ba7 (patch) | |
tree | 369f903bfa378bd24a001385f10859390e4a7a01 | |
parent | 4167d42e1b65de0071675b01d2cd5f3474f7d727 (diff) | |
download | anaconda-6c0a6bd2cdf0f5efaaa54fa3ae5e8dcbfd105ba7.tar.gz anaconda-6c0a6bd2cdf0f5efaaa54fa3ae5e8dcbfd105ba7.tar.xz anaconda-6c0a6bd2cdf0f5efaaa54fa3ae5e8dcbfd105ba7.zip |
*** empty log message ***
-rw-r--r-- | isys/Makefile | 12 | ||||
-rw-r--r-- | isys/dns.c | 123 | ||||
-rw-r--r-- | isys/dns.h | 9 | ||||
-rw-r--r-- | isys/imount.c | 93 | ||||
-rw-r--r-- | isys/imount.h | 2 | ||||
-rw-r--r-- | isys/isys.c | 34 | ||||
-rw-r--r-- | isys/isys.py | 4 | ||||
-rw-r--r-- | isys/mount.h | 208 | ||||
-rw-r--r-- | isys/mount_clnt.c | 94 | ||||
-rw-r--r-- | isys/mount_constants.h | 16 | ||||
-rw-r--r-- | isys/mount_svc.c | 124 | ||||
-rw-r--r-- | isys/mount_xdr.c | 129 | ||||
-rw-r--r-- | isys/nfs_mount3.h | 57 | ||||
-rw-r--r-- | isys/nfs_mountversion.h | 1 | ||||
-rw-r--r-- | isys/nfsmount.c | 749 | ||||
-rw-r--r-- | isys/nfsmount.h | 325 | ||||
-rw-r--r-- | isys/sundries.h | 74 |
17 files changed, 2054 insertions, 0 deletions
diff --git a/isys/Makefile b/isys/Makefile new file mode 100644 index 000000000..91c419174 --- /dev/null +++ b/isys/Makefile @@ -0,0 +1,12 @@ + +CFLAGS = -I/usr/include/python1.5 +OBJECTS = isys.o nfsmount.o dns.o mount_clnt.o mount_xdr.o imount.o +LOADLIBES = -lresolv + +all: _isys.so + +_isys.so: $(OBJECTS) + gcc -shared -o $@ $(OBJECTS) $(LOADLIBES) + +clean: + rm -f *.o $(TARGET) $(OBJECTS) diff --git a/isys/dns.c b/isys/dns.c new file mode 100644 index 000000000..9ee40fa1a --- /dev/null +++ b/isys/dns.c @@ -0,0 +1,123 @@ +#include <alloca.h> +#include <sys/socket.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <resolv.h> +#include <arpa/nameser.h> +#include <stdlib.h> +#include <string.h> + +/* This is dumb, but glibc doesn't like to do hostname lookups w/o libc.so */ + +union dns_response{ + HEADER hdr; + u_char buf[PACKETSZ]; +} ; + +static int doQuery(char * query, int queryType, + char ** domainName, struct in_addr * ipNum) { + int len, ancount, type; + u_char * data, * end; + char name[MAXDNAME]; + union dns_response response; + +#ifdef __sparc__ + /* from jj: */ + /* We have to wait till ethernet negotiation is done */ + _res.retry = 3; +#else + _res.retry = 2; +#endif + + + len = res_search(query, C_IN, queryType, (void *) &response, + sizeof(response)); + if (len <= 0) return -1; + + if (ntohs(response.hdr.rcode) != NOERROR) return -1; + ancount = ntohs(response.hdr.ancount); + if (ancount < 1) return -1; + + data = response.buf + sizeof(HEADER); + end = response.buf + len; + + /* skip the question */ + data += dn_skipname(data, end) + QFIXEDSZ; + + /* parse the answer(s) */ + while (--ancount >= 0 && data < end) { + + /* skip the domain name portion of the RR record */ + data += dn_skipname(data, end); + + /* get RR information */ + GETSHORT(type, data); + data += INT16SZ; /* skipp class */ + data += INT32SZ; /* skipp TTL */ + GETSHORT(len, data); + + if (type == T_PTR) { + /* we got a pointer */ + len = dn_expand(response.buf, end, data, name, sizeof(name)); + if (len <= 0) return -1; + if (queryType == T_PTR && domainName) { + /* we wanted a pointer */ + *domainName = malloc(strlen(name) + 1); + strcpy(*domainName, name); + return 0; + } + } else if (type == T_A) { + /* we got an address */ + if (queryType == T_A && ipNum) { + /* we wanted an address */ + memcpy(ipNum, data, sizeof(*ipNum)); + return 0; + } + } + + /* move ahead to next RR */ + data += len; + } + + return -1; +} + +char * mygethostbyaddr(char * ipnum) { + int rc; + char * result; + char * strbuf; + char * chptr; + char * splits[4]; + int i; + + _res.retry = 1; + + strbuf = alloca(strlen(ipnum) + 1); + strcpy(strbuf, ipnum); + + ipnum = alloca(strlen(strbuf) + 20); + + for (i = 0; i < 4; i++) { + chptr = strbuf; + while (*chptr && *chptr != '.') chptr++; + *chptr = '\0'; + + if (chptr - strbuf > 3) return NULL; + splits[i] = strbuf; + strbuf = chptr + 1; + } + + sprintf(ipnum, "%s.%s.%s.%s.in-addr.arpa", splits[3], splits[2], + splits[1], splits[0]); + + rc = doQuery(ipnum, T_PTR, &result, NULL); + + if (rc) + return NULL; + else + return result; +} + +int mygethostbyname(char * name, struct in_addr * addr) { + return doQuery(name, T_A, NULL, addr); +} diff --git a/isys/dns.h b/isys/dns.h new file mode 100644 index 000000000..45bcb38bf --- /dev/null +++ b/isys/dns.h @@ -0,0 +1,9 @@ +#ifndef H_DNS +#define H_DNS + +#include <netinet/in.h> + +int mygethostbyname(char * name, struct in_addr * addr); +char * mygethostbyaddr(char * ipnum); + +#endif diff --git a/isys/imount.c b/isys/imount.c new file mode 100644 index 000000000..cbb3932e4 --- /dev/null +++ b/isys/imount.c @@ -0,0 +1,93 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/errno.h> +#include <sys/mount.h> + +#include "imount.h" + +#define _(foo) foo + +int doPwMount(char * dev, char * where, char * fs, int rdonly, int istty, + char * acct, char * pw) { + char * buf = NULL; + int isnfs = 0; + char * mount_opt = NULL; + long int flag; + char * chptr; + + if (!strcmp(fs, "nfs")) isnfs = 1; + + /*logMessage("mounting %s on %s as type %s", dev, where, fs);*/ + + if (!strcmp(fs, "smb")) { +#if 0 /* disabled for now */ + /*mkdirChain(where);*/ + + if (!acct) acct = "guest"; + if (!pw) pw = ""; + + buf = alloca(strlen(dev) + 1); + strcpy(buf, dev); + chptr = buf; + while (*chptr && *chptr != ':') chptr++; + if (!*chptr) { + /*logMessage("bad smb mount point %s", where);*/ + return 0; + } + + *chptr = '\0'; + chptr++; + +#ifdef __i386__ + /*logMessage("mounting smb filesystem from %s path %s on %s", + buf, chptr, where);*/ + return smbmount(buf, chptr, acct, pw, "localhost", where); +#else + errorWindow("smbfs only works on Intel machines"); +#endif +#endif /* disabled */ + } else { + /*mkdirChain(where);*/ + + if (!isnfs && *dev == '/') { + buf = dev; + } else if (!isnfs) { + buf = alloca(200); + strcpy(buf, "/tmp/"); + strcat(buf, dev); + } else { +#ifndef DISABLE_NETWORK + char * extra_opts = NULL; + int flags = 0; + + buf = dev; + /*logMessage("calling nfsmount(%s, %s, &flags, &extra_opts, &mount_opt)", + buf, where);*/ + + if (nfsmount(buf, where, &flags, &extra_opts, &mount_opt)) { + /*logMessage("\tnfsmount returned non-zero");*/ + fprintf(stderr, "nfs mount failed: %s\n", + nfs_error()); + return 1; + } +#endif + } + flag = MS_MGC_VAL; + if (rdonly) + flag |= MS_RDONLY; + + if (!strncmp(fs, "vfat", 4)) + mount_opt="check=relaxed"; + + /*logMessage("calling mount(%s, %s, %s, %ld, %p)", buf, where, fs, + flag, mount_opt);*/ + + if (mount(buf, where, fs, flag, mount_opt)) { + fprintf(stderr, "mount failed: %s\n", strerror(errno)); + return 1; + } + } + + return 0; +} + diff --git a/isys/imount.h b/isys/imount.h new file mode 100644 index 000000000..409fd2302 --- /dev/null +++ b/isys/imount.h @@ -0,0 +1,2 @@ +int doPwMount(char * dev, char * where, char * fs, int rdonly, int istty, + char * acct, char * pw); diff --git a/isys/isys.c b/isys/isys.c new file mode 100644 index 000000000..402d1e16a --- /dev/null +++ b/isys/isys.c @@ -0,0 +1,34 @@ +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <unistd.h> + +#include "Python.h" + +#include "imount.h" + +static PyObject * doMount(PyObject * s, PyObject * args); + +static PyMethodDef balkanModuleMethods[] = { + { "mount", (PyCFunction) doMount, METH_VARARGS, NULL }, + { NULL } +} ; + +static PyObject * doMount(PyObject * s, PyObject * args) { + char * fs, * device, * mntpoint; + + if (!PyArg_ParseTuple(args, "sss", &fs, &device, &mntpoint)) return NULL; + + doPwMount(device, mntpoint, fs, 0, 0, NULL, NULL); + + Py_INCREF(Py_None); + return Py_None; +} + +void init_isys(void) { + Py_InitModule("_isys", balkanModuleMethods); +} + +static void emptyDestructor(PyObject * s) { +} diff --git a/isys/isys.py b/isys/isys.py new file mode 100644 index 000000000..7e9e4860d --- /dev/null +++ b/isys/isys.py @@ -0,0 +1,4 @@ +import _isys + +def mount(device, location, fstype = "ext2"): + return _isys.mount(fstype, device, location) diff --git a/isys/mount.h b/isys/mount.h new file mode 100644 index 000000000..d70ccaf9d --- /dev/null +++ b/isys/mount.h @@ -0,0 +1,208 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _MOUNT_H_RPCGEN +#define _MOUNT_H_RPCGEN + +#include <rpc/rpc.h> + +#define MNTPATHLEN 1024 +#define MNTNAMLEN 255 +#define FHSIZE 32 + +typedef char fhandle[FHSIZE]; +#ifdef __cplusplus +extern "C" bool_t xdr_fhandle(XDR *, fhandle); +#elif __STDC__ +extern bool_t xdr_fhandle(XDR *, fhandle); +#else /* Old Style C */ +bool_t xdr_fhandle(); +#endif /* Old Style C */ + + +struct fhstatus { + u_int fhs_status; + union { + fhandle fhs_fhandle; + } fhstatus_u; +}; +typedef struct fhstatus fhstatus; +#ifdef __cplusplus +extern "C" bool_t xdr_fhstatus(XDR *, fhstatus*); +#elif __STDC__ +extern bool_t xdr_fhstatus(XDR *, fhstatus*); +#else /* Old Style C */ +bool_t xdr_fhstatus(); +#endif /* Old Style C */ + + +typedef char *dirpath; +#ifdef __cplusplus +extern "C" bool_t xdr_dirpath(XDR *, dirpath*); +#elif __STDC__ +extern bool_t xdr_dirpath(XDR *, dirpath*); +#else /* Old Style C */ +bool_t xdr_dirpath(); +#endif /* Old Style C */ + + +typedef char *name; +#ifdef __cplusplus +extern "C" bool_t xdr_name(XDR *, name*); +#elif __STDC__ +extern bool_t xdr_name(XDR *, name*); +#else /* Old Style C */ +bool_t xdr_name(); +#endif /* Old Style C */ + + +typedef struct mountbody *mountlist; +#ifdef __cplusplus +extern "C" bool_t xdr_mountlist(XDR *, mountlist*); +#elif __STDC__ +extern bool_t xdr_mountlist(XDR *, mountlist*); +#else /* Old Style C */ +bool_t xdr_mountlist(); +#endif /* Old Style C */ + + +struct mountbody { + name ml_hostname; + dirpath ml_directory; + mountlist ml_next; +}; +typedef struct mountbody mountbody; +#ifdef __cplusplus +extern "C" bool_t xdr_mountbody(XDR *, mountbody*); +#elif __STDC__ +extern bool_t xdr_mountbody(XDR *, mountbody*); +#else /* Old Style C */ +bool_t xdr_mountbody(); +#endif /* Old Style C */ + + +typedef struct groupnode *groups; +#ifdef __cplusplus +extern "C" bool_t xdr_groups(XDR *, groups*); +#elif __STDC__ +extern bool_t xdr_groups(XDR *, groups*); +#else /* Old Style C */ +bool_t xdr_groups(); +#endif /* Old Style C */ + + +struct groupnode { + name gr_name; + groups gr_next; +}; +typedef struct groupnode groupnode; +#ifdef __cplusplus +extern "C" bool_t xdr_groupnode(XDR *, groupnode*); +#elif __STDC__ +extern bool_t xdr_groupnode(XDR *, groupnode*); +#else /* Old Style C */ +bool_t xdr_groupnode(); +#endif /* Old Style C */ + + +typedef struct exportnode *exports; +#ifdef __cplusplus +extern "C" bool_t xdr_exports(XDR *, exports*); +#elif __STDC__ +extern bool_t xdr_exports(XDR *, exports*); +#else /* Old Style C */ +bool_t xdr_exports(); +#endif /* Old Style C */ + + +struct exportnode { + dirpath ex_dir; + groups ex_groups; + exports ex_next; +}; +typedef struct exportnode exportnode; +#ifdef __cplusplus +extern "C" bool_t xdr_exportnode(XDR *, exportnode*); +#elif __STDC__ +extern bool_t xdr_exportnode(XDR *, exportnode*); +#else /* Old Style C */ +bool_t xdr_exportnode(); +#endif /* Old Style C */ + + +#define MOUNTPROG ((u_long)100005) +#define MOUNTVERS ((u_long)1) + +#ifdef __cplusplus +#define MOUNTPROC_NULL ((u_long)0) +extern "C" void * mountproc_null_1(void *, CLIENT *); +extern "C" void * mountproc_null_1_svc(void *, struct svc_req *); +#define MOUNTPROC_MNT ((u_long)1) +extern "C" fhstatus * mountproc_mnt_1(dirpath *, CLIENT *); +extern "C" fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_DUMP ((u_long)2) +extern "C" mountlist * mountproc_dump_1(void *, CLIENT *); +extern "C" mountlist * mountproc_dump_1_svc(void *, struct svc_req *); +#define MOUNTPROC_UMNT ((u_long)3) +extern "C" void * mountproc_umnt_1(dirpath *, CLIENT *); +extern "C" void * mountproc_umnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern "C" void * mountproc_umntall_1(void *, CLIENT *); +extern "C" void * mountproc_umntall_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORT ((u_long)5) +extern "C" exports * mountproc_export_1(void *, CLIENT *); +extern "C" exports * mountproc_export_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern "C" exports * mountproc_exportall_1(void *, CLIENT *); +extern "C" exports * mountproc_exportall_1_svc(void *, struct svc_req *); + +#elif __STDC__ +#define MOUNTPROC_NULL ((u_long)0) +extern void * mountproc_null_1(void *, CLIENT *); +extern void * mountproc_null_1_svc(void *, struct svc_req *); +#define MOUNTPROC_MNT ((u_long)1) +extern fhstatus * mountproc_mnt_1(dirpath *, CLIENT *); +extern fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_DUMP ((u_long)2) +extern mountlist * mountproc_dump_1(void *, CLIENT *); +extern mountlist * mountproc_dump_1_svc(void *, struct svc_req *); +#define MOUNTPROC_UMNT ((u_long)3) +extern void * mountproc_umnt_1(dirpath *, CLIENT *); +extern void * mountproc_umnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern void * mountproc_umntall_1(void *, CLIENT *); +extern void * mountproc_umntall_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORT ((u_long)5) +extern exports * mountproc_export_1(void *, CLIENT *); +extern exports * mountproc_export_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern exports * mountproc_exportall_1(void *, CLIENT *); +extern exports * mountproc_exportall_1_svc(void *, struct svc_req *); + +#else /* Old Style C */ +#define MOUNTPROC_NULL ((u_long)0) +extern void * mountproc_null_1(); +extern void * mountproc_null_1_svc(); +#define MOUNTPROC_MNT ((u_long)1) +extern fhstatus * mountproc_mnt_1(); +extern fhstatus * mountproc_mnt_1_svc(); +#define MOUNTPROC_DUMP ((u_long)2) +extern mountlist * mountproc_dump_1(); +extern mountlist * mountproc_dump_1_svc(); +#define MOUNTPROC_UMNT ((u_long)3) +extern void * mountproc_umnt_1(); +extern void * mountproc_umnt_1_svc(); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern void * mountproc_umntall_1(); +extern void * mountproc_umntall_1_svc(); +#define MOUNTPROC_EXPORT ((u_long)5) +extern exports * mountproc_export_1(); +extern exports * mountproc_export_1_svc(); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern exports * mountproc_exportall_1(); +extern exports * mountproc_exportall_1_svc(); +#endif /* Old Style C */ + +#endif /* !_MOUNT_H_RPCGEN */ diff --git a/isys/mount_clnt.c b/isys/mount_clnt.c new file mode 100644 index 000000000..bc6e5122b --- /dev/null +++ b/isys/mount_clnt.c @@ -0,0 +1,94 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include <memory.h> /* for memset */ +#include "mount.h" + +/* Default timeout can be changed using clnt_control() */ +static struct timeval TIMEOUT = { 25, 0 }; + +void * +mountproc_null_1(void *argp, CLIENT *clnt) +{ + static char clnt_res; + + memset((char *)&clnt_res, 0, sizeof(clnt_res)); + if (clnt_call(clnt, MOUNTPROC_NULL, xdr_void, argp, xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return ((void *)&clnt_res); +} + +fhstatus * +mountproc_mnt_1(dirpath *argp, CLIENT *clnt) +{ + static fhstatus clnt_res; + + memset((char *)&clnt_res, 0, sizeof(clnt_res)); + if (clnt_call(clnt, MOUNTPROC_MNT, xdr_dirpath, argp, xdr_fhstatus, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&clnt_res); +} + +mountlist * +mountproc_dump_1(void *argp, CLIENT *clnt) +{ + static mountlist clnt_res; + + memset((char *)&clnt_res, 0, sizeof(clnt_res)); + if (clnt_call(clnt, MOUNTPROC_DUMP, xdr_void, argp, xdr_mountlist, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&clnt_res); +} + +void * +mountproc_umnt_1(dirpath *argp, CLIENT *clnt) +{ + static char clnt_res; + + memset((char *)&clnt_res, 0, sizeof(clnt_res)); + if (clnt_call(clnt, MOUNTPROC_UMNT, xdr_dirpath, argp, xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return ((void *)&clnt_res); +} + +void * +mountproc_umntall_1(void *argp, CLIENT *clnt) +{ + static char clnt_res; + + memset((char *)&clnt_res, 0, sizeof(clnt_res)); + if (clnt_call(clnt, MOUNTPROC_UMNTALL, xdr_void, argp, xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return ((void *)&clnt_res); +} + +exports * +mountproc_export_1(void *argp, CLIENT *clnt) +{ + static exports clnt_res; + + memset((char *)&clnt_res, 0, sizeof(clnt_res)); + if (clnt_call(clnt, MOUNTPROC_EXPORT, xdr_void, argp, xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&clnt_res); +} + +exports * +mountproc_exportall_1(void *argp, CLIENT *clnt) +{ + static exports clnt_res; + + memset((char *)&clnt_res, 0, sizeof(clnt_res)); + if (clnt_call(clnt, MOUNTPROC_EXPORTALL, xdr_void, argp, xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&clnt_res); +} diff --git a/isys/mount_constants.h b/isys/mount_constants.h new file mode 100644 index 000000000..5f033452d --- /dev/null +++ b/isys/mount_constants.h @@ -0,0 +1,16 @@ +#define MS_RDONLY 1 /* Mount read-only */ +#define MS_NOSUID 2 /* Ignore suid and sgid bits */ +#define MS_NODEV 4 /* Disallow access to device special files */ +#define MS_NOEXEC 8 /* Disallow program execution */ +#define MS_SYNCHRONOUS 16 /* Writes are synced at once */ +#define MS_REMOUNT 32 /* Alter flags of a mounted FS */ +#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ +#define MS_NOATIME 1024 /* Do not update access times. */ +#define MS_NODIRATIME 2048 /* Do not update directory access times */ +/* + * Magic mount flag number. Has to be or-ed to the flag values. + */ +#ifndef MS_MGC_VAL +#define MS_MGC_VAL 0xC0ED0000 /* magic flag number to indicate "new" flags */ +#endif +#define MS_MGC_MSK 0xffff0000 /* magic flag number mask */ diff --git a/isys/mount_svc.c b/isys/mount_svc.c new file mode 100644 index 000000000..30be5ca3d --- /dev/null +++ b/isys/mount_svc.c @@ -0,0 +1,124 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "mount.h" +#include <stdio.h> +#include <stdlib.h>/* getenv, exit */ +#include <rpc/pmap_clnt.h> /* for pmap_unset */ +#include <string.h> /* strcmp */ +#include <memory.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#ifdef __STDC__ +#define SIG_PF void(*)(int) +#endif + +static void +mountprog_1(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + dirpath mountproc_mnt_1_arg; + dirpath mountproc_umnt_1_arg; + } argument; + char *result; + xdrproc_t xdr_argument, xdr_result; + char *(*local)(char *, struct svc_req *); + + switch (rqstp->rq_proc) { + case MOUNTPROC_NULL: + xdr_argument = (xdrproc_t) xdr_void; + xdr_result = (xdrproc_t) xdr_void; + local = (char *(*)(char *, struct svc_req *)) mountproc_null_1_svc; + break; + + case MOUNTPROC_MNT: + xdr_argument = (xdrproc_t) xdr_dirpath; + xdr_result = (xdrproc_t) xdr_fhstatus; + local = (char *(*)(char *, struct svc_req *)) mountproc_mnt_1_svc; + break; + + case MOUNTPROC_DUMP: + xdr_argument = (xdrproc_t) xdr_void; + xdr_result = (xdrproc_t) xdr_mountlist; + local = (char *(*)(char *, struct svc_req *)) mountproc_dump_1_svc; + break; + + case MOUNTPROC_UMNT: + xdr_argument = (xdrproc_t) xdr_dirpath; + xdr_result = (xdrproc_t) xdr_void; + local = (char *(*)(char *, struct svc_req *)) mountproc_umnt_1_svc; + break; + + case MOUNTPROC_UMNTALL: + xdr_argument = (xdrproc_t) xdr_void; + xdr_result = (xdrproc_t) xdr_void; + local = (char *(*)(char *, struct svc_req *)) mountproc_umntall_1_svc; + break; + + case MOUNTPROC_EXPORT: + xdr_argument = (xdrproc_t) xdr_void; + xdr_result = (xdrproc_t) xdr_exports; + local = (char *(*)(char *, struct svc_req *)) mountproc_export_1_svc; + break; + + case MOUNTPROC_EXPORTALL: + xdr_argument = (xdrproc_t) xdr_void; + xdr_result = (xdrproc_t) xdr_exports; + local = (char *(*)(char *, struct svc_req *)) mountproc_exportall_1_svc; + break; + + default: + svcerr_noproc(transp); + return; + } + (void) memset((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) { + svcerr_decode(transp); + return; + } + result = (*local)((char *)&argument, rqstp); + if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { + svcerr_systemerr(transp); + } + if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) { + fprintf(stderr, "unable to free arguments"); + exit(1); + } + return; +} + +int +main(int argc, char **argv) +{ + register SVCXPRT *transp; + + (void) pmap_unset(MOUNTPROG, MOUNTVERS); + + transp = svcudp_create(RPC_ANYSOCK); + if (transp == NULL) { + fprintf(stderr, "cannot create udp service."); + exit(1); + } + if (!svc_register(transp, MOUNTPROG, MOUNTVERS, mountprog_1, IPPROTO_UDP)) { + fprintf(stderr, "unable to register (MOUNTPROG, MOUNTVERS, udp)."); + exit(1); + } + + transp = svctcp_create(RPC_ANYSOCK, 0, 0); + if (transp == NULL) { + fprintf(stderr, "cannot create tcp service."); + exit(1); + } + if (!svc_register(transp, MOUNTPROG, MOUNTVERS, mountprog_1, IPPROTO_TCP)) { + fprintf(stderr, "unable to register (MOUNTPROG, MOUNTVERS, tcp)."); + exit(1); + } + + svc_run(); + fprintf(stderr, "svc_run returned"); + exit(1); + /* NOTREACHED */ +} diff --git a/isys/mount_xdr.c b/isys/mount_xdr.c new file mode 100644 index 000000000..542a7efb0 --- /dev/null +++ b/isys/mount_xdr.c @@ -0,0 +1,129 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "mount.h" + +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); +} diff --git a/isys/nfs_mount3.h b/isys/nfs_mount3.h new file mode 100644 index 000000000..e5c2b2fe4 --- /dev/null +++ b/isys/nfs_mount3.h @@ -0,0 +1,57 @@ +/* + * We want to be able to compile mount on old kernels in such a way + * that the binary will work well on more recent kernels. + * Thus, if necessary we teach nfsmount.c the structure of new fields + * that will come later. + */ +#include "nfs_mountversion.h" + +#if KERNEL_NFS_MOUNT_VERSION >= 3 + +/* + * The kernel includes are at least as good as this file. + * Use them. + */ +#include <linux/nfs_mount.h> + +#else /* KERNEL_NFS_MOUNT_VERSION < 3 */ + +/* + * We know more than the kernel. Override the kernel defines. + * Check at runtime whether the running kernel can handle the new stuff. + */ +#define NFS_MOUNT_VERSION 3 + +struct nfs_mount_data { + int version; /* 1 */ + int fd; /* 1 */ + struct nfs_fh root; /* 1 */ + int flags; /* 1 */ + int rsize; /* 1 */ + int wsize; /* 1 */ + int timeo; /* 1 */ + int retrans; /* 1 */ + int acregmin; /* 1 */ + int acregmax; /* 1 */ + int acdirmin; /* 1 */ + int acdirmax; /* 1 */ + struct sockaddr_in addr; /* 1 */ + char hostname[256]; /* 1 */ + int namlen; /* 2 */ + unsigned int bsize; /* 3 */ +}; + +/* bits in the flags field */ + +#define NFS_MOUNT_SOFT 0x0001 /* 1 */ +#define NFS_MOUNT_INTR 0x0002 /* 1 */ +#define NFS_MOUNT_SECURE 0x0004 /* 1 */ +#define NFS_MOUNT_POSIX 0x0008 /* 1 */ +#define NFS_MOUNT_NOCTO 0x0010 /* 1 */ +#define NFS_MOUNT_NOAC 0x0020 /* 1 */ +#define NFS_MOUNT_TCP 0x0040 /* 2 */ +#define NFS_MOUNT_VER3 0x0080 /* 3 */ +#define NFS_MOUNT_KERBEROS 0x0100 /* 3 */ +#define NFS_MOUNT_NONLM 0x0200 /* 3 */ + +#endif diff --git a/isys/nfs_mountversion.h b/isys/nfs_mountversion.h new file mode 100644 index 000000000..e5b90ee09 --- /dev/null +++ b/isys/nfs_mountversion.h @@ -0,0 +1 @@ +#define KERNEL_NFS_MOUNT_VERSION 3 diff --git a/isys/nfsmount.c b/isys/nfsmount.c new file mode 100644 index 000000000..e4537f779 --- /dev/null +++ b/isys/nfsmount.c @@ -0,0 +1,749 @@ +/* MODIFIED for Red Hat Linux installer + * msw@redhat.com + * o always mounts without lockd + * o uses our own host resolution + */ + +/* + * nfsmount.c -- Linux NFS mount + * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com> + * + * 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 <swen@uni-paderborn.de>: + * Omit the call to connect() for Linux version 1.3.11 or later. + * + * Wed Oct 1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com> + * Implemented the "bg", "fg" and "retry" mount options for NFS. + */ + +/* + * nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp + */ + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <netdb.h> +#include <rpc/rpc.h> +#include <rpc/pmap_prot.h> +#include <rpc/pmap_clnt.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/utsname.h> +#include <sys/stat.h> +#include <arpa/inet.h> + +#include "sundries.h" +#include "nfsmount.h" + +#include <linux/nfs.h> +#include "mount_constants.h" +#include "nfs_mount3.h" + +#include "dns.h" + +static char *nfs_strerror(int stat); + +#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) + +#define ERROR_CONNECT -50 +#define ERROR_HOSTNAME -51 + +static int myerror = 0; + +/* from sundries.c */ +/* Fatal error. Print message and exit. */ +void +die (int err, const char *fmt, ...) { + va_list args; + + va_start (args, fmt); + vfprintf (stderr, fmt, args); + fprintf (stderr, "\n"); + va_end (args); + +#if 0 + unlock_mtab (); +#endif + exit (err); +} + +char * +xstrdup (const char *s) { + char *t; + + if (s == NULL) + return NULL; + + t = strdup (s); + + if (t == NULL) + die (EX_SYSERR, "not enough memory"); + + return t; +} + +char * +xstrndup (const char *s, int n) { + char *t; + + if (s == NULL) + die (EX_SOFTWARE, "bug in xstrndup call"); + + t = malloc(n+1); + strncpy(t,s,n); + t[n] = 0; + + return t; +} + +void * +xmalloc(size_t size) +{ + void *ptr = malloc(size); + if (!ptr) + { + error("Out of memory"); + exit(1); + } + return ptr; +} + +/* end of sundries.c */ + +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 = KERNEL_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 0 + if (nfs_mount_version > NFS_MOUNT_VERSION) + nfs_mount_version = NFS_MOUNT_VERSION; +#endif +} + +int nfsmount(const char *spec, const char *node, int *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 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(); + + myerror = 0; + retval = EX_FAIL; + msock = fsock = -1; + mclient = NULL; + if (strlen(spec) >= sizeof(hostdir)) { + goto fail; + } + strcpy(hostdir, spec); + if ((s = (strchr(hostdir, ':')))) { + hostname = hostdir; + dirname = s + 1; + *s = '\0'; + } else { + goto fail; + } + + server_addr.sin_family = AF_INET; +#if 1 /* old libc's do not have inet_aton() -- change 1 to 0 */ + if (!inet_aton(hostname, &server_addr.sin_addr)) +#endif + { + if (mygethostbyname(hostname, &server_addr.sin_addr)) { + myerror = ERROR_HOSTNAME; + goto fail; + } else { + server_addr.sin_family = AF_INET; + } + } + + 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)) { + 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")) + nfsvers = val; + 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 0 + if (!sloppy) { +#endif + printf("unknown nfs mount option: " + "%s%s\n", val ? "" : "no", opt); + goto fail; +#if 0 + } +#endif + } + } + } + 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 |= NFS_MOUNT_NONLM; /* HACK HACK msw */ +#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 (mygethostbyname(hostname, &mount_server_addr.sin_addr)) { + myerror = ERROR_HOSTNAME; + goto fail; + } else { + mount_server_addr.sin_family = AF_INET; + } + } + } + + /* + * 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) { + myerror = ERROR_CONNECT; + 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) { + myerror = 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 <schwab@LS5.informatik.uni-dortmund.de>: change errno: + * "after #include <errno.h> 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 }, +}; + +char *nfs_error(void) +{ + static char * host = "Unable to resolve hostname"; + static char * connect = "Unable to connect to server"; + + if (myerror == 0) + return strerror(0); + if (myerror == ERROR_CONNECT) + return connect; + if (myerror == ERROR_HOSTNAME) + return host; + return nfs_strerror(myerror); +} + +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 diff --git a/isys/nfsmount.h b/isys/nfsmount.h new file mode 100644 index 000000000..73c71fc68 --- /dev/null +++ b/isys/nfsmount.h @@ -0,0 +1,325 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _NFSMOUNT_H_RPCGEN +#define _NFSMOUNT_H_RPCGEN + +#include <rpc/rpc.h> + +/* + * 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 */ +#ifndef _rpcsvc_mount_h +#define _rpcsvc_mount_h +#define MNTPATHLEN 1024 +#define MNTNAMLEN 255 +#define FHSIZE 32 + +typedef char fhandle[FHSIZE]; +#ifdef __cplusplus +extern "C" bool_t xdr_fhandle(XDR *, fhandle); +#elif __STDC__ +extern bool_t xdr_fhandle(XDR *, fhandle); +#else /* Old Style C */ +bool_t xdr_fhandle(); +#endif /* Old Style C */ + + +struct fhstatus { + u_int fhs_status; + union { + fhandle fhs_fhandle; + } fhstatus_u; +}; +typedef struct fhstatus fhstatus; +#ifdef __cplusplus +extern "C" bool_t xdr_fhstatus(XDR *, fhstatus*); +#elif __STDC__ +extern bool_t xdr_fhstatus(XDR *, fhstatus*); +#else /* Old Style C */ +bool_t xdr_fhstatus(); +#endif /* Old Style C */ + + +typedef char *dirpath; +#ifdef __cplusplus +extern "C" bool_t xdr_dirpath(XDR *, dirpath*); +#elif __STDC__ +extern bool_t xdr_dirpath(XDR *, dirpath*); +#else /* Old Style C */ +bool_t xdr_dirpath(); +#endif /* Old Style C */ + + +typedef char *name; +#ifdef __cplusplus +extern "C" bool_t xdr_name(XDR *, name*); +#elif __STDC__ +extern bool_t xdr_name(XDR *, name*); +#else /* Old Style C */ +bool_t xdr_name(); +#endif /* Old Style C */ + + +typedef struct mountbody *mountlist; +#ifdef __cplusplus +extern "C" bool_t xdr_mountlist(XDR *, mountlist*); +#elif __STDC__ +extern bool_t xdr_mountlist(XDR *, mountlist*); +#else /* Old Style C */ +bool_t xdr_mountlist(); +#endif /* Old Style C */ + + +struct mountbody { + name ml_hostname; + dirpath ml_directory; + mountlist ml_next; +}; +typedef struct mountbody mountbody; +#ifdef __cplusplus +extern "C" bool_t xdr_mountbody(XDR *, mountbody*); +#elif __STDC__ +extern bool_t xdr_mountbody(XDR *, mountbody*); +#else /* Old Style C */ +bool_t xdr_mountbody(); +#endif /* Old Style C */ + + +typedef struct groupnode *groups; +#ifdef __cplusplus +extern "C" bool_t xdr_groups(XDR *, groups*); +#elif __STDC__ +extern bool_t xdr_groups(XDR *, groups*); +#else /* Old Style C */ +bool_t xdr_groups(); +#endif /* Old Style C */ + + +struct groupnode { + name gr_name; + groups gr_next; +}; +typedef struct groupnode groupnode; +#ifdef __cplusplus +extern "C" bool_t xdr_groupnode(XDR *, groupnode*); +#elif __STDC__ +extern bool_t xdr_groupnode(XDR *, groupnode*); +#else /* Old Style C */ +bool_t xdr_groupnode(); +#endif /* Old Style C */ + + +typedef struct exportnode *exports; +#ifdef __cplusplus +extern "C" bool_t xdr_exports(XDR *, exports*); +#elif __STDC__ +extern bool_t xdr_exports(XDR *, exports*); +#else /* Old Style C */ +bool_t xdr_exports(); +#endif /* Old Style C */ + + +struct exportnode { + dirpath ex_dir; + groups ex_groups; + exports ex_next; +}; +typedef struct exportnode exportnode; +#ifdef __cplusplus +extern "C" bool_t xdr_exportnode(XDR *, exportnode*); +#elif __STDC__ +extern bool_t xdr_exportnode(XDR *, exportnode*); +#else /* Old Style C */ +bool_t xdr_exportnode(); +#endif /* Old Style C */ + + +struct ppathcnf { + int pc_link_max; + short pc_max_canon; + short pc_max_input; + short pc_name_max; + short pc_path_max; + short pc_pipe_buf; + u_char pc_vdisable; + char pc_xxx; + short pc_mask[2]; +}; +typedef struct ppathcnf ppathcnf; +#ifdef __cplusplus +extern "C" bool_t xdr_ppathcnf(XDR *, ppathcnf*); +#elif __STDC__ +extern bool_t xdr_ppathcnf(XDR *, ppathcnf*); +#else /* Old Style C */ +bool_t xdr_ppathcnf(); +#endif /* Old Style C */ + +#endif /*!_rpcsvc_mount_h*/ + +#define MOUNTPROG ((u_long)100005) +#define MOUNTVERS ((u_long)1) + +#ifdef __cplusplus +#define MOUNTPROC_NULL ((u_long)0) +extern "C" void * mountproc_null_1(void *, CLIENT *); +extern "C" void * mountproc_null_1_svc(void *, struct svc_req *); +#define MOUNTPROC_MNT ((u_long)1) +extern "C" fhstatus * mountproc_mnt_1(dirpath *, CLIENT *); +extern "C" fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_DUMP ((u_long)2) +extern "C" mountlist * mountproc_dump_1(void *, CLIENT *); +extern "C" mountlist * mountproc_dump_1_svc(void *, struct svc_req *); +#define MOUNTPROC_UMNT ((u_long)3) +extern "C" void * mountproc_umnt_1(dirpath *, CLIENT *); +extern "C" void * mountproc_umnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern "C" void * mountproc_umntall_1(void *, CLIENT *); +extern "C" void * mountproc_umntall_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORT ((u_long)5) +extern "C" exports * mountproc_export_1(void *, CLIENT *); +extern "C" exports * mountproc_export_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern "C" exports * mountproc_exportall_1(void *, CLIENT *); +extern "C" exports * mountproc_exportall_1_svc(void *, struct svc_req *); + +#elif __STDC__ +#define MOUNTPROC_NULL ((u_long)0) +extern void * mountproc_null_1(void *, CLIENT *); +extern void * mountproc_null_1_svc(void *, struct svc_req *); +#define MOUNTPROC_MNT ((u_long)1) +extern fhstatus * mountproc_mnt_1(dirpath *, CLIENT *); +extern fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_DUMP ((u_long)2) +extern mountlist * mountproc_dump_1(void *, CLIENT *); +extern mountlist * mountproc_dump_1_svc(void *, struct svc_req *); +#define MOUNTPROC_UMNT ((u_long)3) +extern void * mountproc_umnt_1(dirpath *, CLIENT *); +extern void * mountproc_umnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern void * mountproc_umntall_1(void *, CLIENT *); +extern void * mountproc_umntall_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORT ((u_long)5) +extern exports * mountproc_export_1(void *, CLIENT *); +extern exports * mountproc_export_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern exports * mountproc_exportall_1(void *, CLIENT *); +extern exports * mountproc_exportall_1_svc(void *, struct svc_req *); + +#else /* Old Style C */ +#define MOUNTPROC_NULL ((u_long)0) +extern void * mountproc_null_1(); +extern void * mountproc_null_1_svc(); +#define MOUNTPROC_MNT ((u_long)1) +extern fhstatus * mountproc_mnt_1(); +extern fhstatus * mountproc_mnt_1_svc(); +#define MOUNTPROC_DUMP ((u_long)2) +extern mountlist * mountproc_dump_1(); +extern mountlist * mountproc_dump_1_svc(); +#define MOUNTPROC_UMNT ((u_long)3) +extern void * mountproc_umnt_1(); +extern void * mountproc_umnt_1_svc(); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern void * mountproc_umntall_1(); +extern void * mountproc_umntall_1_svc(); +#define MOUNTPROC_EXPORT ((u_long)5) +extern exports * mountproc_export_1(); +extern exports * mountproc_export_1_svc(); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern exports * mountproc_exportall_1(); +extern exports * mountproc_exportall_1_svc(); +#endif /* Old Style C */ +#define MOUNTVERS_POSIX ((u_long)2) + +#ifdef __cplusplus +extern "C" void * mountproc_null_2(void *, CLIENT *); +extern "C" void * mountproc_null_2_svc(void *, struct svc_req *); +extern "C" fhstatus * mountproc_mnt_2(dirpath *, CLIENT *); +extern "C" fhstatus * mountproc_mnt_2_svc(dirpath *, struct svc_req *); +extern "C" mountlist * mountproc_dump_2(void *, CLIENT *); +extern "C" mountlist * mountproc_dump_2_svc(void *, struct svc_req *); +extern "C" void * mountproc_umnt_2(dirpath *, CLIENT *); +extern "C" void * mountproc_umnt_2_svc(dirpath *, struct svc_req *); +extern "C" void * mountproc_umntall_2(void *, CLIENT *); +extern "C" void * mountproc_umntall_2_svc(void *, struct svc_req *); +extern "C" exports * mountproc_export_2(void *, CLIENT *); +extern "C" exports * mountproc_export_2_svc(void *, struct svc_req *); +extern "C" exports * mountproc_exportall_2(void *, CLIENT *); +extern "C" exports * mountproc_exportall_2_svc(void *, struct svc_req *); +#define MOUNTPROC_PATHCONF ((u_long)7) +extern "C" ppathcnf * mountproc_pathconf_2(dirpath *, CLIENT *); +extern "C" ppathcnf * mountproc_pathconf_2_svc(dirpath *, struct svc_req *); + +#elif __STDC__ +extern void * mountproc_null_2(void *, CLIENT *); +extern void * mountproc_null_2_svc(void *, struct svc_req *); +extern fhstatus * mountproc_mnt_2(dirpath *, CLIENT *); +extern fhstatus * mountproc_mnt_2_svc(dirpath *, struct svc_req *); +extern mountlist * mountproc_dump_2(void *, CLIENT *); +extern mountlist * mountproc_dump_2_svc(void *, struct svc_req *); +extern void * mountproc_umnt_2(dirpath *, CLIENT *); +extern void * mountproc_umnt_2_svc(dirpath *, struct svc_req *); +extern void * mountproc_umntall_2(void *, CLIENT *); +extern void * mountproc_umntall_2_svc(void *, struct svc_req *); +extern exports * mountproc_export_2(void *, CLIENT *); +extern exports * mountproc_export_2_svc(void *, struct svc_req *); +extern exports * mountproc_exportall_2(void *, CLIENT *); +extern exports * mountproc_exportall_2_svc(void *, struct svc_req *); +#define MOUNTPROC_PATHCONF ((u_long)7) +extern ppathcnf * mountproc_pathconf_2(dirpath *, CLIENT *); +extern ppathcnf * mountproc_pathconf_2_svc(dirpath *, struct svc_req *); + +#else /* Old Style C */ +extern void * mountproc_null_2(); +extern void * mountproc_null_2_svc(); +extern fhstatus * mountproc_mnt_2(); +extern fhstatus * mountproc_mnt_2_svc(); +extern mountlist * mountproc_dump_2(); +extern mountlist * mountproc_dump_2_svc(); +extern void * mountproc_umnt_2(); +extern void * mountproc_umnt_2_svc(); +extern void * mountproc_umntall_2(); +extern void * mountproc_umntall_2_svc(); +extern exports * mountproc_export_2(); +extern exports * mountproc_export_2_svc(); +extern exports * mountproc_exportall_2(); +extern exports * mountproc_exportall_2_svc(); +#define MOUNTPROC_PATHCONF ((u_long)7) +extern ppathcnf * mountproc_pathconf_2(); +extern ppathcnf * mountproc_pathconf_2_svc(); +#endif /* Old Style C */ + +#endif /* !_NFSMOUNT_H_RPCGEN */ diff --git a/isys/sundries.h b/isys/sundries.h new file mode 100644 index 000000000..cad87a1c8 --- /dev/null +++ b/isys/sundries.h @@ -0,0 +1,74 @@ +/* + * sundries.h + * Support function prototypes. Functions are in sundries.c. + */ + +#include <sys/types.h> +#include <fcntl.h> +#include <limits.h> +#include <signal.h> +#include <stdarg.h> +#include <stdlib.h> +#if !defined(bool_t) && !defined(__GLIBC__) +#include <rpc/types.h> +#endif + +extern int mount_quiet; +extern int verbose; +extern int sloppy; + +#define streq(s, t) (strcmp ((s), (t)) == 0) + + +/* String list data structure. */ +typedef struct string_list +{ + char *hd; + struct string_list *tl; +} *string_list; + +#define car(p) ((p) -> hd) +#define cdr(p) ((p) -> tl) + +string_list cons (char *a, const string_list); + +/* Functions in sundries.c that are used in mount.c and umount.c */ +void block_signals (int how); +char *canonicalize (const char *path); +char *realpath (const char *path, char *resolved_path); +void error (const char *fmt, ...); +int matching_type (const char *type, string_list types); +string_list parse_list (char *strings); +void *xmalloc (size_t size); +char *xstrdup (const char *s); +char *xstrndup (const char *s, int n); +char *xstrconcat2 (const char *, const char *); +char *xstrconcat3 (const char *, const char *, const char *); +char *xstrconcat4 (const char *, const char *, const char *, const char *); + +/* Here is some serious cruft. */ +#ifdef __GNUC__ +#if defined(__GNUC_MINOR__) && __GNUC__ == 2 && __GNUC_MINOR__ >= 5 +void die (int errcode, const char *fmt, ...) __attribute__ ((noreturn)); +#else /* GNUC < 2.5 */ +void volatile die (int errcode, const char *fmt, ...); +#endif /* GNUC < 2.5 */ +#else /* !__GNUC__ */ +void die (int errcode, const char *fmt, ...); +#endif /* !__GNUC__ */ + +#ifdef HAVE_NFS +int nfsmount (const char *spec, const char *node, int *flags, + char **orig_opts, char **opt_args, int running_bg); +#endif + +/* exit status - bits below are ORed */ +#define EX_USAGE 1 /* incorrect invocation or permission */ +#define EX_SYSERR 2 /* out of memory, cannot fork, ... */ +#define EX_SOFTWARE 4 /* internal mount bug or wrong version */ +#define EX_USER 8 /* user interrupt */ +#define EX_FILEIO 16 /* problems writing, locking, ... mtab/fstab */ +#define EX_FAIL 32 /* mount failure */ +#define EX_SOMEOK 64 /* some mount succeeded */ + +#define EX_BG 256 /* retry in background (internal only) */ |