nfs.c revision 38451
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 3138451Smsmith#include <sys/param.h> 3238451Smsmith#include <sys/time.h> 3338451Smsmith#include <sys/socket.h> 3438451Smsmith#include <sys/stat.h> 3538451Smsmith#include <string.h> 3638451Smsmith 3738451Smsmith#include <netinet/in.h> 3838451Smsmith#include <netinet/in_systm.h> 3938451Smsmith 4038451Smsmith#include "rpcv2.h" 4138451Smsmith#include "nfsv2.h" 4238451Smsmith 4338451Smsmith#include "stand.h" 4438451Smsmith#include "net.h" 4538451Smsmith#include "netif.h" 4638451Smsmith#include "nfs.h" 4738451Smsmith#include "rpc.h" 4838451Smsmith 4938451Smsmith#define NFS_DEBUGxx 5038451Smsmith 5138451Smsmith/* Define our own NFS attributes without NQNFS stuff. */ 5238451Smsmithstruct nfsv2_fattrs { 5338451Smsmith n_long fa_type; 5438451Smsmith n_long fa_mode; 5538451Smsmith n_long fa_nlink; 5638451Smsmith n_long fa_uid; 5738451Smsmith n_long fa_gid; 5838451Smsmith n_long fa_size; 5938451Smsmith n_long fa_blocksize; 6038451Smsmith n_long fa_rdev; 6138451Smsmith n_long fa_blocks; 6238451Smsmith n_long fa_fsid; 6338451Smsmith n_long fa_fileid; 6438451Smsmith struct nfsv2_time fa_atime; 6538451Smsmith struct nfsv2_time fa_mtime; 6638451Smsmith struct nfsv2_time fa_ctime; 6738451Smsmith}; 6838451Smsmith 6938451Smsmith 7038451Smsmithstruct nfs_read_args { 7138451Smsmith u_char fh[NFS_FHSIZE]; 7238451Smsmith n_long off; 7338451Smsmith n_long len; 7438451Smsmith n_long xxx; /* XXX what's this for? */ 7538451Smsmith}; 7638451Smsmith 7738451Smsmith/* Data part of nfs rpc reply (also the largest thing we receive) */ 7838451Smsmith#define NFSREAD_SIZE 1024 7938451Smsmithstruct nfs_read_repl { 8038451Smsmith n_long errno; 8138451Smsmith struct nfsv2_fattrs fa; 8238451Smsmith n_long count; 8338451Smsmith u_char data[NFSREAD_SIZE]; 8438451Smsmith}; 8538451Smsmith 8638451Smsmith#ifndef NFS_NOSYMLINK 8738451Smsmithstruct nfs_readlnk_repl { 8838451Smsmith n_long errno; 8938451Smsmith n_long len; 9038451Smsmith char path[NFS_MAXPATHLEN]; 9138451Smsmith}; 9238451Smsmith#endif 9338451Smsmith 9438451Smsmithstruct nfs_iodesc { 9538451Smsmith struct iodesc *iodesc; 9638451Smsmith off_t off; 9738451Smsmith u_char fh[NFS_FHSIZE]; 9838451Smsmith struct nfsv2_fattrs fa; /* all in network order */ 9938451Smsmith}; 10038451Smsmith 10138451Smsmith/* 10238451Smsmith * XXX interactions with tftp? See nfswrapper.c for a confusing 10338451Smsmith * issue. 10438451Smsmith */ 10538451Smsmithint nfs_open(char *path, struct open_file *f); 10638451Smsmithstatic int nfs_close(struct open_file *f); 10738451Smsmithstatic int nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid); 10838451Smsmithstatic int nfs_write(struct open_file *f, void *buf, size_t size, size_t *resid); 10938451Smsmithstatic off_t nfs_seek(struct open_file *f, off_t offset, int where); 11038451Smsmithstatic int nfs_stat(struct open_file *f, struct stat *sb); 11138451Smsmith 11238451Smsmithstruct fs_ops nfs_fsops = { 11338451Smsmith "nfs", nfs_open, nfs_close, nfs_read, nfs_write, nfs_seek, nfs_stat 11438451Smsmith}; 11538451Smsmith 11638451Smsmith 11738451Smsmith/* 11838451Smsmith * Fetch the root file handle (call mount daemon) 11938451Smsmith * Return zero or error number. 12038451Smsmith */ 12138451Smsmithint 12238451Smsmithnfs_getrootfh(d, path, fhp) 12338451Smsmith register struct iodesc *d; 12438451Smsmith char *path; 12538451Smsmith u_char *fhp; 12638451Smsmith{ 12738451Smsmith register int len; 12838451Smsmith struct args { 12938451Smsmith n_long len; 13038451Smsmith char path[FNAME_SIZE]; 13138451Smsmith } *args; 13238451Smsmith struct repl { 13338451Smsmith n_long errno; 13438451Smsmith u_char fh[NFS_FHSIZE]; 13538451Smsmith } *repl; 13638451Smsmith struct { 13738451Smsmith n_long h[RPC_HEADER_WORDS]; 13838451Smsmith struct args d; 13938451Smsmith } sdata; 14038451Smsmith struct { 14138451Smsmith n_long h[RPC_HEADER_WORDS]; 14238451Smsmith struct repl d; 14338451Smsmith } rdata; 14438451Smsmith size_t cc; 14538451Smsmith 14638451Smsmith#ifdef NFS_DEBUG 14738451Smsmith if (debug) 14838451Smsmith printf("nfs_getrootfh: %s\n", path); 14938451Smsmith#endif 15038451Smsmith 15138451Smsmith args = &sdata.d; 15238451Smsmith repl = &rdata.d; 15338451Smsmith 15438451Smsmith bzero(args, sizeof(*args)); 15538451Smsmith len = strlen(path); 15638451Smsmith if (len > sizeof(args->path)) 15738451Smsmith len = sizeof(args->path); 15838451Smsmith args->len = htonl(len); 15938451Smsmith bcopy(path, args->path, len); 16038451Smsmith len = 4 + roundup(len, 4); 16138451Smsmith 16238451Smsmith cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT, 16338451Smsmith args, len, repl, sizeof(*repl)); 16438451Smsmith if (cc == -1) { 16538451Smsmith /* errno was set by rpc_call */ 16638451Smsmith return (errno); 16738451Smsmith } 16838451Smsmith if (cc < 4) 16938451Smsmith return (EBADRPC); 17038451Smsmith if (repl->errno) 17138451Smsmith return (ntohl(repl->errno)); 17238451Smsmith bcopy(repl->fh, fhp, sizeof(repl->fh)); 17338451Smsmith return (0); 17438451Smsmith} 17538451Smsmith 17638451Smsmith/* 17738451Smsmith * Lookup a file. Store handle and attributes. 17838451Smsmith * Return zero or error number. 17938451Smsmith */ 18038451Smsmithint 18138451Smsmithnfs_lookupfh(d, name, newfd) 18238451Smsmith struct nfs_iodesc *d; 18338451Smsmith char *name; 18438451Smsmith struct nfs_iodesc *newfd; 18538451Smsmith{ 18638451Smsmith register int len, rlen; 18738451Smsmith struct args { 18838451Smsmith u_char fh[NFS_FHSIZE]; 18938451Smsmith n_long len; 19038451Smsmith char name[FNAME_SIZE]; 19138451Smsmith } *args; 19238451Smsmith struct repl { 19338451Smsmith n_long errno; 19438451Smsmith u_char fh[NFS_FHSIZE]; 19538451Smsmith struct nfsv2_fattrs fa; 19638451Smsmith } *repl; 19738451Smsmith struct { 19838451Smsmith n_long h[RPC_HEADER_WORDS]; 19938451Smsmith struct args d; 20038451Smsmith } sdata; 20138451Smsmith struct { 20238451Smsmith n_long h[RPC_HEADER_WORDS]; 20338451Smsmith struct repl d; 20438451Smsmith } rdata; 20538451Smsmith ssize_t cc; 20638451Smsmith 20738451Smsmith#ifdef NFS_DEBUG 20838451Smsmith if (debug) 20938451Smsmith printf("lookupfh: called\n"); 21038451Smsmith#endif 21138451Smsmith 21238451Smsmith args = &sdata.d; 21338451Smsmith repl = &rdata.d; 21438451Smsmith 21538451Smsmith bzero(args, sizeof(*args)); 21638451Smsmith bcopy(d->fh, args->fh, sizeof(args->fh)); 21738451Smsmith len = strlen(name); 21838451Smsmith if (len > sizeof(args->name)) 21938451Smsmith len = sizeof(args->name); 22038451Smsmith bcopy(name, args->name, len); 22138451Smsmith args->len = htonl(len); 22238451Smsmith len = 4 + roundup(len, 4); 22338451Smsmith len += NFS_FHSIZE; 22438451Smsmith 22538451Smsmith rlen = sizeof(*repl); 22638451Smsmith 22738451Smsmith cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP, 22838451Smsmith args, len, repl, rlen); 22938451Smsmith if (cc == -1) 23038451Smsmith return (errno); /* XXX - from rpc_call */ 23138451Smsmith if (cc < 4) 23238451Smsmith return (EIO); 23338451Smsmith if (repl->errno) { 23438451Smsmith /* saerrno.h now matches NFS error numbers. */ 23538451Smsmith return (ntohl(repl->errno)); 23638451Smsmith } 23738451Smsmith bcopy( repl->fh, &newfd->fh, sizeof(newfd->fh)); 23838451Smsmith bcopy(&repl->fa, &newfd->fa, sizeof(newfd->fa)); 23938451Smsmith return (0); 24038451Smsmith} 24138451Smsmith 24238451Smsmith#ifndef NFS_NOSYMLINK 24338451Smsmith/* 24438451Smsmith * Get the destination of a symbolic link. 24538451Smsmith */ 24638451Smsmithint 24738451Smsmithnfs_readlink(d, buf) 24838451Smsmith struct nfs_iodesc *d; 24938451Smsmith char *buf; 25038451Smsmith{ 25138451Smsmith struct { 25238451Smsmith n_long h[RPC_HEADER_WORDS]; 25338451Smsmith u_char fh[NFS_FHSIZE]; 25438451Smsmith } sdata; 25538451Smsmith struct { 25638451Smsmith n_long h[RPC_HEADER_WORDS]; 25738451Smsmith struct nfs_readlnk_repl d; 25838451Smsmith } rdata; 25938451Smsmith ssize_t cc; 26038451Smsmith 26138451Smsmith#ifdef NFS_DEBUG 26238451Smsmith if (debug) 26338451Smsmith printf("readlink: called\n"); 26438451Smsmith#endif 26538451Smsmith 26638451Smsmith bcopy(d->fh, sdata.fh, NFS_FHSIZE); 26738451Smsmith cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK, 26838451Smsmith sdata.fh, NFS_FHSIZE, 26938451Smsmith &rdata.d, sizeof(rdata.d)); 27038451Smsmith if (cc == -1) 27138451Smsmith return (errno); 27238451Smsmith 27338451Smsmith if (cc < 4) 27438451Smsmith return (EIO); 27538451Smsmith 27638451Smsmith if (rdata.d.errno) 27738451Smsmith return (ntohl(rdata.d.errno)); 27838451Smsmith 27938451Smsmith rdata.d.len = ntohl(rdata.d.len); 28038451Smsmith if (rdata.d.len > NFS_MAXPATHLEN) 28138451Smsmith return (ENAMETOOLONG); 28238451Smsmith 28338451Smsmith bcopy(rdata.d.path, buf, rdata.d.len); 28438451Smsmith buf[rdata.d.len] = 0; 28538451Smsmith return (0); 28638451Smsmith} 28738451Smsmith#endif 28838451Smsmith 28938451Smsmith/* 29038451Smsmith * Read data from a file. 29138451Smsmith * Return transfer count or -1 (and set errno) 29238451Smsmith */ 29338451Smsmithssize_t 29438451Smsmithnfs_readdata(d, off, addr, len) 29538451Smsmith struct nfs_iodesc *d; 29638451Smsmith off_t off; 29738451Smsmith void *addr; 29838451Smsmith size_t len; 29938451Smsmith{ 30038451Smsmith struct nfs_read_args *args; 30138451Smsmith struct nfs_read_repl *repl; 30238451Smsmith struct { 30338451Smsmith n_long h[RPC_HEADER_WORDS]; 30438451Smsmith struct nfs_read_args d; 30538451Smsmith } sdata; 30638451Smsmith struct { 30738451Smsmith n_long h[RPC_HEADER_WORDS]; 30838451Smsmith struct nfs_read_repl d; 30938451Smsmith } rdata; 31038451Smsmith size_t cc; 31138451Smsmith long x; 31238451Smsmith int hlen, rlen; 31338451Smsmith 31438451Smsmith args = &sdata.d; 31538451Smsmith repl = &rdata.d; 31638451Smsmith 31738451Smsmith bcopy(d->fh, args->fh, NFS_FHSIZE); 31838451Smsmith args->off = htonl((n_long)off); 31938451Smsmith if (len > NFSREAD_SIZE) 32038451Smsmith len = NFSREAD_SIZE; 32138451Smsmith args->len = htonl((n_long)len); 32238451Smsmith args->xxx = htonl((n_long)0); 32338451Smsmith hlen = sizeof(*repl) - NFSREAD_SIZE; 32438451Smsmith 32538451Smsmith cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ, 32638451Smsmith args, sizeof(*args), 32738451Smsmith repl, sizeof(*repl)); 32838451Smsmith if (cc == -1) { 32938451Smsmith /* errno was already set by rpc_call */ 33038451Smsmith return (-1); 33138451Smsmith } 33238451Smsmith if (cc < hlen) { 33338451Smsmith errno = EBADRPC; 33438451Smsmith return (-1); 33538451Smsmith } 33638451Smsmith if (repl->errno) { 33738451Smsmith errno = ntohl(repl->errno); 33838451Smsmith return (-1); 33938451Smsmith } 34038451Smsmith rlen = cc - hlen; 34138451Smsmith x = ntohl(repl->count); 34238451Smsmith if (rlen < x) { 34338451Smsmith printf("nfsread: short packet, %d < %ld\n", rlen, x); 34438451Smsmith errno = EBADRPC; 34538451Smsmith return(-1); 34638451Smsmith } 34738451Smsmith bcopy(repl->data, addr, x); 34838451Smsmith return (x); 34938451Smsmith} 35038451Smsmith 35138451Smsmith/* 35238451Smsmith * Open a file. 35338451Smsmith * return zero or error number 35438451Smsmith */ 35538451Smsmithint 35638451Smsmithnfs_open(path, f) 35738451Smsmith char *path; 35838451Smsmith struct open_file *f; 35938451Smsmith{ 36038451Smsmith static struct nfs_iodesc nfs_root_node; 36138451Smsmith struct iodesc *desc; 36238451Smsmith struct nfs_iodesc *currfd; 36338451Smsmith#ifndef NFS_NOSYMLINK 36438451Smsmith struct nfs_iodesc *newfd; 36538451Smsmith struct nfsv2_fattrs *fa; 36638451Smsmith register char *cp, *ncp; 36738451Smsmith register int c; 36838451Smsmith char namebuf[NFS_MAXPATHLEN + 1]; 36938451Smsmith char linkbuf[NFS_MAXPATHLEN + 1]; 37038451Smsmith int nlinks = 0; 37138451Smsmith#endif 37238451Smsmith int error; 37338451Smsmith 37438451Smsmith#ifdef NFS_DEBUG 37538451Smsmith if (debug) 37638451Smsmith printf("nfs_open: %s (rootpath=%s)\n", path, rootpath); 37738451Smsmith#endif 37838451Smsmith if (!rootpath[0]) { 37938451Smsmith printf("no rootpath, no nfs\n"); 38038451Smsmith return (ENXIO); 38138451Smsmith } 38238451Smsmith 38338451Smsmith if (!(desc = socktodesc(*(int *)(f->f_devdata)))) 38438451Smsmith return(EINVAL); 38538451Smsmith 38638451Smsmith /* Bind to a reserved port. */ 38738451Smsmith desc->myport = htons(--rpc_port); 38838451Smsmith desc->destip = rootip; 38938451Smsmith if ((error = nfs_getrootfh(desc, rootpath, nfs_root_node.fh))) 39038451Smsmith return (error); 39138451Smsmith nfs_root_node.iodesc = desc; 39238451Smsmith 39338451Smsmith#ifndef NFS_NOSYMLINK 39438451Smsmith /* Fake up attributes for the root dir. */ 39538451Smsmith fa = &nfs_root_node.fa; 39638451Smsmith fa->fa_type = htonl(NFDIR); 39738451Smsmith fa->fa_mode = htonl(0755); 39838451Smsmith fa->fa_nlink = htonl(2); 39938451Smsmith 40038451Smsmith currfd = &nfs_root_node; 40138451Smsmith newfd = 0; 40238451Smsmith 40338451Smsmith cp = path; 40438451Smsmith while (*cp) { 40538451Smsmith /* 40638451Smsmith * Remove extra separators 40738451Smsmith */ 40838451Smsmith while (*cp == '/') 40938451Smsmith cp++; 41038451Smsmith 41138451Smsmith if (*cp == '\0') 41238451Smsmith break; 41338451Smsmith /* 41438451Smsmith * Check that current node is a directory. 41538451Smsmith */ 41638451Smsmith if (currfd->fa.fa_type != htonl(NFDIR)) { 41738451Smsmith error = ENOTDIR; 41838451Smsmith goto out; 41938451Smsmith } 42038451Smsmith 42138451Smsmith /* allocate file system specific data structure */ 42238451Smsmith newfd = malloc(sizeof(*newfd)); 42338451Smsmith newfd->iodesc = currfd->iodesc; 42438451Smsmith newfd->off = 0; 42538451Smsmith 42638451Smsmith /* 42738451Smsmith * Get next component of path name. 42838451Smsmith */ 42938451Smsmith { 43038451Smsmith register int len = 0; 43138451Smsmith 43238451Smsmith ncp = cp; 43338451Smsmith while ((c = *cp) != '\0' && c != '/') { 43438451Smsmith if (++len > NFS_MAXNAMLEN) { 43538451Smsmith error = ENOENT; 43638451Smsmith goto out; 43738451Smsmith } 43838451Smsmith cp++; 43938451Smsmith } 44038451Smsmith *cp = '\0'; 44138451Smsmith } 44238451Smsmith 44338451Smsmith /* lookup a file handle */ 44438451Smsmith error = nfs_lookupfh(currfd, ncp, newfd); 44538451Smsmith *cp = c; 44638451Smsmith if (error) 44738451Smsmith goto out; 44838451Smsmith 44938451Smsmith /* 45038451Smsmith * Check for symbolic link 45138451Smsmith */ 45238451Smsmith if (newfd->fa.fa_type == htonl(NFLNK)) { 45338451Smsmith int link_len, len; 45438451Smsmith 45538451Smsmith error = nfs_readlink(newfd, linkbuf); 45638451Smsmith if (error) 45738451Smsmith goto out; 45838451Smsmith 45938451Smsmith link_len = strlen(linkbuf); 46038451Smsmith len = strlen(cp); 46138451Smsmith 46238451Smsmith if (link_len + len > MAXPATHLEN 46338451Smsmith || ++nlinks > MAXSYMLINKS) { 46438451Smsmith error = ENOENT; 46538451Smsmith goto out; 46638451Smsmith } 46738451Smsmith 46838451Smsmith bcopy(cp, &namebuf[link_len], len + 1); 46938451Smsmith bcopy(linkbuf, namebuf, link_len); 47038451Smsmith 47138451Smsmith /* 47238451Smsmith * If absolute pathname, restart at root. 47338451Smsmith * If relative pathname, restart at parent directory. 47438451Smsmith */ 47538451Smsmith cp = namebuf; 47638451Smsmith if (*cp == '/') { 47738451Smsmith if (currfd != &nfs_root_node) 47838451Smsmith free(currfd); 47938451Smsmith currfd = &nfs_root_node; 48038451Smsmith } 48138451Smsmith 48238451Smsmith free(newfd); 48338451Smsmith newfd = 0; 48438451Smsmith 48538451Smsmith continue; 48638451Smsmith } 48738451Smsmith 48838451Smsmith if (currfd != &nfs_root_node) 48938451Smsmith free(currfd); 49038451Smsmith currfd = newfd; 49138451Smsmith newfd = 0; 49238451Smsmith } 49338451Smsmith 49438451Smsmith error = 0; 49538451Smsmith 49638451Smsmithout: 49738451Smsmith if (newfd) 49838451Smsmith free(newfd); 49938451Smsmith#else 50038451Smsmith /* allocate file system specific data structure */ 50138451Smsmith currfd = malloc(sizeof(*currfd)); 50238451Smsmith currfd->iodesc = desc; 50338451Smsmith currfd->off = 0; 50438451Smsmith 50538451Smsmith error = nfs_lookupfh(&nfs_root_node, path, currfd); 50638451Smsmith#endif 50738451Smsmith if (!error) { 50838451Smsmith f->f_fsdata = (void *)currfd; 50938451Smsmith return (0); 51038451Smsmith } 51138451Smsmith 51238451Smsmith#ifdef NFS_DEBUG 51338451Smsmith if (debug) 51438451Smsmith printf("nfs_open: %s lookupfh failed: %s\n", 51538451Smsmith path, strerror(error)); 51638451Smsmith#endif 51738451Smsmith#ifndef NFS_NOSYMLINK 51838451Smsmith if (currfd != &nfs_root_node) 51938451Smsmith#endif 52038451Smsmith free(currfd); 52138451Smsmith 52238451Smsmith return (error); 52338451Smsmith} 52438451Smsmith 52538451Smsmithint 52638451Smsmithnfs_close(f) 52738451Smsmith struct open_file *f; 52838451Smsmith{ 52938451Smsmith register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 53038451Smsmith 53138451Smsmith#ifdef NFS_DEBUG 53238451Smsmith if (debug) 53338451Smsmith printf("nfs_close: fp=0x%lx\n", (u_long)fp); 53438451Smsmith#endif 53538451Smsmith 53638451Smsmith if (fp) 53738451Smsmith free(fp); 53838451Smsmith f->f_fsdata = (void *)0; 53938451Smsmith 54038451Smsmith return (0); 54138451Smsmith} 54238451Smsmith 54338451Smsmith/* 54438451Smsmith * read a portion of a file 54538451Smsmith */ 54638451Smsmithint 54738451Smsmithnfs_read(f, buf, size, resid) 54838451Smsmith struct open_file *f; 54938451Smsmith void *buf; 55038451Smsmith size_t size; 55138451Smsmith size_t *resid; /* out */ 55238451Smsmith{ 55338451Smsmith register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 55438451Smsmith register ssize_t cc; 55538451Smsmith register char *addr = buf; 55638451Smsmith 55738451Smsmith#ifdef NFS_DEBUG 55838451Smsmith if (debug) 55938451Smsmith printf("nfs_read: size=%lu off=%d\n", (u_long)size, 56038451Smsmith (int)fp->off); 56138451Smsmith#endif 56238451Smsmith while ((int)size > 0) { 56338451Smsmith twiddle(); 56438451Smsmith cc = nfs_readdata(fp, fp->off, (void *)addr, size); 56538451Smsmith /* XXX maybe should retry on certain errors */ 56638451Smsmith if (cc == -1) { 56738451Smsmith#ifdef NFS_DEBUG 56838451Smsmith if (debug) 56938451Smsmith printf("nfs_read: read: %s", strerror(errno)); 57038451Smsmith#endif 57138451Smsmith return (errno); /* XXX - from nfs_readdata */ 57238451Smsmith } 57338451Smsmith if (cc == 0) { 57438451Smsmith#ifdef NFS_DEBUG 57538451Smsmith if (debug) 57638451Smsmith printf("nfs_read: hit EOF unexpectantly"); 57738451Smsmith#endif 57838451Smsmith goto ret; 57938451Smsmith } 58038451Smsmith fp->off += cc; 58138451Smsmith addr += cc; 58238451Smsmith size -= cc; 58338451Smsmith } 58438451Smsmithret: 58538451Smsmith if (resid) 58638451Smsmith *resid = size; 58738451Smsmith 58838451Smsmith return (0); 58938451Smsmith} 59038451Smsmith 59138451Smsmith/* 59238451Smsmith * Not implemented. 59338451Smsmith */ 59438451Smsmithint 59538451Smsmithnfs_write(f, buf, size, resid) 59638451Smsmith struct open_file *f; 59738451Smsmith void *buf; 59838451Smsmith size_t size; 59938451Smsmith size_t *resid; /* out */ 60038451Smsmith{ 60138451Smsmith return (EROFS); 60238451Smsmith} 60338451Smsmith 60438451Smsmithoff_t 60538451Smsmithnfs_seek(f, offset, where) 60638451Smsmith struct open_file *f; 60738451Smsmith off_t offset; 60838451Smsmith int where; 60938451Smsmith{ 61038451Smsmith register struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata; 61138451Smsmith n_long size = ntohl(d->fa.fa_size); 61238451Smsmith 61338451Smsmith switch (where) { 61438451Smsmith case SEEK_SET: 61538451Smsmith d->off = offset; 61638451Smsmith break; 61738451Smsmith case SEEK_CUR: 61838451Smsmith d->off += offset; 61938451Smsmith break; 62038451Smsmith case SEEK_END: 62138451Smsmith d->off = size - offset; 62238451Smsmith break; 62338451Smsmith default: 62438451Smsmith return (-1); 62538451Smsmith } 62638451Smsmith 62738451Smsmith return (d->off); 62838451Smsmith} 62938451Smsmith 63038451Smsmith/* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */ 63138451Smsmithint nfs_stat_types[8] = { 63238451Smsmith 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0 }; 63338451Smsmith 63438451Smsmithint 63538451Smsmithnfs_stat(f, sb) 63638451Smsmith struct open_file *f; 63738451Smsmith struct stat *sb; 63838451Smsmith{ 63938451Smsmith struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 64038451Smsmith register n_long ftype, mode; 64138451Smsmith 64238451Smsmith ftype = ntohl(fp->fa.fa_type); 64338451Smsmith mode = ntohl(fp->fa.fa_mode); 64438451Smsmith mode |= nfs_stat_types[ftype & 7]; 64538451Smsmith 64638451Smsmith sb->st_mode = mode; 64738451Smsmith sb->st_nlink = ntohl(fp->fa.fa_nlink); 64838451Smsmith sb->st_uid = ntohl(fp->fa.fa_uid); 64938451Smsmith sb->st_gid = ntohl(fp->fa.fa_gid); 65038451Smsmith sb->st_size = ntohl(fp->fa.fa_size); 65138451Smsmith 65238451Smsmith return (0); 65338451Smsmith} 654