nfs.c revision 99558
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 99558 2002-07-07 23:01:36Z jake $"); 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) 15192913Sobrien struct iodesc *d; 15238451Smsmith char *path; 15338451Smsmith u_char *fhp; 15438451Smsmith{ 15592913Sobrien 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{ 21492913Sobrien 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; 39392913Sobrien char *cp, *ncp; 39492913Sobrien 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 41199558Sjake#ifdef __sparc64__ 41299558Sjake if (strcmp(f->f_dev->dv_name, "net") != 0) 41399558Sjake return(EINVAL); 41499558Sjake#endif 41538451Smsmith if (!(desc = socktodesc(*(int *)(f->f_devdata)))) 41638451Smsmith return(EINVAL); 41738451Smsmith 41838451Smsmith /* Bind to a reserved port. */ 41938451Smsmith desc->myport = htons(--rpc_port); 42038451Smsmith desc->destip = rootip; 42138451Smsmith if ((error = nfs_getrootfh(desc, rootpath, nfs_root_node.fh))) 42238451Smsmith return (error); 42338451Smsmith nfs_root_node.iodesc = desc; 42438451Smsmith 42538451Smsmith#ifndef NFS_NOSYMLINK 42638451Smsmith /* Fake up attributes for the root dir. */ 42738451Smsmith fa = &nfs_root_node.fa; 42838451Smsmith fa->fa_type = htonl(NFDIR); 42938451Smsmith fa->fa_mode = htonl(0755); 43038451Smsmith fa->fa_nlink = htonl(2); 43138451Smsmith 43238451Smsmith currfd = &nfs_root_node; 43338451Smsmith newfd = 0; 43438451Smsmith 43539468Smsmith cp = path = strdup(upath); 43639468Smsmith if (path == NULL) { 43739468Smsmith error = ENOMEM; 43839468Smsmith goto out; 43939468Smsmith } 44038451Smsmith while (*cp) { 44138451Smsmith /* 44238451Smsmith * Remove extra separators 44338451Smsmith */ 44438451Smsmith while (*cp == '/') 44538451Smsmith cp++; 44638451Smsmith 44738451Smsmith if (*cp == '\0') 44838451Smsmith break; 44938451Smsmith /* 45038451Smsmith * Check that current node is a directory. 45138451Smsmith */ 45238451Smsmith if (currfd->fa.fa_type != htonl(NFDIR)) { 45338451Smsmith error = ENOTDIR; 45438451Smsmith goto out; 45538451Smsmith } 45638451Smsmith 45738451Smsmith /* allocate file system specific data structure */ 45838451Smsmith newfd = malloc(sizeof(*newfd)); 45938451Smsmith newfd->iodesc = currfd->iodesc; 46038451Smsmith newfd->off = 0; 46138451Smsmith 46238451Smsmith /* 46338451Smsmith * Get next component of path name. 46438451Smsmith */ 46538451Smsmith { 46692913Sobrien int len = 0; 46738451Smsmith 46838451Smsmith ncp = cp; 46938451Smsmith while ((c = *cp) != '\0' && c != '/') { 47038451Smsmith if (++len > NFS_MAXNAMLEN) { 47138451Smsmith error = ENOENT; 47238451Smsmith goto out; 47338451Smsmith } 47438451Smsmith cp++; 47538451Smsmith } 47638451Smsmith *cp = '\0'; 47738451Smsmith } 47838451Smsmith 47938451Smsmith /* lookup a file handle */ 48038451Smsmith error = nfs_lookupfh(currfd, ncp, newfd); 48138451Smsmith *cp = c; 48238451Smsmith if (error) 48338451Smsmith goto out; 48438451Smsmith 48538451Smsmith /* 48638451Smsmith * Check for symbolic link 48738451Smsmith */ 48838451Smsmith if (newfd->fa.fa_type == htonl(NFLNK)) { 48938451Smsmith int link_len, len; 49038451Smsmith 49138451Smsmith error = nfs_readlink(newfd, linkbuf); 49238451Smsmith if (error) 49338451Smsmith goto out; 49438451Smsmith 49538451Smsmith link_len = strlen(linkbuf); 49638451Smsmith len = strlen(cp); 49738451Smsmith 49838451Smsmith if (link_len + len > MAXPATHLEN 49938451Smsmith || ++nlinks > MAXSYMLINKS) { 50038451Smsmith error = ENOENT; 50138451Smsmith goto out; 50238451Smsmith } 50338451Smsmith 50438451Smsmith bcopy(cp, &namebuf[link_len], len + 1); 50538451Smsmith bcopy(linkbuf, namebuf, link_len); 50638451Smsmith 50738451Smsmith /* 50838451Smsmith * If absolute pathname, restart at root. 50938451Smsmith * If relative pathname, restart at parent directory. 51038451Smsmith */ 51138451Smsmith cp = namebuf; 51238451Smsmith if (*cp == '/') { 51338451Smsmith if (currfd != &nfs_root_node) 51438451Smsmith free(currfd); 51538451Smsmith currfd = &nfs_root_node; 51638451Smsmith } 51738451Smsmith 51838451Smsmith free(newfd); 51938451Smsmith newfd = 0; 52038451Smsmith 52138451Smsmith continue; 52238451Smsmith } 52338451Smsmith 52438451Smsmith if (currfd != &nfs_root_node) 52538451Smsmith free(currfd); 52638451Smsmith currfd = newfd; 52738451Smsmith newfd = 0; 52838451Smsmith } 52938451Smsmith 53038451Smsmith error = 0; 53138451Smsmith 53238451Smsmithout: 53338451Smsmith if (newfd) 53438451Smsmith free(newfd); 53539468Smsmith if (path) 53639468Smsmith free(path); 53738451Smsmith#else 53838451Smsmith /* allocate file system specific data structure */ 53938451Smsmith currfd = malloc(sizeof(*currfd)); 54038451Smsmith currfd->iodesc = desc; 54138451Smsmith currfd->off = 0; 54238451Smsmith 54339468Smsmith error = nfs_lookupfh(&nfs_root_node, upath, currfd); 54438451Smsmith#endif 54538451Smsmith if (!error) { 54638451Smsmith f->f_fsdata = (void *)currfd; 54738451Smsmith return (0); 54838451Smsmith } 54938451Smsmith 55038451Smsmith#ifdef NFS_DEBUG 55138451Smsmith if (debug) 55238451Smsmith printf("nfs_open: %s lookupfh failed: %s\n", 55338451Smsmith path, strerror(error)); 55438451Smsmith#endif 55538451Smsmith#ifndef NFS_NOSYMLINK 55638451Smsmith if (currfd != &nfs_root_node) 55738451Smsmith#endif 55838451Smsmith free(currfd); 55938451Smsmith 56038451Smsmith return (error); 56138451Smsmith} 56238451Smsmith 56338451Smsmithint 56438451Smsmithnfs_close(f) 56538451Smsmith struct open_file *f; 56638451Smsmith{ 56792913Sobrien struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 56838451Smsmith 56938451Smsmith#ifdef NFS_DEBUG 57038451Smsmith if (debug) 57138451Smsmith printf("nfs_close: fp=0x%lx\n", (u_long)fp); 57238451Smsmith#endif 57338451Smsmith 57459824Sps if (fp != &nfs_root_node && fp) 57538451Smsmith free(fp); 57638451Smsmith f->f_fsdata = (void *)0; 57738451Smsmith 57838451Smsmith return (0); 57938451Smsmith} 58038451Smsmith 58138451Smsmith/* 58238451Smsmith * read a portion of a file 58338451Smsmith */ 58438451Smsmithint 58538451Smsmithnfs_read(f, buf, size, resid) 58638451Smsmith struct open_file *f; 58738451Smsmith void *buf; 58838451Smsmith size_t size; 58938451Smsmith size_t *resid; /* out */ 59038451Smsmith{ 59192913Sobrien struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 59292913Sobrien ssize_t cc; 59392913Sobrien char *addr = buf; 59438451Smsmith 59538451Smsmith#ifdef NFS_DEBUG 59638451Smsmith if (debug) 59738451Smsmith printf("nfs_read: size=%lu off=%d\n", (u_long)size, 59838451Smsmith (int)fp->off); 59938451Smsmith#endif 60038451Smsmith while ((int)size > 0) { 60138451Smsmith twiddle(); 60238451Smsmith cc = nfs_readdata(fp, fp->off, (void *)addr, size); 60338451Smsmith /* XXX maybe should retry on certain errors */ 60438451Smsmith if (cc == -1) { 60538451Smsmith#ifdef NFS_DEBUG 60638451Smsmith if (debug) 60738451Smsmith printf("nfs_read: read: %s", strerror(errno)); 60838451Smsmith#endif 60938451Smsmith return (errno); /* XXX - from nfs_readdata */ 61038451Smsmith } 61138451Smsmith if (cc == 0) { 61238451Smsmith#ifdef NFS_DEBUG 61338451Smsmith if (debug) 61438451Smsmith printf("nfs_read: hit EOF unexpectantly"); 61538451Smsmith#endif 61638451Smsmith goto ret; 61738451Smsmith } 61838451Smsmith fp->off += cc; 61938451Smsmith addr += cc; 62038451Smsmith size -= cc; 62138451Smsmith } 62238451Smsmithret: 62338451Smsmith if (resid) 62438451Smsmith *resid = size; 62538451Smsmith 62638451Smsmith return (0); 62738451Smsmith} 62838451Smsmith 62938451Smsmith/* 63038451Smsmith * Not implemented. 63138451Smsmith */ 63238451Smsmithint 63338451Smsmithnfs_write(f, buf, size, resid) 63438451Smsmith struct open_file *f; 63538451Smsmith void *buf; 63638451Smsmith size_t size; 63738451Smsmith size_t *resid; /* out */ 63838451Smsmith{ 63938451Smsmith return (EROFS); 64038451Smsmith} 64138451Smsmith 64238451Smsmithoff_t 64338451Smsmithnfs_seek(f, offset, where) 64438451Smsmith struct open_file *f; 64538451Smsmith off_t offset; 64638451Smsmith int where; 64738451Smsmith{ 64892913Sobrien struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata; 64938451Smsmith n_long size = ntohl(d->fa.fa_size); 65038451Smsmith 65138451Smsmith switch (where) { 65238451Smsmith case SEEK_SET: 65338451Smsmith d->off = offset; 65438451Smsmith break; 65538451Smsmith case SEEK_CUR: 65638451Smsmith d->off += offset; 65738451Smsmith break; 65838451Smsmith case SEEK_END: 65938451Smsmith d->off = size - offset; 66038451Smsmith break; 66138451Smsmith default: 66238451Smsmith return (-1); 66338451Smsmith } 66438451Smsmith 66538451Smsmith return (d->off); 66638451Smsmith} 66738451Smsmith 66838451Smsmith/* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */ 66938451Smsmithint nfs_stat_types[8] = { 67038451Smsmith 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0 }; 67138451Smsmith 67238451Smsmithint 67338451Smsmithnfs_stat(f, sb) 67438451Smsmith struct open_file *f; 67538451Smsmith struct stat *sb; 67638451Smsmith{ 67738451Smsmith struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 67892913Sobrien n_long ftype, mode; 67938451Smsmith 68038451Smsmith ftype = ntohl(fp->fa.fa_type); 68138451Smsmith mode = ntohl(fp->fa.fa_mode); 68238451Smsmith mode |= nfs_stat_types[ftype & 7]; 68338451Smsmith 68438451Smsmith sb->st_mode = mode; 68538451Smsmith sb->st_nlink = ntohl(fp->fa.fa_nlink); 68638451Smsmith sb->st_uid = ntohl(fp->fa.fa_uid); 68738451Smsmith sb->st_gid = ntohl(fp->fa.fa_gid); 68838451Smsmith sb->st_size = ntohl(fp->fa.fa_size); 68938451Smsmith 69038451Smsmith return (0); 69138451Smsmith} 69259853Sps 69359853Spsstatic int 69459853Spsnfs_readdir(struct open_file *f, struct dirent *d) 69559853Sps{ 69692913Sobrien struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 69759853Sps struct nfs_readdir_args *args; 69859853Sps struct nfs_readdir_data *rd; 69959853Sps struct nfs_readdir_off *roff = NULL; 70059853Sps static char *buf; 70159853Sps static n_long cookie = 0; 70259853Sps size_t cc; 70359853Sps n_long eof; 70459853Sps 70559853Sps struct { 70659853Sps n_long h[RPC_HEADER_WORDS]; 70759853Sps struct nfs_readdir_args d; 70859853Sps } sdata; 70959853Sps static struct { 71059853Sps n_long h[RPC_HEADER_WORDS]; 71159853Sps u_char d[NFS_READDIRSIZE]; 71259853Sps } rdata; 71359853Sps 71459853Sps if (cookie == 0) { 71559853Sps refill: 71659853Sps args = &sdata.d; 71759853Sps bzero(args, sizeof(*args)); 71859853Sps 71959853Sps bcopy(fp->fh, args->fh, NFS_FHSIZE); 72059853Sps args->cookie = htonl(cookie); 72159853Sps args->count = htonl(NFS_READDIRSIZE); 72259853Sps 72359853Sps cc = rpc_call(fp->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READDIR, 72459853Sps args, sizeof(*args), 72559853Sps rdata.d, sizeof(rdata.d)); 72659853Sps buf = rdata.d; 72759853Sps roff = (struct nfs_readdir_off *)buf; 72859853Sps if (ntohl(roff->cookie) != 0) 72959853Sps return 1; 73059853Sps } 73159853Sps roff = (struct nfs_readdir_off *)buf; 73259853Sps 73359853Sps if (ntohl(roff->follows) == 0) { 73459853Sps eof = ntohl((roff+1)->cookie); 73559853Sps if (eof) { 73659853Sps cookie = 0; 73759853Sps return 1; 73859853Sps } 73959853Sps goto refill; 74059853Sps } 74159853Sps 74259853Sps buf += sizeof(struct nfs_readdir_off); 74359853Sps rd = (struct nfs_readdir_data *)buf; 74459853Sps d->d_namlen = ntohl(rd->len); 74559853Sps bcopy(rd->name, d->d_name, d->d_namlen); 74659853Sps d->d_name[d->d_namlen] = '\0'; 74759853Sps 74859853Sps buf += (sizeof(struct nfs_readdir_data) + roundup(htonl(rd->len),4)); 74959853Sps roff = (struct nfs_readdir_off *)buf; 75059853Sps cookie = ntohl(roff->cookie); 75159853Sps return 0; 75259853Sps} 753