nfs.c revision 84221
138451Smsmith/* $NetBSD: nfs.c,v 1.2 1998/01/24 12:43:09 drochner Exp $ */ 238451Smsmith 338451Smsmith/*- 438451Smsmith * Copyright (c) 1993 John Brezak 538451Smsmith * All rights reserved. 638451Smsmith * 738451Smsmith * Redistribution and use in source and binary forms, with or without 838451Smsmith * modification, are permitted provided that the following conditions 938451Smsmith * are met: 1038451Smsmith * 1. Redistributions of source code must retain the above copyright 1138451Smsmith * notice, this list of conditions and the following disclaimer. 1238451Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1338451Smsmith * notice, this list of conditions and the following disclaimer in the 1438451Smsmith * documentation and/or other materials provided with the distribution. 1538451Smsmith * 3. The name of the author may not be used to endorse or promote products 1638451Smsmith * derived from this software without specific prior written permission. 1738451Smsmith * 1838451Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 1938451Smsmith * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2038451Smsmith * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2138451Smsmith * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2238451Smsmith * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2338451Smsmith * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2438451Smsmith * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2538451Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2638451Smsmith * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 2738451Smsmith * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2838451Smsmith * POSSIBILITY OF SUCH DAMAGE. 2938451Smsmith */ 3038451Smsmith 3184221Sdillon#include <sys/cdefs.h> 3284221Sdillon__FBSDID("$FreeBSD: head/lib/libstand/nfs.c 84221 2001-09-30 22:28:01Z dillon $"); 3384221Sdillon 3438451Smsmith#include <sys/param.h> 3538451Smsmith#include <sys/time.h> 3638451Smsmith#include <sys/socket.h> 3738451Smsmith#include <sys/stat.h> 3838451Smsmith#include <string.h> 3938451Smsmith 4038451Smsmith#include <netinet/in.h> 4138451Smsmith#include <netinet/in_systm.h> 4238451Smsmith 4338451Smsmith#include "rpcv2.h" 4438451Smsmith#include "nfsv2.h" 4538451Smsmith 4638451Smsmith#include "stand.h" 4738451Smsmith#include "net.h" 4838451Smsmith#include "netif.h" 4938451Smsmith#include "rpc.h" 5038451Smsmith 5138451Smsmith#define NFS_DEBUGxx 5238451Smsmith 5338451Smsmith/* Define our own NFS attributes without NQNFS stuff. */ 5438451Smsmithstruct nfsv2_fattrs { 5538451Smsmith n_long fa_type; 5638451Smsmith n_long fa_mode; 5738451Smsmith n_long fa_nlink; 5838451Smsmith n_long fa_uid; 5938451Smsmith n_long fa_gid; 6038451Smsmith n_long fa_size; 6138451Smsmith n_long fa_blocksize; 6238451Smsmith n_long fa_rdev; 6338451Smsmith n_long fa_blocks; 6438451Smsmith n_long fa_fsid; 6538451Smsmith n_long fa_fileid; 6638451Smsmith struct nfsv2_time fa_atime; 6738451Smsmith struct nfsv2_time fa_mtime; 6838451Smsmith struct nfsv2_time fa_ctime; 6938451Smsmith}; 7038451Smsmith 7138451Smsmith 7238451Smsmithstruct nfs_read_args { 7338451Smsmith u_char fh[NFS_FHSIZE]; 7438451Smsmith n_long off; 7538451Smsmith n_long len; 7638451Smsmith n_long xxx; /* XXX what's this for? */ 7738451Smsmith}; 7838451Smsmith 7938451Smsmith/* Data part of nfs rpc reply (also the largest thing we receive) */ 8038451Smsmith#define NFSREAD_SIZE 1024 8138451Smsmithstruct nfs_read_repl { 8238451Smsmith n_long errno; 8338451Smsmith struct nfsv2_fattrs fa; 8438451Smsmith n_long count; 8538451Smsmith u_char data[NFSREAD_SIZE]; 8638451Smsmith}; 8738451Smsmith 8838451Smsmith#ifndef NFS_NOSYMLINK 8938451Smsmithstruct nfs_readlnk_repl { 9038451Smsmith n_long errno; 9138451Smsmith n_long len; 9238451Smsmith char path[NFS_MAXPATHLEN]; 9338451Smsmith}; 9438451Smsmith#endif 9538451Smsmith 9659853Spsstruct nfs_readdir_args { 9759853Sps u_char fh[NFS_FHSIZE]; 9859853Sps n_long cookie; 9959853Sps n_long count; 10059853Sps}; 10159853Sps 10259853Spsstruct nfs_readdir_data { 10359853Sps n_long fileid; 10459853Sps n_long len; 10559853Sps char name[0]; 10659853Sps}; 10759853Sps 10859853Spsstruct nfs_readdir_off { 10959853Sps n_long cookie; 11059853Sps n_long follows; 11159853Sps}; 11259853Sps 11338451Smsmithstruct nfs_iodesc { 11438451Smsmith struct iodesc *iodesc; 11538451Smsmith off_t off; 11638451Smsmith u_char fh[NFS_FHSIZE]; 11738451Smsmith struct nfsv2_fattrs fa; /* all in network order */ 11838451Smsmith}; 11938451Smsmith 12038451Smsmith/* 12138451Smsmith * XXX interactions with tftp? See nfswrapper.c for a confusing 12238451Smsmith * issue. 12338451Smsmith */ 12439468Smsmithint nfs_open(const char *path, struct open_file *f); 12538451Smsmithstatic int nfs_close(struct open_file *f); 12638451Smsmithstatic int nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid); 12738451Smsmithstatic int nfs_write(struct open_file *f, void *buf, size_t size, size_t *resid); 12838451Smsmithstatic off_t nfs_seek(struct open_file *f, off_t offset, int where); 12938451Smsmithstatic int nfs_stat(struct open_file *f, struct stat *sb); 13059853Spsstatic int nfs_readdir(struct open_file *f, struct dirent *d); 13138451Smsmith 13265496Smsmithstruct nfs_iodesc nfs_root_node; 13359824Sps 13438451Smsmithstruct fs_ops nfs_fsops = { 13559766Sjlemon "nfs", 13659766Sjlemon nfs_open, 13759766Sjlemon nfs_close, 13859766Sjlemon nfs_read, 13959766Sjlemon nfs_write, 14059766Sjlemon nfs_seek, 14159766Sjlemon nfs_stat, 14259853Sps nfs_readdir 14338451Smsmith}; 14438451Smsmith 14538451Smsmith/* 14638451Smsmith * Fetch the root file handle (call mount daemon) 14738451Smsmith * Return zero or error number. 14838451Smsmith */ 14938451Smsmithint 15038451Smsmithnfs_getrootfh(d, path, fhp) 15138451Smsmith register struct iodesc *d; 15238451Smsmith char *path; 15338451Smsmith u_char *fhp; 15438451Smsmith{ 15538451Smsmith register int len; 15638451Smsmith struct args { 15738451Smsmith n_long len; 15838451Smsmith char path[FNAME_SIZE]; 15938451Smsmith } *args; 16038451Smsmith struct repl { 16138451Smsmith n_long errno; 16238451Smsmith u_char fh[NFS_FHSIZE]; 16338451Smsmith } *repl; 16438451Smsmith struct { 16538451Smsmith n_long h[RPC_HEADER_WORDS]; 16638451Smsmith struct args d; 16738451Smsmith } sdata; 16838451Smsmith struct { 16938451Smsmith n_long h[RPC_HEADER_WORDS]; 17038451Smsmith struct repl d; 17138451Smsmith } rdata; 17238451Smsmith size_t cc; 17338451Smsmith 17438451Smsmith#ifdef NFS_DEBUG 17538451Smsmith if (debug) 17638451Smsmith printf("nfs_getrootfh: %s\n", path); 17738451Smsmith#endif 17838451Smsmith 17938451Smsmith args = &sdata.d; 18038451Smsmith repl = &rdata.d; 18138451Smsmith 18238451Smsmith bzero(args, sizeof(*args)); 18338451Smsmith len = strlen(path); 18438451Smsmith if (len > sizeof(args->path)) 18538451Smsmith len = sizeof(args->path); 18638451Smsmith args->len = htonl(len); 18738451Smsmith bcopy(path, args->path, len); 18838451Smsmith len = 4 + roundup(len, 4); 18938451Smsmith 19038451Smsmith cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT, 19138451Smsmith args, len, repl, sizeof(*repl)); 19238451Smsmith if (cc == -1) { 19338451Smsmith /* errno was set by rpc_call */ 19438451Smsmith return (errno); 19538451Smsmith } 19638451Smsmith if (cc < 4) 19738451Smsmith return (EBADRPC); 19838451Smsmith if (repl->errno) 19938451Smsmith return (ntohl(repl->errno)); 20038451Smsmith bcopy(repl->fh, fhp, sizeof(repl->fh)); 20138451Smsmith return (0); 20238451Smsmith} 20338451Smsmith 20438451Smsmith/* 20538451Smsmith * Lookup a file. Store handle and attributes. 20638451Smsmith * Return zero or error number. 20738451Smsmith */ 20838451Smsmithint 20938451Smsmithnfs_lookupfh(d, name, newfd) 21038451Smsmith struct nfs_iodesc *d; 21139468Smsmith const char *name; 21238451Smsmith struct nfs_iodesc *newfd; 21338451Smsmith{ 21438451Smsmith register int len, rlen; 21538451Smsmith struct args { 21638451Smsmith u_char fh[NFS_FHSIZE]; 21738451Smsmith n_long len; 21838451Smsmith char name[FNAME_SIZE]; 21938451Smsmith } *args; 22038451Smsmith struct repl { 22138451Smsmith n_long errno; 22238451Smsmith u_char fh[NFS_FHSIZE]; 22338451Smsmith struct nfsv2_fattrs fa; 22438451Smsmith } *repl; 22538451Smsmith struct { 22638451Smsmith n_long h[RPC_HEADER_WORDS]; 22738451Smsmith struct args d; 22838451Smsmith } sdata; 22938451Smsmith struct { 23038451Smsmith n_long h[RPC_HEADER_WORDS]; 23138451Smsmith struct repl d; 23238451Smsmith } rdata; 23338451Smsmith ssize_t cc; 23438451Smsmith 23538451Smsmith#ifdef NFS_DEBUG 23638451Smsmith if (debug) 23738451Smsmith printf("lookupfh: called\n"); 23838451Smsmith#endif 23938451Smsmith 24038451Smsmith args = &sdata.d; 24138451Smsmith repl = &rdata.d; 24238451Smsmith 24338451Smsmith bzero(args, sizeof(*args)); 24438451Smsmith bcopy(d->fh, args->fh, sizeof(args->fh)); 24538451Smsmith len = strlen(name); 24638451Smsmith if (len > sizeof(args->name)) 24738451Smsmith len = sizeof(args->name); 24838451Smsmith bcopy(name, args->name, len); 24938451Smsmith args->len = htonl(len); 25038451Smsmith len = 4 + roundup(len, 4); 25138451Smsmith len += NFS_FHSIZE; 25238451Smsmith 25338451Smsmith rlen = sizeof(*repl); 25438451Smsmith 25538451Smsmith cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP, 25638451Smsmith args, len, repl, rlen); 25738451Smsmith if (cc == -1) 25838451Smsmith return (errno); /* XXX - from rpc_call */ 25938451Smsmith if (cc < 4) 26038451Smsmith return (EIO); 26138451Smsmith if (repl->errno) { 26238451Smsmith /* saerrno.h now matches NFS error numbers. */ 26338451Smsmith return (ntohl(repl->errno)); 26438451Smsmith } 26538451Smsmith bcopy( repl->fh, &newfd->fh, sizeof(newfd->fh)); 26638451Smsmith bcopy(&repl->fa, &newfd->fa, sizeof(newfd->fa)); 26738451Smsmith return (0); 26838451Smsmith} 26938451Smsmith 27038451Smsmith#ifndef NFS_NOSYMLINK 27138451Smsmith/* 27238451Smsmith * Get the destination of a symbolic link. 27338451Smsmith */ 27438451Smsmithint 27538451Smsmithnfs_readlink(d, buf) 27638451Smsmith struct nfs_iodesc *d; 27738451Smsmith char *buf; 27838451Smsmith{ 27938451Smsmith struct { 28038451Smsmith n_long h[RPC_HEADER_WORDS]; 28138451Smsmith u_char fh[NFS_FHSIZE]; 28238451Smsmith } sdata; 28338451Smsmith struct { 28438451Smsmith n_long h[RPC_HEADER_WORDS]; 28538451Smsmith struct nfs_readlnk_repl d; 28638451Smsmith } rdata; 28738451Smsmith ssize_t cc; 28838451Smsmith 28938451Smsmith#ifdef NFS_DEBUG 29038451Smsmith if (debug) 29138451Smsmith printf("readlink: called\n"); 29238451Smsmith#endif 29338451Smsmith 29438451Smsmith bcopy(d->fh, sdata.fh, NFS_FHSIZE); 29538451Smsmith cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK, 29638451Smsmith sdata.fh, NFS_FHSIZE, 29738451Smsmith &rdata.d, sizeof(rdata.d)); 29838451Smsmith if (cc == -1) 29938451Smsmith return (errno); 30038451Smsmith 30138451Smsmith if (cc < 4) 30238451Smsmith return (EIO); 30338451Smsmith 30438451Smsmith if (rdata.d.errno) 30538451Smsmith return (ntohl(rdata.d.errno)); 30638451Smsmith 30738451Smsmith rdata.d.len = ntohl(rdata.d.len); 30838451Smsmith if (rdata.d.len > NFS_MAXPATHLEN) 30938451Smsmith return (ENAMETOOLONG); 31038451Smsmith 31138451Smsmith bcopy(rdata.d.path, buf, rdata.d.len); 31238451Smsmith buf[rdata.d.len] = 0; 31338451Smsmith return (0); 31438451Smsmith} 31538451Smsmith#endif 31638451Smsmith 31738451Smsmith/* 31838451Smsmith * Read data from a file. 31938451Smsmith * Return transfer count or -1 (and set errno) 32038451Smsmith */ 32138451Smsmithssize_t 32238451Smsmithnfs_readdata(d, off, addr, len) 32338451Smsmith struct nfs_iodesc *d; 32438451Smsmith off_t off; 32538451Smsmith void *addr; 32638451Smsmith size_t len; 32738451Smsmith{ 32838451Smsmith struct nfs_read_args *args; 32938451Smsmith struct nfs_read_repl *repl; 33038451Smsmith struct { 33138451Smsmith n_long h[RPC_HEADER_WORDS]; 33238451Smsmith struct nfs_read_args d; 33338451Smsmith } sdata; 33438451Smsmith struct { 33538451Smsmith n_long h[RPC_HEADER_WORDS]; 33638451Smsmith struct nfs_read_repl d; 33738451Smsmith } rdata; 33838451Smsmith size_t cc; 33938451Smsmith long x; 34038451Smsmith int hlen, rlen; 34138451Smsmith 34238451Smsmith args = &sdata.d; 34338451Smsmith repl = &rdata.d; 34438451Smsmith 34538451Smsmith bcopy(d->fh, args->fh, NFS_FHSIZE); 34638451Smsmith args->off = htonl((n_long)off); 34738451Smsmith if (len > NFSREAD_SIZE) 34838451Smsmith len = NFSREAD_SIZE; 34938451Smsmith args->len = htonl((n_long)len); 35038451Smsmith args->xxx = htonl((n_long)0); 35138451Smsmith hlen = sizeof(*repl) - NFSREAD_SIZE; 35238451Smsmith 35338451Smsmith cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ, 35438451Smsmith args, sizeof(*args), 35538451Smsmith repl, sizeof(*repl)); 35638451Smsmith if (cc == -1) { 35738451Smsmith /* errno was already set by rpc_call */ 35838451Smsmith return (-1); 35938451Smsmith } 36038451Smsmith if (cc < hlen) { 36138451Smsmith errno = EBADRPC; 36238451Smsmith return (-1); 36338451Smsmith } 36438451Smsmith if (repl->errno) { 36538451Smsmith errno = ntohl(repl->errno); 36638451Smsmith return (-1); 36738451Smsmith } 36838451Smsmith rlen = cc - hlen; 36938451Smsmith x = ntohl(repl->count); 37038451Smsmith if (rlen < x) { 37138451Smsmith printf("nfsread: short packet, %d < %ld\n", rlen, x); 37238451Smsmith errno = EBADRPC; 37338451Smsmith return(-1); 37438451Smsmith } 37538451Smsmith bcopy(repl->data, addr, x); 37638451Smsmith return (x); 37738451Smsmith} 37838451Smsmith 37938451Smsmith/* 38038451Smsmith * Open a file. 38138451Smsmith * return zero or error number 38238451Smsmith */ 38338451Smsmithint 38439468Smsmithnfs_open(upath, f) 38539468Smsmith const char *upath; 38638451Smsmith struct open_file *f; 38738451Smsmith{ 38838451Smsmith struct iodesc *desc; 38938451Smsmith struct nfs_iodesc *currfd; 39038451Smsmith#ifndef NFS_NOSYMLINK 39138451Smsmith struct nfs_iodesc *newfd; 39238451Smsmith struct nfsv2_fattrs *fa; 39338451Smsmith register char *cp, *ncp; 39438451Smsmith register int c; 39538451Smsmith char namebuf[NFS_MAXPATHLEN + 1]; 39638451Smsmith char linkbuf[NFS_MAXPATHLEN + 1]; 39738451Smsmith int nlinks = 0; 39838451Smsmith#endif 39938451Smsmith int error; 40039468Smsmith char *path; 40138451Smsmith 40238451Smsmith#ifdef NFS_DEBUG 40338451Smsmith if (debug) 40438451Smsmith printf("nfs_open: %s (rootpath=%s)\n", path, rootpath); 40538451Smsmith#endif 40638451Smsmith if (!rootpath[0]) { 40738451Smsmith printf("no rootpath, no nfs\n"); 40838451Smsmith return (ENXIO); 40938451Smsmith } 41038451Smsmith 41138451Smsmith if (!(desc = socktodesc(*(int *)(f->f_devdata)))) 41238451Smsmith return(EINVAL); 41338451Smsmith 41438451Smsmith /* Bind to a reserved port. */ 41538451Smsmith desc->myport = htons(--rpc_port); 41638451Smsmith desc->destip = rootip; 41738451Smsmith if ((error = nfs_getrootfh(desc, rootpath, nfs_root_node.fh))) 41838451Smsmith return (error); 41938451Smsmith nfs_root_node.iodesc = desc; 42038451Smsmith 42138451Smsmith#ifndef NFS_NOSYMLINK 42238451Smsmith /* Fake up attributes for the root dir. */ 42338451Smsmith fa = &nfs_root_node.fa; 42438451Smsmith fa->fa_type = htonl(NFDIR); 42538451Smsmith fa->fa_mode = htonl(0755); 42638451Smsmith fa->fa_nlink = htonl(2); 42738451Smsmith 42838451Smsmith currfd = &nfs_root_node; 42938451Smsmith newfd = 0; 43038451Smsmith 43139468Smsmith cp = path = strdup(upath); 43239468Smsmith if (path == NULL) { 43339468Smsmith error = ENOMEM; 43439468Smsmith goto out; 43539468Smsmith } 43638451Smsmith while (*cp) { 43738451Smsmith /* 43838451Smsmith * Remove extra separators 43938451Smsmith */ 44038451Smsmith while (*cp == '/') 44138451Smsmith cp++; 44238451Smsmith 44338451Smsmith if (*cp == '\0') 44438451Smsmith break; 44538451Smsmith /* 44638451Smsmith * Check that current node is a directory. 44738451Smsmith */ 44838451Smsmith if (currfd->fa.fa_type != htonl(NFDIR)) { 44938451Smsmith error = ENOTDIR; 45038451Smsmith goto out; 45138451Smsmith } 45238451Smsmith 45338451Smsmith /* allocate file system specific data structure */ 45438451Smsmith newfd = malloc(sizeof(*newfd)); 45538451Smsmith newfd->iodesc = currfd->iodesc; 45638451Smsmith newfd->off = 0; 45738451Smsmith 45838451Smsmith /* 45938451Smsmith * Get next component of path name. 46038451Smsmith */ 46138451Smsmith { 46238451Smsmith register int len = 0; 46338451Smsmith 46438451Smsmith ncp = cp; 46538451Smsmith while ((c = *cp) != '\0' && c != '/') { 46638451Smsmith if (++len > NFS_MAXNAMLEN) { 46738451Smsmith error = ENOENT; 46838451Smsmith goto out; 46938451Smsmith } 47038451Smsmith cp++; 47138451Smsmith } 47238451Smsmith *cp = '\0'; 47338451Smsmith } 47438451Smsmith 47538451Smsmith /* lookup a file handle */ 47638451Smsmith error = nfs_lookupfh(currfd, ncp, newfd); 47738451Smsmith *cp = c; 47838451Smsmith if (error) 47938451Smsmith goto out; 48038451Smsmith 48138451Smsmith /* 48238451Smsmith * Check for symbolic link 48338451Smsmith */ 48438451Smsmith if (newfd->fa.fa_type == htonl(NFLNK)) { 48538451Smsmith int link_len, len; 48638451Smsmith 48738451Smsmith error = nfs_readlink(newfd, linkbuf); 48838451Smsmith if (error) 48938451Smsmith goto out; 49038451Smsmith 49138451Smsmith link_len = strlen(linkbuf); 49238451Smsmith len = strlen(cp); 49338451Smsmith 49438451Smsmith if (link_len + len > MAXPATHLEN 49538451Smsmith || ++nlinks > MAXSYMLINKS) { 49638451Smsmith error = ENOENT; 49738451Smsmith goto out; 49838451Smsmith } 49938451Smsmith 50038451Smsmith bcopy(cp, &namebuf[link_len], len + 1); 50138451Smsmith bcopy(linkbuf, namebuf, link_len); 50238451Smsmith 50338451Smsmith /* 50438451Smsmith * If absolute pathname, restart at root. 50538451Smsmith * If relative pathname, restart at parent directory. 50638451Smsmith */ 50738451Smsmith cp = namebuf; 50838451Smsmith if (*cp == '/') { 50938451Smsmith if (currfd != &nfs_root_node) 51038451Smsmith free(currfd); 51138451Smsmith currfd = &nfs_root_node; 51238451Smsmith } 51338451Smsmith 51438451Smsmith free(newfd); 51538451Smsmith newfd = 0; 51638451Smsmith 51738451Smsmith continue; 51838451Smsmith } 51938451Smsmith 52038451Smsmith if (currfd != &nfs_root_node) 52138451Smsmith free(currfd); 52238451Smsmith currfd = newfd; 52338451Smsmith newfd = 0; 52438451Smsmith } 52538451Smsmith 52638451Smsmith error = 0; 52738451Smsmith 52838451Smsmithout: 52938451Smsmith if (newfd) 53038451Smsmith free(newfd); 53139468Smsmith if (path) 53239468Smsmith free(path); 53338451Smsmith#else 53438451Smsmith /* allocate file system specific data structure */ 53538451Smsmith currfd = malloc(sizeof(*currfd)); 53638451Smsmith currfd->iodesc = desc; 53738451Smsmith currfd->off = 0; 53838451Smsmith 53939468Smsmith error = nfs_lookupfh(&nfs_root_node, upath, currfd); 54038451Smsmith#endif 54138451Smsmith if (!error) { 54238451Smsmith f->f_fsdata = (void *)currfd; 54338451Smsmith return (0); 54438451Smsmith } 54538451Smsmith 54638451Smsmith#ifdef NFS_DEBUG 54738451Smsmith if (debug) 54838451Smsmith printf("nfs_open: %s lookupfh failed: %s\n", 54938451Smsmith path, strerror(error)); 55038451Smsmith#endif 55138451Smsmith#ifndef NFS_NOSYMLINK 55238451Smsmith if (currfd != &nfs_root_node) 55338451Smsmith#endif 55438451Smsmith free(currfd); 55538451Smsmith 55638451Smsmith return (error); 55738451Smsmith} 55838451Smsmith 55938451Smsmithint 56038451Smsmithnfs_close(f) 56138451Smsmith struct open_file *f; 56238451Smsmith{ 56338451Smsmith register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 56438451Smsmith 56538451Smsmith#ifdef NFS_DEBUG 56638451Smsmith if (debug) 56738451Smsmith printf("nfs_close: fp=0x%lx\n", (u_long)fp); 56838451Smsmith#endif 56938451Smsmith 57059824Sps if (fp != &nfs_root_node && fp) 57138451Smsmith free(fp); 57238451Smsmith f->f_fsdata = (void *)0; 57338451Smsmith 57438451Smsmith return (0); 57538451Smsmith} 57638451Smsmith 57738451Smsmith/* 57838451Smsmith * read a portion of a file 57938451Smsmith */ 58038451Smsmithint 58138451Smsmithnfs_read(f, buf, size, resid) 58238451Smsmith struct open_file *f; 58338451Smsmith void *buf; 58438451Smsmith size_t size; 58538451Smsmith size_t *resid; /* out */ 58638451Smsmith{ 58738451Smsmith register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 58838451Smsmith register ssize_t cc; 58938451Smsmith register char *addr = buf; 59038451Smsmith 59138451Smsmith#ifdef NFS_DEBUG 59238451Smsmith if (debug) 59338451Smsmith printf("nfs_read: size=%lu off=%d\n", (u_long)size, 59438451Smsmith (int)fp->off); 59538451Smsmith#endif 59638451Smsmith while ((int)size > 0) { 59738451Smsmith twiddle(); 59838451Smsmith cc = nfs_readdata(fp, fp->off, (void *)addr, size); 59938451Smsmith /* XXX maybe should retry on certain errors */ 60038451Smsmith if (cc == -1) { 60138451Smsmith#ifdef NFS_DEBUG 60238451Smsmith if (debug) 60338451Smsmith printf("nfs_read: read: %s", strerror(errno)); 60438451Smsmith#endif 60538451Smsmith return (errno); /* XXX - from nfs_readdata */ 60638451Smsmith } 60738451Smsmith if (cc == 0) { 60838451Smsmith#ifdef NFS_DEBUG 60938451Smsmith if (debug) 61038451Smsmith printf("nfs_read: hit EOF unexpectantly"); 61138451Smsmith#endif 61238451Smsmith goto ret; 61338451Smsmith } 61438451Smsmith fp->off += cc; 61538451Smsmith addr += cc; 61638451Smsmith size -= cc; 61738451Smsmith } 61838451Smsmithret: 61938451Smsmith if (resid) 62038451Smsmith *resid = size; 62138451Smsmith 62238451Smsmith return (0); 62338451Smsmith} 62438451Smsmith 62538451Smsmith/* 62638451Smsmith * Not implemented. 62738451Smsmith */ 62838451Smsmithint 62938451Smsmithnfs_write(f, buf, size, resid) 63038451Smsmith struct open_file *f; 63138451Smsmith void *buf; 63238451Smsmith size_t size; 63338451Smsmith size_t *resid; /* out */ 63438451Smsmith{ 63538451Smsmith return (EROFS); 63638451Smsmith} 63738451Smsmith 63838451Smsmithoff_t 63938451Smsmithnfs_seek(f, offset, where) 64038451Smsmith struct open_file *f; 64138451Smsmith off_t offset; 64238451Smsmith int where; 64338451Smsmith{ 64438451Smsmith register struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata; 64538451Smsmith n_long size = ntohl(d->fa.fa_size); 64638451Smsmith 64738451Smsmith switch (where) { 64838451Smsmith case SEEK_SET: 64938451Smsmith d->off = offset; 65038451Smsmith break; 65138451Smsmith case SEEK_CUR: 65238451Smsmith d->off += offset; 65338451Smsmith break; 65438451Smsmith case SEEK_END: 65538451Smsmith d->off = size - offset; 65638451Smsmith break; 65738451Smsmith default: 65838451Smsmith return (-1); 65938451Smsmith } 66038451Smsmith 66138451Smsmith return (d->off); 66238451Smsmith} 66338451Smsmith 66438451Smsmith/* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */ 66538451Smsmithint nfs_stat_types[8] = { 66638451Smsmith 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0 }; 66738451Smsmith 66838451Smsmithint 66938451Smsmithnfs_stat(f, sb) 67038451Smsmith struct open_file *f; 67138451Smsmith struct stat *sb; 67238451Smsmith{ 67338451Smsmith struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 67438451Smsmith register n_long ftype, mode; 67538451Smsmith 67638451Smsmith ftype = ntohl(fp->fa.fa_type); 67738451Smsmith mode = ntohl(fp->fa.fa_mode); 67838451Smsmith mode |= nfs_stat_types[ftype & 7]; 67938451Smsmith 68038451Smsmith sb->st_mode = mode; 68138451Smsmith sb->st_nlink = ntohl(fp->fa.fa_nlink); 68238451Smsmith sb->st_uid = ntohl(fp->fa.fa_uid); 68338451Smsmith sb->st_gid = ntohl(fp->fa.fa_gid); 68438451Smsmith sb->st_size = ntohl(fp->fa.fa_size); 68538451Smsmith 68638451Smsmith return (0); 68738451Smsmith} 68859853Sps 68959853Spsstatic int 69059853Spsnfs_readdir(struct open_file *f, struct dirent *d) 69159853Sps{ 69259853Sps register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 69359853Sps struct nfs_readdir_args *args; 69459853Sps struct nfs_readdir_data *rd; 69559853Sps struct nfs_readdir_off *roff = NULL; 69659853Sps static char *buf; 69759853Sps static n_long cookie = 0; 69859853Sps size_t cc; 69959853Sps n_long eof; 70059853Sps 70159853Sps struct { 70259853Sps n_long h[RPC_HEADER_WORDS]; 70359853Sps struct nfs_readdir_args d; 70459853Sps } sdata; 70559853Sps static struct { 70659853Sps n_long h[RPC_HEADER_WORDS]; 70759853Sps u_char d[NFS_READDIRSIZE]; 70859853Sps } rdata; 70959853Sps 71059853Sps if (cookie == 0) { 71159853Sps refill: 71259853Sps args = &sdata.d; 71359853Sps bzero(args, sizeof(*args)); 71459853Sps 71559853Sps bcopy(fp->fh, args->fh, NFS_FHSIZE); 71659853Sps args->cookie = htonl(cookie); 71759853Sps args->count = htonl(NFS_READDIRSIZE); 71859853Sps 71959853Sps cc = rpc_call(fp->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READDIR, 72059853Sps args, sizeof(*args), 72159853Sps rdata.d, sizeof(rdata.d)); 72259853Sps buf = rdata.d; 72359853Sps roff = (struct nfs_readdir_off *)buf; 72459853Sps if (ntohl(roff->cookie) != 0) 72559853Sps return 1; 72659853Sps } 72759853Sps roff = (struct nfs_readdir_off *)buf; 72859853Sps 72959853Sps if (ntohl(roff->follows) == 0) { 73059853Sps eof = ntohl((roff+1)->cookie); 73159853Sps if (eof) { 73259853Sps cookie = 0; 73359853Sps return 1; 73459853Sps } 73559853Sps goto refill; 73659853Sps } 73759853Sps 73859853Sps buf += sizeof(struct nfs_readdir_off); 73959853Sps rd = (struct nfs_readdir_data *)buf; 74059853Sps d->d_namlen = ntohl(rd->len); 74159853Sps bcopy(rd->name, d->d_name, d->d_namlen); 74259853Sps d->d_name[d->d_namlen] = '\0'; 74359853Sps 74459853Sps buf += (sizeof(struct nfs_readdir_data) + roundup(htonl(rd->len),4)); 74559853Sps roff = (struct nfs_readdir_off *)buf; 74659853Sps cookie = ntohl(roff->cookie); 74759853Sps return 0; 74859853Sps} 749