Module Name: src Committed By: mlelstv Date: Tue Dec 12 09:16:17 UTC 2023
Modified Files: src/sys/arch/i386/stand/libsa: nfs.c Log Message: Merge with generic libsa NFS code to minimize differences and to learn NFSv3. To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.20 src/sys/arch/i386/stand/libsa/nfs.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/i386/stand/libsa/nfs.c diff -u src/sys/arch/i386/stand/libsa/nfs.c:1.19 src/sys/arch/i386/stand/libsa/nfs.c:1.20 --- src/sys/arch/i386/stand/libsa/nfs.c:1.19 Sun Dec 25 06:09:09 2011 +++ src/sys/arch/i386/stand/libsa/nfs.c Tue Dec 12 09:16:17 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: nfs.c,v 1.19 2011/12/25 06:09:09 tsutsui Exp $ */ +/* $NetBSD: nfs.c,v 1.20 2023/12/12 09:16:17 mlelstv Exp $ */ /*- * Copyright (c) 1993 John Brezak @@ -28,6 +28,16 @@ * POSSIBILITY OF SUCH DAMAGE. */ +/* + * XXX Does not currently implement: + * XXX + * XXX LIBSA_NO_FS_CLOSE + * XXX LIBSA_NO_FS_SEEK + * XXX LIBSA_NO_FS_WRITE + * XXX LIBSA_NO_FS_SYMLINK (does this even make sense?) + * XXX LIBSA_FS_SINGLECOMPONENT (does this even make sense?) + */ + #include <sys/param.h> #include <sys/time.h> #include <sys/socket.h> @@ -43,6 +53,7 @@ #include "rpcv2.h" #include "nfsv2.h" +#include "nfsv3.h" #include <lib/libsa/stand.h> #include "net.h" @@ -50,40 +61,11 @@ #include "nfs.h" #include "rpc.h" -/* Define our own NFS attributes. */ -struct nfsv2_fattrs { - n_long fa_type; - n_long fa_mode; - n_long fa_nlink; - n_long fa_uid; - n_long fa_gid; - n_long fa_size; - n_long fa_blocksize; - n_long fa_rdev; - n_long fa_blocks; - n_long fa_fsid; - n_long fa_fileid; - struct nfsv2_time fa_atime; - struct nfsv2_time fa_mtime; - struct nfsv2_time fa_ctime; -}; - - -struct nfs_read_args { - u_char fh[NFS_FHSIZE]; - n_long off; - n_long len; - n_long xxx; /* XXX what's this for? */ -}; +/* Storage for any filehandle (including length for V3) */ +#define NFS_FHSTORE (NFS_FHSIZE < NFS_V3FHSIZE ? NFS_V3FHSIZE + 4: NFS_FHSIZE) /* Data part of nfs rpc reply (also the largest thing we receive) */ #define NFSREAD_SIZE 1024 -struct nfs_read_repl { - n_long errno; - struct nfsv2_fattrs fa; - n_long count; - u_char data[NFSREAD_SIZE]; -}; #ifndef NFS_NOSYMLINK struct nfs_readlnk_repl { @@ -93,36 +75,88 @@ struct nfs_readlnk_repl { }; #endif +static inline uint64_t +getnquad(n_long x[2]) { + return (uint64_t)ntohl(x[0]) << 32 | ntohl(x[1]); +} + +static inline void +setnquad(n_long x[2], uint64_t v) +{ + x[0] = htonl((n_long)(v >> 32)); + x[1] = htonl((n_long)(v & 0xffffffff)); +} + struct nfs_iodesc { struct iodesc *iodesc; off_t off; - u_char fh[NFS_FHSIZE]; - struct nfsv2_fattrs fa; /* all in network order */ + int version; + u_char fh[NFS_FHSTORE]; + union { + /* all in network order */ + struct nfsv2_fattr v2; + struct nfsv3_fattr v3; + } u_fa; }; -int nfs_getrootfh(struct iodesc *, char *, u_char *); +static inline size_t +fhstore(int version, u_char *fh) +{ + size_t len; + + switch (version) { + case NFS_VER2: + len = NFS_FHSIZE; + break; + case NFS_VER3: + len = fh[0] << 24 | fh[1] << 16 | fh[2] << 8 | fh[3]; + if (len > NFS_V3FHSIZE) + len = NFS_V3FHSIZE; + len = 4 + roundup(len, 4); + break; + default: + len = 0; + break; + } + + return len; +} + +static inline size_t +fhcopy(int version, u_char *src, u_char *dst) +{ + size_t len = fhstore(version, src); + memcpy(dst, src, len); + return len; +} + +#define setfh(d, s) fhcopy((d)->version, (s), (d)->fh) +#define getfh(d, s) fhcopy((d)->version, (d)->fh, (s)) + + +struct nfs_iodesc nfs_root_node; + +int nfs_getrootfh(struct iodesc *, char *, u_char *, int *); int nfs_lookupfh(struct nfs_iodesc *, const char *, int, struct nfs_iodesc *); -#ifndef NFS_NOSYMLINK int nfs_readlink(struct nfs_iodesc *, char *); -#endif ssize_t nfs_readdata(struct nfs_iodesc *, off_t, void *, size_t); /* * Fetch the root file handle (call mount daemon) - * Return zero or error number. + * On error, return non-zero and set errno. */ int -nfs_getrootfh(struct iodesc *d, char *path, u_char *fhp) +nfs_getrootfh(struct iodesc *d, char *path, u_char *fhp, int *versionp) { - size_t len; + int len; struct args { n_long len; char path[FNAME_SIZE]; } *args; struct repl { n_long errno; - u_char fh[NFS_FHSIZE]; + u_char fh[NFS_FHSTORE]; } *repl; struct { n_long h[RPC_HEADER_WORDS]; @@ -136,32 +170,42 @@ nfs_getrootfh(struct iodesc *d, char *pa #ifdef NFS_DEBUG if (debug) - printf("nfs_getrootfh: %s\n", path); + printf("%s: %s\n", __func__, path); #endif args = &sdata.d; repl = &rdata.d; - memset(args, 0, sizeof(*args)); + (void)memset(args, 0, sizeof(*args)); len = strlen(path); - if (len > sizeof(args->path)) + if ((size_t)len > sizeof(args->path)) len = sizeof(args->path); args->len = htonl(len); - memcpy(args->path, path, len); + (void)memcpy(args->path, path, len); len = 4 + roundup(len, 4); - cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT, + *versionp = NFS_VER3; + cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER3, RPCMNT_MOUNT, args, len, repl, sizeof(*repl)); + if (cc == -1 || cc < 4 || repl->errno) { + *versionp = NFS_VER2; + cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT, + args, len, repl, sizeof(*repl)); + } if (cc == -1) { /* errno was set by rpc_call */ - return (errno); + return -1; } - if (cc < 4) - return (EBADRPC); - if (repl->errno) - return (ntohl(repl->errno)); - memcpy(fhp, repl->fh, sizeof(repl->fh)); - return (0); + if (cc < 4) { + errno = EBADRPC; + return -1; + } + if (repl->errno) { + errno = ntohl(repl->errno); + return -1; + } + fhcopy(*versionp, repl->fh, fhp); + return 0; } /* @@ -169,61 +213,130 @@ nfs_getrootfh(struct iodesc *d, char *pa * Return zero or error number. */ int -nfs_lookupfh(struct nfs_iodesc *d, const char *name, int len, struct nfs_iodesc *newfd) +nfs_lookupfh(struct nfs_iodesc *d, const char *name, int len, + struct nfs_iodesc *newfd) { - int rlen; - struct args { + struct argsv2 { u_char fh[NFS_FHSIZE]; n_long len; char name[FNAME_SIZE]; - } *args; - struct repl { + } *argsv2; + struct argsv3 { + u_char fh[NFS_FHSTORE]; + n_long len; + char name[FNAME_SIZE]; + } *argsv3; + struct replv2 { n_long errno; u_char fh[NFS_FHSIZE]; - struct nfsv2_fattrs fa; - } *repl; + struct nfsv2_fattr fa; + } *replv2; + struct replv3 { + n_long errno; + u_char fh[NFS_FHSTORE]; + n_long fattrflag; + struct nfsv3_fattr fa; + n_long dattrflag; + struct nfsv3_fattr da; + } *replv3; struct { n_long h[RPC_HEADER_WORDS]; - struct args d; + union { + struct argsv2 v2; + struct argsv3 v3; + } u_d; } sdata; struct { n_long h[RPC_HEADER_WORDS]; - struct repl d; + union { + struct replv2 v2; + struct replv3 v3; + } u_d; } rdata; ssize_t cc; + size_t alen; #ifdef NFS_DEBUG if (debug) - printf("lookupfh: called\n"); + printf("%s: called\n", __func__); #endif - args = &sdata.d; - repl = &rdata.d; + argsv2 = &sdata.u_d.v2; + argsv3 = &sdata.u_d.v3; + replv2 = &rdata.u_d.v2; + replv3 = &rdata.u_d.v3; + + switch (d->version) { + case NFS_VER2: + (void)memset(argsv2, 0, sizeof(*argsv2)); + getfh(d, argsv2->fh); + if ((size_t)len > sizeof(argsv2->name)) + len = sizeof(argsv2->name); + (void)memcpy(argsv2->name, name, len); + argsv2->len = htonl(len); + + /* padded name, name length */ + len = roundup(len, 4) + 4; + /* filehandle size */ + alen = fhstore(d->version, argsv2->fh); - memset(args, 0, sizeof(*args)); - memcpy(args->fh, d->fh, sizeof(args->fh)); - if ((size_t)len > sizeof(args->name)) - len = sizeof(args->name); - memcpy(args->name, name, len); - args->len = htonl(len); - len = 4 + roundup(len, 4); - len += NFS_FHSIZE; + cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP, + argsv2, alen+len, replv2, sizeof(*replv2)); + break; + case NFS_VER3: + (void)memset(argsv3, 0, sizeof(*argsv3)); + getfh(d, argsv3->fh); + if ((size_t)len > sizeof(argsv3->name)) + len = sizeof(argsv3->name); + (void)memcpy(argsv3->name, name, len); + argsv3->len = htonl(len); + + /* padded name, name length */ + len = roundup(len, 4) + 4; + /* filehandle size */ + alen = fhstore(d->version, argsv3->fh); - rlen = sizeof(*repl); + /* adjust for variable sized file handle */ + memmove(argsv3->fh + alen, &argsv3->len, len); + + cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER3, NFSV3PROC_LOOKUP, + argsv3, alen+len, replv3, sizeof(*replv3)); + break; + default: + return ENOSYS; + } - cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP, - args, len, repl, rlen); if (cc == -1) - return (errno); /* XXX - from rpc_call */ + return errno; /* XXX - from rpc_call */ if (cc < 4) - return (EIO); - if (repl->errno) { - /* saerrno.h now matches NFS error numbers. */ - return (ntohl(repl->errno)); + return EIO; + + switch (d->version) { + case NFS_VER2: + if (replv2->errno) { + /* saerrno.h now matches NFS error numbers. */ + return ntohl(replv2->errno); + } + + setfh(newfd, replv2->fh); + (void)memcpy(&newfd->u_fa.v2, &replv2->fa, + sizeof(newfd->u_fa.v2)); + break; + case NFS_VER3: + if (replv3->errno) { + /* saerrno.h now matches NFS error numbers. */ + return ntohl(replv3->errno); + } + + setfh(newfd, replv3->fh); + + if (replv3->fattrflag) { + (void)memcpy(&newfd->u_fa.v3, &replv3->fa, + sizeof(newfd->u_fa.v3)); + } + break; } - memcpy(&newfd->fh, repl->fh, sizeof(newfd->fh)); - memcpy(&newfd->fa, &repl->fa, sizeof(newfd->fa)); - return (0); + return 0; } #ifndef NFS_NOSYMLINK @@ -235,7 +348,7 @@ nfs_readlink(struct nfs_iodesc *d, char { struct { n_long h[RPC_HEADER_WORDS]; - u_char fh[NFS_FHSIZE]; + u_char fh[NFS_FHSTORE]; } sdata; struct { n_long h[RPC_HEADER_WORDS]; @@ -245,29 +358,29 @@ nfs_readlink(struct nfs_iodesc *d, char #ifdef NFS_DEBUG if (debug) - printf("readlink: called\n"); + printf("%s: called\n", __func__); #endif - memcpy(sdata.fh, d->fh, NFS_FHSIZE); - cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK, - sdata.fh, NFS_FHSIZE, + getfh(d, sdata.fh); + cc = rpc_call(d->iodesc, NFS_PROG, d->version, NFSPROC_READLINK, + sdata.fh, fhstore(d->version, sdata.fh), &rdata.d, sizeof(rdata.d)); if (cc == -1) - return (errno); + return errno; if (cc < 4) - return (EIO); + return EIO; if (rdata.d.errno) - return (ntohl(rdata.d.errno)); + return ntohl(rdata.d.errno); rdata.d.len = ntohl(rdata.d.len); if (rdata.d.len > NFS_MAXPATHLEN) - return (ENAMETOOLONG); + return ENAMETOOLONG; - memcpy(buf, rdata.d.path, rdata.d.len); + (void)memcpy(buf, rdata.d.path, rdata.d.len); buf[rdata.d.len] = 0; - return (0); + return 0; } #endif @@ -278,55 +391,195 @@ nfs_readlink(struct nfs_iodesc *d, char ssize_t nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len) { - struct nfs_read_args *args; - struct nfs_read_repl *repl; + struct argsv2 { + u_char fh[NFS_FHSIZE]; + n_long off; + n_long len; + n_long xxx; /* XXX what's this for? */ + } *argsv2; + struct argsv3 { + u_char fh[NFS_FHSTORE]; + n_long off[2]; + n_long len; + } *argsv3; + struct replv2 { + n_long errno; + struct nfsv2_fattr fa; + n_long count; + u_char data[NFSREAD_SIZE]; + } *replv2; + struct replv3 { + n_long errno; + n_long attrflag; + struct nfsv3_fattr fa; + n_long count; + n_long eof; + n_long length; + u_char data[NFSREAD_SIZE]; + } *replv3; + struct replv3_noattr { + n_long errno; + n_long attrflag; + n_long count; + n_long eof; + n_long length; + u_char data[NFSREAD_SIZE]; + } *replv3no; struct { n_long h[RPC_HEADER_WORDS]; - struct nfs_read_args d; + union { + struct argsv2 v2; + struct argsv3 v3; + } u_d; } sdata; struct { n_long h[RPC_HEADER_WORDS]; - struct nfs_read_repl d; + union { + struct replv2 v2; + struct replv3 v3; + } u_d; } rdata; ssize_t cc; long x; - int hlen, rlen; + size_t hlen, rlen, alen; + u_char *data; - args = &sdata.d; - repl = &rdata.d; + argsv2 = &sdata.u_d.v2; + argsv3 = &sdata.u_d.v3; + replv2 = &rdata.u_d.v2; + replv3 = &rdata.u_d.v3; - memcpy(args->fh, d->fh, NFS_FHSIZE); - args->off = htonl((n_long)off); if (len > NFSREAD_SIZE) len = NFSREAD_SIZE; - args->len = htonl((n_long)len); - args->xxx = htonl((n_long)0); - hlen = sizeof(*repl) - NFSREAD_SIZE; - - cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ, - args, sizeof(*args), - repl, sizeof(*repl)); + + switch (d->version) { + case NFS_VER2: + getfh(d, argsv2->fh); + argsv2->off = htonl((n_long)off); + argsv2->len = htonl((n_long)len); + argsv2->xxx = htonl((n_long)0); + hlen = sizeof(*replv2) - NFSREAD_SIZE; + cc = rpc_call(d->iodesc, NFS_PROG, d->version, NFSPROC_READ, + argsv2, sizeof(*argsv2), + replv2, sizeof(*replv2)); + break; + case NFS_VER3: + getfh(d, argsv3->fh); + setnquad(argsv3->off, (uint64_t)off); + argsv3->len = htonl((n_long)len); + hlen = sizeof(*replv3) - NFSREAD_SIZE; + + /* adjust for variable sized file handle */ + alen = sizeof(*argsv3) - offsetof(struct argsv3, off); + memmove(argsv3->fh + fhstore(d->version, argsv3->fh), + &argsv3->off, alen); + alen += fhstore(d->version, argsv3->fh); + + cc = rpc_call(d->iodesc, NFS_PROG, d->version, NFSPROC_READ, + argsv3, alen, + replv3, sizeof(*replv3)); + break; + default: + errno = ENOSYS; + return -1; + } + if (cc == -1) { /* errno was already set by rpc_call */ - return (-1); + return -1; } - if (cc < hlen) { + if (cc < (ssize_t)hlen) { errno = EBADRPC; - return (-1); + return -1; } - if (repl->errno) { - errno = ntohl(repl->errno); - return (-1); + + switch (d->version) { + case NFS_VER2: + if (replv2->errno) { + errno = ntohl(replv2->errno); + return -1; + } + x = ntohl(replv2->count); + data = replv2->data; + break; + case NFS_VER3: + if (replv3->errno) { + errno = ntohl(replv3->errno); + return -1; + } + + /* adjust for optional attributes */ + if (replv3->attrflag) { + x = ntohl(replv3->length); + data = replv3->data; + } else { + replv3no = (struct replv3_noattr *)replv3; + x = ntohl(replv3no->length); + data = replv3no->data; + } + break; + default: + errno = ENOSYS; + return -1; } + rlen = cc - hlen; - x = ntohl(repl->count); - if (rlen < x) { - printf("nfsread: short packet, %d < %ld\n", rlen, x); + if (rlen < (size_t)x) { + printf("%s: short packet, %zu < %ld\n", __func__, rlen, x); errno = EBADRPC; - return (-1); + return -1; } - memcpy(addr, repl->data, x); - return (x); + (void)memcpy(addr, data, x); + return x; +} + +/* + * nfs_mount - mount this nfs filesystem to a host + * On error, return non-zero and set errno. + */ +int +nfs_mount(int sock, struct in_addr ip, char *path) +{ + struct iodesc *desc; + struct nfsv2_fattr *fa2; + struct nfsv3_fattr *fa3; + + if (!(desc = socktodesc(sock))) { + errno = EINVAL; + return -1; + } + + /* Bind to a reserved port. */ + desc->myport = htons(--rpc_port); + desc->destip = ip; + if (nfs_getrootfh(desc, path, nfs_root_node.fh, &nfs_root_node.version)) + return -1; + nfs_root_node.iodesc = desc; + /* Fake up attributes for the root dir. */ + switch (nfs_root_node.version) { + case NFS_VER2: + fa2 = &nfs_root_node.u_fa.v2; + fa2->fa_type = htonl(NFDIR); + fa2->fa_mode = htonl(0755); + fa2->fa_nlink = htonl(2); + break; + case NFS_VER3: + fa3 = &nfs_root_node.u_fa.v3; + fa3->fa_type = htonl(NFDIR); + fa3->fa_mode = htonl(0755); + fa3->fa_nlink = htonl(2); + break; + default: + errno = ENOSYS; + return -1; + } + +#ifdef NFS_DEBUG + if (debug) + printf("%s: got fh for %s\n", __func__, path); +#endif + + return 0; } /* @@ -336,50 +589,35 @@ nfs_readdata(struct nfs_iodesc *d, off_t __compactcall int nfs_open(const char *path, struct open_file *f) { - static struct nfs_iodesc nfs_root_node; - struct iodesc *desc; - struct nfs_iodesc *currfd; + struct nfs_iodesc *newfd, *currfd; const char *cp; #ifndef NFS_NOSYMLINK - struct nfs_iodesc *newfd; - struct nfsv2_fattrs *fa; const char *ncp; int c; char namebuf[NFS_MAXPATHLEN + 1]; char linkbuf[NFS_MAXPATHLEN + 1]; int nlinks = 0; #endif - int error; + int error = 0; + n_long fa_type; #ifdef NFS_DEBUG if (debug) - printf("nfs_open: %s\n", path); + printf("%s: %s\n", __func__, path); #endif - if (!rootpath[0]) { - printf("no rootpath, no nfs\n"); - return (ENXIO); - } - if (!(desc = socktodesc(*(int *)(f->f_devdata)))) - return (EINVAL); + if (nfs_mount(*((int *)(f->f_devdata)), rootip, rootpath)) + return errno; - /* Bind to a reserved port. */ - desc->myport = htons(--rpc_port); - desc->destip = rootip; - if ((error = nfs_getrootfh(desc, rootpath, nfs_root_node.fh))) - return (error); - nfs_root_node.iodesc = desc; - -#ifndef NFS_NOSYMLINK - /* Fake up attributes for the root dir. */ - fa = &nfs_root_node.fa; - fa->fa_type = htonl(NFDIR); - fa->fa_mode = htonl(0755); - fa->fa_nlink = htonl(2); + if (nfs_root_node.iodesc == NULL) { + printf("%s: must mount first.\n", __func__); + return ENXIO; + } currfd = &nfs_root_node; newfd = 0; +#ifndef NFS_NOSYMLINK cp = path; while (*cp) { /* @@ -393,7 +631,18 @@ nfs_open(const char *path, struct open_f /* * Check that current node is a directory. */ - if (currfd->fa.fa_type != htonl(NFDIR)) { + switch (currfd->version) { + case NFS_VER2: + fa_type = currfd->u_fa.v2.fa_type; + break; + case NFS_VER3: + fa_type = currfd->u_fa.v3.fa_type; + break; + default: + fa_type = htonl(NFNON); + break; + } + if (fa_type != htonl(NFDIR)) { error = ENOTDIR; goto out; } @@ -402,6 +651,7 @@ nfs_open(const char *path, struct open_f newfd = alloc(sizeof(*newfd)); newfd->iodesc = currfd->iodesc; newfd->off = 0; + newfd->version = currfd->version; /* * Get next component of path name. @@ -427,7 +677,18 @@ nfs_open(const char *path, struct open_f /* * Check for symbolic link */ - if (newfd->fa.fa_type == htonl(NFLNK)) { + switch (newfd->version) { + case NFS_VER2: + fa_type = newfd->u_fa.v2.fa_type; + break; + case NFS_VER3: + fa_type = newfd->u_fa.v3.fa_type; + break; + default: + fa_type = htonl(NFNON); + break; + } + if (fa_type == htonl(NFLNK)) { int link_len, len; error = nfs_readlink(newfd, linkbuf); @@ -443,8 +704,8 @@ nfs_open(const char *path, struct open_f goto out; } - memcpy(&namebuf[link_len], cp, len + 1); - memcpy(namebuf, linkbuf, link_len); + (void)memcpy(&namebuf[link_len], cp, len + 1); + (void)memcpy(namebuf, linkbuf, link_len); /* * If absolute pathname, restart at root. @@ -472,13 +733,12 @@ nfs_open(const char *path, struct open_f error = 0; out: - if (newfd) - dealloc(newfd, sizeof(*newfd)); #else - /* allocate file system specific data structure */ - currfd = alloc(sizeof(*currfd)); - currfd->iodesc = desc; - currfd->off = 0; + /* allocate file system specific data structure */ + currfd = alloc(sizeof(*currfd)); + currfd->iodesc = nfs_root_node.iodesc; + currfd->off = 0; + currfd->version = nfs_root_node.version; cp = path; /* @@ -489,25 +749,25 @@ out: /* XXX: Check for empty path here? */ - error = nfs_lookupfh(&nfs_root_node, cp, strlen(cp), currfd); + error = nfs_lookupfh(&nfs_root_node, cp, strlen(cp), currfd); #endif if (!error) { f->f_fsdata = (void *)currfd; fsmod = "nfs"; - return (0); + return 0; } #ifdef NFS_DEBUG if (debug) - printf("nfs_open: %s lookupfh failed: %s\n", + printf("%s: %s lookupfh failed: %s\n", __func__, path, strerror(error)); #endif -#ifndef NFS_NOSYMLINK if (currfd != &nfs_root_node) -#endif dealloc(currfd, sizeof(*currfd)); + if (newfd) + dealloc(newfd, sizeof(*newfd)); - return (error); + return error; } __compactcall int @@ -517,14 +777,14 @@ nfs_close(struct open_file *f) #ifdef NFS_DEBUG if (debug) - printf("nfs_close: fp=0x%lx\n", (u_long)fp); + printf("%s: fp=%p\n", __func__, fp); #endif if (fp) dealloc(fp, sizeof(struct nfs_iodesc)); f->f_fsdata = (void *)0; - return (0); + return 0; } /* @@ -532,7 +792,6 @@ nfs_close(struct open_file *f) */ __compactcall int nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid) - /* resid: out */ { struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; ssize_t cc; @@ -540,8 +799,7 @@ nfs_read(struct open_file *f, void *buf, #ifdef NFS_DEBUG if (debug) - printf("nfs_read: size=%lu off=%d\n", (u_long)size, - (int)fp->off); + printf("%s: size=%zu off=%" PRIx64 "\n", __func__, size, fp->off); #endif while ((int)size > 0) { #if !defined(LIBSA_NO_TWIDDLE) @@ -552,14 +810,15 @@ nfs_read(struct open_file *f, void *buf, if (cc == -1) { #ifdef NFS_DEBUG if (debug) - printf("nfs_read: read: %s", strerror(errno)); + printf("%s: read: %s\n", __func__, + strerror(errno)); #endif - return (errno); /* XXX - from nfs_readdata */ + return errno; /* XXX - from nfs_readdata */ } if (cc == 0) { #ifdef NFS_DEBUG if (debug) - printf("nfs_read: hit EOF unexpectantly"); + printf("%s: hit EOF unexpectedly\n", __func__); #endif goto ret; } @@ -571,7 +830,7 @@ ret: if (resid) *resid = size; - return (0); + return 0; } /* @@ -579,17 +838,26 @@ ret: */ __compactcall int nfs_write(struct open_file *f, void *buf, size_t size, size_t *resid) - /* resid: out */ { - - return (EROFS); + return EROFS; } __compactcall off_t nfs_seek(struct open_file *f, off_t offset, int where) { struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata; - n_long size = ntohl(d->fa.fa_size); + off_t size; + + switch (d->version) { + case NFS_VER2: + size = ntohl(d->u_fa.v2.fa_size); + break; + case NFS_VER3: + size = getnquad(d->u_fa.v3.fa_size); + break; + default: + return -1; + } switch (where) { case SEEK_SET: @@ -602,10 +870,10 @@ nfs_seek(struct open_file *f, off_t offs d->off = size - offset; break; default: - return (-1); + return -1; } - return (d->off); + return d->off; } /* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */ @@ -618,24 +886,38 @@ nfs_stat(struct open_file *f, struct sta struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; n_long ftype, mode; - ftype = ntohl(fp->fa.fa_type); - mode = ntohl(fp->fa.fa_mode); - mode |= nfs_stat_types[ftype & 7]; + switch (fp->version) { + case NFS_VER2: + ftype = ntohl(fp->u_fa.v2.fa_type); + mode = ntohl(fp->u_fa.v2.fa_mode); + sb->st_nlink = ntohl(fp->u_fa.v2.fa_nlink); + sb->st_uid = ntohl(fp->u_fa.v2.fa_uid); + sb->st_gid = ntohl(fp->u_fa.v2.fa_gid); + sb->st_size = ntohl(fp->u_fa.v2.fa_size); + break; + case NFS_VER3: + ftype = ntohl(fp->u_fa.v3.fa_type); + mode = ntohl(fp->u_fa.v3.fa_mode); + sb->st_nlink = ntohl(fp->u_fa.v3.fa_nlink); + sb->st_uid = ntohl(fp->u_fa.v3.fa_uid); + sb->st_gid = ntohl(fp->u_fa.v3.fa_gid); + sb->st_size = getnquad(fp->u_fa.v3.fa_size); + break; + default: + return -1; + } + mode |= nfs_stat_types[ftype & 7]; sb->st_mode = mode; - sb->st_nlink = ntohl(fp->fa.fa_nlink); - sb->st_uid = ntohl(fp->fa.fa_uid); - sb->st_gid = ntohl(fp->fa.fa_gid); - sb->st_size = ntohl(fp->fa.fa_size); - return (0); + return 0; } #if defined(LIBSA_ENABLE_LS_OP) +#include "ls.h" __compactcall void nfs_ls(struct open_file *f, const char *pattern) { - printf("Currently ls command is unsupported by nfs\n"); - return; + lsunsup("nfs"); } #endif