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