X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=util-linux%2Fnfsmount.c;h=e9d6dc6354309b6b84391cda61cd780ea8c04a99;hb=248d2220f9985754268f4492278758052494b80a;hp=d661a99a42c0f750590fc58b769df2c18ce036e2;hpb=59ab025363d884deb2013dcaae6c968585a6ec72;p=oweals%2Fbusybox.git diff --git a/util-linux/nfsmount.c b/util-linux/nfsmount.c index d661a99a4..e9d6dc635 100644 --- a/util-linux/nfsmount.c +++ b/util-linux/nfsmount.c @@ -24,7 +24,7 @@ * * 1999-02-22 Arkadiusz Mi¶kiewicz * - added Native Language Support - * + * * Modified by Olaf Kirch and Trond Myklebust for new NFS code, * plus NFSv3 stuff. */ @@ -33,25 +33,78 @@ * nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp */ -#include "busybox.h" -#undef FALSE -#undef TRUE #include #include #include #include #include -#include -#include -#include #include -#include +#include #include #include #include - +#include +#include "busybox.h" +#undef TRUE +#undef FALSE +#include +#include +#include #include "nfsmount.h" -#include /* For the kernels nfs stuff */ + +/* This is just a warning of a common mistake. Possibly this should be a + * * uclibc faq entry rather than in busybox... */ +#if ENABLE_FEATURE_MOUNT_NFS && defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__) +#error "You need to build uClibc with UCLIBC_HAS_RPC for NFS support." +#endif + + +/* + * NFS stats. The good thing with these values is that NFSv3 errors are + * a superset of NFSv2 errors (with the exception of NFSERR_WFLUSH which + * no-one uses anyway), so we can happily mix code as long as we make sure + * no NFSv3 errors are returned to NFSv2 clients. + * Error codes that have a `--' in the v2 column are not part of the + * standard, but seem to be widely used nevertheless. + */ +enum nfs_stat { + NFS_OK = 0, /* v2 v3 */ + NFSERR_PERM = 1, /* v2 v3 */ + NFSERR_NOENT = 2, /* v2 v3 */ + NFSERR_IO = 5, /* v2 v3 */ + NFSERR_NXIO = 6, /* v2 v3 */ + NFSERR_EAGAIN = 11, /* v2 v3 */ + NFSERR_ACCES = 13, /* v2 v3 */ + NFSERR_EXIST = 17, /* v2 v3 */ + NFSERR_XDEV = 18, /* v3 */ + NFSERR_NODEV = 19, /* v2 v3 */ + NFSERR_NOTDIR = 20, /* v2 v3 */ + NFSERR_ISDIR = 21, /* v2 v3 */ + NFSERR_INVAL = 22, /* v2 v3 that Sun forgot */ + NFSERR_FBIG = 27, /* v2 v3 */ + NFSERR_NOSPC = 28, /* v2 v3 */ + NFSERR_ROFS = 30, /* v2 v3 */ + NFSERR_MLINK = 31, /* v3 */ + NFSERR_OPNOTSUPP = 45, /* v2 v3 */ + NFSERR_NAMETOOLONG = 63, /* v2 v3 */ + NFSERR_NOTEMPTY = 66, /* v2 v3 */ + NFSERR_DQUOT = 69, /* v2 v3 */ + NFSERR_STALE = 70, /* v2 v3 */ + NFSERR_REMOTE = 71, /* v2 v3 */ + NFSERR_WFLUSH = 99, /* v2 */ + NFSERR_BADHANDLE = 10001, /* v3 */ + NFSERR_NOT_SYNC = 10002, /* v3 */ + NFSERR_BAD_COOKIE = 10003, /* v3 */ + NFSERR_NOTSUPP = 10004, /* v3 */ + NFSERR_TOOSMALL = 10005, /* v3 */ + NFSERR_SERVERFAULT = 10006, /* v3 */ + NFSERR_BADTYPE = 10007, /* v3 */ + NFSERR_JUKEBOX = 10008 /* v3 */ +}; + +#define NFS_PROGRAM 100003 + + #ifndef NFS_FHSIZE static const int NFS_FHSIZE = 32; @@ -93,14 +146,16 @@ static const int MS_NODIRATIME = 2048; /* Do not update directory access time * so it is easiest to ignore the kernel altogether (at compile time). */ -static const int NFS_MOUNT_VERSION = 4; +/* NOTE: Do not make this into a 'static const int' because the pre-processor + * needs to test this value in some #if statements. */ +#define NFS_MOUNT_VERSION 4 struct nfs2_fh { - char data[32]; + char data[32]; }; struct nfs3_fh { - unsigned short size; - unsigned char data[64]; + unsigned short size; + unsigned char data[64]; }; struct nfs_mount_data { @@ -155,7 +210,7 @@ static const int NFS_MOUNT_NONLM = 0x0200; /* 3 */ #define HAVE_personality #define HAVE_tm_gmtoff -static char *nfs_strerror(int stat); +static char *nfs_strerror(int status); #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) #define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2) @@ -181,7 +236,8 @@ static int nfs_mount_version; * nfs_mount_version: version this source and running kernel can handle */ static void -find_kernel_nfs_mount_version(void) { +find_kernel_nfs_mount_version(void) +{ static int kernel_version = 0; if (kernel_version) @@ -191,15 +247,17 @@ find_kernel_nfs_mount_version(void) { kernel_version = get_kernel_revision(); if (kernel_version) { - if (kernel_version < MAKE_VERSION(2,1,32)) - nfs_mount_version = 1; - else if (kernel_version < MAKE_VERSION(2,3,99)) - nfs_mount_version = 3; - else - nfs_mount_version = 4; /* since 2.3.99pre4 */ + if (kernel_version < MAKE_VERSION(2,1,32)) + nfs_mount_version = 1; + else if (kernel_version < MAKE_VERSION(2,2,18) || + (kernel_version >= MAKE_VERSION(2,3,0) && + kernel_version < MAKE_VERSION(2,3,99))) + nfs_mount_version = 3; + else + nfs_mount_version = 4; /* since 2.3.99pre4 */ } if (nfs_mount_version > NFS_MOUNT_VERSION) - nfs_mount_version = NFS_MOUNT_VERSION; + nfs_mount_version = NFS_MOUNT_VERSION; } static struct pmap * @@ -251,19 +309,19 @@ return &p; } int nfsmount(const char *spec, const char *node, int *flags, - char **extra_opts, char **mount_opts, int running_bg) + char **mount_opts, int running_bg) { static char *prev_bg_host; char hostdir[1024]; CLIENT *mclient; char *hostname; - char *dirname; + char *pathname; char *old_opts; char *mounthost=NULL; char new_opts[1024]; struct timeval total_timeout; enum clnt_stat clnt_stat; - static struct nfs_mount_data data; + struct nfs_mount_data data; char *opt, *opteq; int val; struct hostent *hp; @@ -305,22 +363,22 @@ int nfsmount(const char *spec, const char *node, int *flags, msock = fsock = -1; mclient = NULL; if (strlen(spec) >= sizeof(hostdir)) { - error_msg("excessively long host:dir argument\n"); + bb_error_msg("excessively long host:dir argument"); goto fail; } strcpy(hostdir, spec); if ((s = strchr(hostdir, ':'))) { hostname = hostdir; - dirname = s + 1; + pathname = 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'; - error_msg("warning: multiple hostnames not supported\n"); + bb_error_msg("warning: multiple hostnames not supported"); } } else { - error_msg("directory to mount not in host:dir format\n"); + bb_error_msg("directory to mount not in host:dir format"); goto fail; } @@ -330,11 +388,11 @@ int nfsmount(const char *spec, const char *node, int *flags, #endif { if ((hp = gethostbyname(hostname)) == NULL) { - error_msg("can't get address for %s\n", hostname); + bb_herror_msg("%s", hostname); goto fail; } else { if (hp->h_length > sizeof(struct in_addr)) { - error_msg("got bad hp->h_length\n"); + bb_error_msg("got bad hp->h_length"); hp->h_length = sizeof(struct in_addr); } memcpy(&server_addr.sin_addr, @@ -347,16 +405,16 @@ int nfsmount(const char *spec, const char *node, int *flags, /* add IP address to mtab options for use when unmounting */ s = inet_ntoa(server_addr.sin_addr); - old_opts = *extra_opts; + old_opts = *mount_opts; if (!old_opts) old_opts = ""; if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) { - error_msg("excessively long option argument\n"); + bb_error_msg("excessively long option argument"); goto fail; } sprintf(new_opts, "%s%saddr=%s", old_opts, *old_opts ? "," : "", s); - *extra_opts = xstrdup(new_opts); + *mount_opts = bb_xstrdup(new_opts); /* Set default options. * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to @@ -393,7 +451,7 @@ int nfsmount(const char *spec, const char *node, int *flags, for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) { if ((opteq = strchr(opt, '='))) { - val = atoi(opteq + 1); + val = atoi(opteq + 1); *opteq = '\0'; if (!strcmp(opt, "rsize")) data.rsize = val; @@ -424,7 +482,7 @@ int nfsmount(const char *spec, const char *node, int *flags, else if (!strcmp(opt, "mountport")) mountport = val; else if (!strcmp(opt, "mounthost")) - mounthost=xstrndup(opteq+1, + mounthost=bb_xstrndup(opteq+1, strcspn(opteq+1," \t\n\r,")); else if (!strcmp(opt, "mountprog")) mountprog = val; @@ -463,9 +521,9 @@ int nfsmount(const char *spec, const char *node, int *flags, val = 0; opt += 2; } - if (!strcmp(opt, "bg")) + if (!strcmp(opt, "bg")) bg = val; - else if (!strcmp(opt, "fg")) + else if (!strcmp(opt, "fg")) bg = !val; else if (!strcmp(opt, "soft")) soft = val; @@ -511,11 +569,11 @@ int nfsmount(const char *spec, const char *node, int *flags, data.flags |= (nolock ? NFS_MOUNT_NONLM : 0); #endif if (nfsvers > MAX_NFSPROT) { - error_msg("NFSv%d not supported!\n", nfsvers); + bb_error_msg("NFSv%d not supported!", nfsvers); return 0; } if (mountvers > MAX_NFSPROT) { - error_msg("NFSv%d not supported!\n", nfsvers); + bb_error_msg("NFSv%d not supported!", nfsvers); return 0; } if (nfsvers && !mountvers) @@ -550,10 +608,9 @@ int nfsmount(const char *spec, const char *node, int *flags, #endif data.version = nfs_mount_version; - *mount_opts = (char *) &data; if (*flags & MS_REMOUNT) - return 0; + goto copy_data_and_return; /* * If the previous mount operation on the same host was @@ -575,11 +632,11 @@ int nfsmount(const char *spec, const char *node, int *flags, mount_server_addr.sin_addr.s_addr = inet_addr(hostname); } else { if ((hp = gethostbyname(mounthost)) == NULL) { - error_msg("can't get address for %s\n", hostname); + bb_herror_msg("%s", mounthost); goto fail; } else { if (hp->h_length > sizeof(struct in_addr)) { - error_msg("got bad hp->h_length?\n"); + bb_error_msg("got bad hp->h_length?"); hp->h_length = sizeof(struct in_addr); } mount_server_addr.sin_family = AF_INET; @@ -630,7 +687,7 @@ int nfsmount(const char *spec, const char *node, int *flags, mountprog, mountvers, proto, - mountport); + mountport); /* contact the mount daemon via TCP */ mount_server_addr.sin_port = htons(pm_mnt->pm_port); @@ -657,7 +714,7 @@ int nfsmount(const char *spec, const char *node, int *flags, mclient = 0; } if (mclient) { - /* try to mount hostname:dirname */ + /* try to mount hostname:pathname */ mclient->cl_auth = authunix_create_default(); /* make pointers in xdr_mountres3 NULL so @@ -668,14 +725,14 @@ int nfsmount(const char *spec, const char *node, int *flags, if (pm_mnt->pm_vers == 3) clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT, (xdrproc_t) xdr_dirpath, - (caddr_t) &dirname, + (caddr_t) &pathname, (xdrproc_t) xdr_mountres3, (caddr_t) &status, total_timeout); else clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, - (caddr_t) &dirname, + (caddr_t) &pathname, (xdrproc_t) xdr_fhstatus, (caddr_t) &status, total_timeout); @@ -701,7 +758,7 @@ int nfsmount(const char *spec, const char *node, int *flags, if (!bg) goto fail; if (!running_bg) { - prev_bg_host = xstrdup(hostname); + prev_bg_host = bb_xstrdup(hostname); if (retry > 0) retval = EX_BG; goto fail; @@ -714,8 +771,8 @@ int nfsmount(const char *spec, const char *node, int *flags, if (nfsvers == 2) { if (status.nfsv2.fhs_status != 0) { - error_msg("%s:%s failed, reason given by server: %s\n", - hostname, dirname, + bb_error_msg("%s:%s failed, reason given by server: %s", + hostname, pathname, nfs_strerror(status.nfsv2.fhs_status)); goto fail; } @@ -730,20 +787,20 @@ int nfsmount(const char *spec, const char *node, int *flags, #endif } else { #if NFS_MOUNT_VERSION >= 4 - fhandle3 *fhandle; + fhandle3 *my_fhandle; if (status.nfsv3.fhs_status != 0) { - error_msg("%s:%s failed, reason given by server: %s\n", - hostname, dirname, + bb_error_msg("%s:%s failed, reason given by server: %s", + hostname, pathname, nfs_strerror(status.nfsv3.fhs_status)); goto fail; } - fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle; + my_fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle; memset(data.old_root.data, 0, NFS_FHSIZE); memset(&data.root, 0, sizeof(data.root)); - data.root.size = fhandle->fhandle3_len; + data.root.size = my_fhandle->fhandle3_len; memcpy(data.root.data, - (char *) fhandle->fhandle3_val, - fhandle->fhandle3_len); + (char *) my_fhandle->fhandle3_val, + my_fhandle->fhandle3_len); data.flags |= NFS_MOUNT_VER3; #endif @@ -753,7 +810,7 @@ int nfsmount(const char *spec, const char *node, int *flags, if (tcp) { if (nfs_mount_version < 3) { - printf(_("NFS over TCP is not supported.\n")); + printf(_("NFS over TCP is not supported.\n")); goto fail; } fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -805,6 +862,9 @@ int nfsmount(const char *spec, const char *node, int *flags, auth_destroy(mclient->cl_auth); clnt_destroy(mclient); close(msock); +copy_data_and_return: + *mount_opts = xrealloc(*mount_opts, sizeof(data)); + memcpy(*mount_opts, &data, sizeof(data)); return 0; /* abort */ @@ -820,7 +880,7 @@ fail: if (fsock != -1) close(fsock); return retval; -} +} /* * We need to translate between nfs status return values and @@ -835,7 +895,7 @@ fail: #define EDQUOT ENOSPC #endif -static struct { +static const struct { enum nfs_stat stat; int errnum; } nfs_errtbl[] = { @@ -868,20 +928,20 @@ static struct { { -1, EIO } }; -static char *nfs_strerror(int stat) +static char *nfs_strerror(int status) { int i; static char buf[256]; for (i = 0; nfs_errtbl[i].stat != -1; i++) { - if (nfs_errtbl[i].stat == stat) + if (nfs_errtbl[i].stat == status) return strerror(nfs_errtbl[i].errnum); } - sprintf(buf, _("unknown nfs status return value: %d"), stat); + sprintf(buf, _("unknown nfs status return value: %d"), status); return buf; } -bool_t +static bool_t xdr_fhandle (XDR *xdrs, fhandle objp) { //register int32_t *buf; @@ -924,7 +984,7 @@ xdr_fhandle3 (XDR *xdrs, fhandle3 *objp) { //register int32_t *buf; - if (!xdr_bytes (xdrs, (char **)&objp->fhandle3_val, (u_int *) &objp->fhandle3_len, FHSIZE3)) + if (!xdr_bytes (xdrs, (char **)&objp->fhandle3_val, (unsigned int *) &objp->fhandle3_len, FHSIZE3)) return FALSE; return TRUE; } @@ -936,7 +996,7 @@ xdr_mountres3_ok (XDR *xdrs, mountres3_ok *objp) if (!xdr_fhandle3 (xdrs, &objp->fhandle)) return FALSE; - if (!xdr_array (xdrs, (char **)&objp->auth_flavours.auth_flavours_val, (u_int *) &objp->auth_flavours.auth_flavours_len, ~0, + if (!xdr_array (xdrs, (char **)&objp->auth_flavours.auth_flavours_val, (unsigned int *) &objp->auth_flavours.auth_flavours_len, ~0, sizeof (int), (xdrproc_t) xdr_int)) return FALSE; return TRUE;