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