1*599546b3Sderaadt /* $OpenBSD: nfs.c,v 1.10 2003/08/11 06:23:09 deraadt Exp $ */ 279dbd5ceSniklas /* $NetBSD: nfs.c,v 1.19 1996/10/13 02:29:04 christos Exp $ */ 3df930be7Sderaadt 4df930be7Sderaadt /*- 5df930be7Sderaadt * Copyright (c) 1993 John Brezak 6df930be7Sderaadt * All rights reserved. 7df930be7Sderaadt * 8df930be7Sderaadt * Redistribution and use in source and binary forms, with or without 9df930be7Sderaadt * modification, are permitted provided that the following conditions 10df930be7Sderaadt * are met: 11df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright 12df930be7Sderaadt * notice, this list of conditions and the following disclaimer. 13df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright 14df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the 15df930be7Sderaadt * documentation and/or other materials provided with the distribution. 16df930be7Sderaadt * 3. The name of the author may not be used to endorse or promote products 17df930be7Sderaadt * derived from this software without specific prior written permission. 18df930be7Sderaadt * 19df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 20df930be7Sderaadt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21df930be7Sderaadt * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22df930be7Sderaadt * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 23df930be7Sderaadt * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24df930be7Sderaadt * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25df930be7Sderaadt * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27df930be7Sderaadt * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28df930be7Sderaadt * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29df930be7Sderaadt * POSSIBILITY OF SUCH DAMAGE. 30df930be7Sderaadt */ 31df930be7Sderaadt 32df930be7Sderaadt #include <sys/param.h> 33df930be7Sderaadt #include <sys/time.h> 34df930be7Sderaadt #include <sys/socket.h> 35df930be7Sderaadt #include <sys/stat.h> 36df930be7Sderaadt 37df930be7Sderaadt #include <netinet/in.h> 38df930be7Sderaadt #include <netinet/in_systm.h> 39df930be7Sderaadt 4079dbd5ceSniklas #include "rpcv2.h" 4179dbd5ceSniklas #include "nfsv2.h" 42df930be7Sderaadt 43df930be7Sderaadt #include "stand.h" 44e76f679cSmickey #include "saerrno.h" 45df930be7Sderaadt #include "net.h" 46df930be7Sderaadt #include "netif.h" 47df930be7Sderaadt #include "nfs.h" 48df930be7Sderaadt #include "rpc.h" 49df930be7Sderaadt 50df930be7Sderaadt /* Define our own NFS attributes without NQNFS stuff. */ 51df930be7Sderaadt struct nfsv2_fattrs { 52df930be7Sderaadt n_long fa_type; 53df930be7Sderaadt n_long fa_mode; 54df930be7Sderaadt n_long fa_nlink; 55df930be7Sderaadt n_long fa_uid; 56df930be7Sderaadt n_long fa_gid; 57df930be7Sderaadt n_long fa_size; 58df930be7Sderaadt n_long fa_blocksize; 59df930be7Sderaadt n_long fa_rdev; 60df930be7Sderaadt n_long fa_blocks; 61df930be7Sderaadt n_long fa_fsid; 62df930be7Sderaadt n_long fa_fileid; 63df930be7Sderaadt struct nfsv2_time fa_atime; 64df930be7Sderaadt struct nfsv2_time fa_mtime; 65df930be7Sderaadt struct nfsv2_time fa_ctime; 66df930be7Sderaadt }; 67df930be7Sderaadt 68df930be7Sderaadt 69df930be7Sderaadt struct nfs_read_args { 70df930be7Sderaadt u_char fh[NFS_FHSIZE]; 71df930be7Sderaadt n_long off; 72df930be7Sderaadt n_long len; 73df930be7Sderaadt n_long xxx; /* XXX what's this for? */ 74df930be7Sderaadt }; 75df930be7Sderaadt 76df930be7Sderaadt /* Data part of nfs rpc reply (also the largest thing we receive) */ 77df930be7Sderaadt #define NFSREAD_SIZE 1024 78df930be7Sderaadt struct nfs_read_repl { 79df930be7Sderaadt n_long errno; 80df930be7Sderaadt struct nfsv2_fattrs fa; 81df930be7Sderaadt n_long count; 82df930be7Sderaadt u_char data[NFSREAD_SIZE]; 83df930be7Sderaadt }; 84df930be7Sderaadt 8579dbd5ceSniklas struct nfs_readlnk_repl { 8679dbd5ceSniklas n_long errno; 8779dbd5ceSniklas n_long len; 8879dbd5ceSniklas char path[NFS_MAXPATHLEN]; 8979dbd5ceSniklas }; 9079dbd5ceSniklas 91df930be7Sderaadt struct nfs_iodesc { 92df930be7Sderaadt struct iodesc *iodesc; 93df930be7Sderaadt off_t off; 94df930be7Sderaadt u_char fh[NFS_FHSIZE]; 95df930be7Sderaadt struct nfsv2_fattrs fa; /* all in network order */ 96df930be7Sderaadt }; 97df930be7Sderaadt 98df930be7Sderaadt struct nfs_iodesc nfs_root_node; 99df930be7Sderaadt 100df930be7Sderaadt 101df930be7Sderaadt /* 102df930be7Sderaadt * Fetch the root file handle (call mount daemon) 103df930be7Sderaadt * On error, return non-zero and set errno. 104df930be7Sderaadt */ 105*599546b3Sderaadt static int 106*599546b3Sderaadt nfs_getrootfh(struct iodesc *d, char *path, u_char *fhp) 107df930be7Sderaadt { 108*599546b3Sderaadt int len; 109df930be7Sderaadt struct args { 110df930be7Sderaadt n_long len; 111df930be7Sderaadt char path[FNAME_SIZE]; 112df930be7Sderaadt } *args; 113df930be7Sderaadt struct repl { 114df930be7Sderaadt n_long errno; 115df930be7Sderaadt u_char fh[NFS_FHSIZE]; 116df930be7Sderaadt } *repl; 117df930be7Sderaadt struct { 118df930be7Sderaadt n_long h[RPC_HEADER_WORDS]; 119df930be7Sderaadt struct args d; 120df930be7Sderaadt } sdata; 121df930be7Sderaadt struct { 122df930be7Sderaadt n_long h[RPC_HEADER_WORDS]; 123df930be7Sderaadt struct repl d; 124df930be7Sderaadt } rdata; 125df930be7Sderaadt size_t cc; 126df930be7Sderaadt 127df930be7Sderaadt #ifdef NFS_DEBUG 128df930be7Sderaadt if (debug) 129df930be7Sderaadt printf("nfs_getrootfh: %s\n", path); 130df930be7Sderaadt #endif 131df930be7Sderaadt 132df930be7Sderaadt args = &sdata.d; 133df930be7Sderaadt repl = &rdata.d; 134df930be7Sderaadt 135df930be7Sderaadt bzero(args, sizeof(*args)); 136df930be7Sderaadt len = strlen(path); 137df930be7Sderaadt if (len > sizeof(args->path)) 138df930be7Sderaadt len = sizeof(args->path); 139df930be7Sderaadt args->len = htonl(len); 140df930be7Sderaadt bcopy(path, args->path, len); 141df930be7Sderaadt len = 4 + roundup(len, 4); 142df930be7Sderaadt 143df930be7Sderaadt cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT, 144df930be7Sderaadt args, len, repl, sizeof(*repl)); 145df930be7Sderaadt if (cc == -1) { 146df930be7Sderaadt /* errno was set by rpc_call */ 147df930be7Sderaadt return (-1); 148df930be7Sderaadt } 149df930be7Sderaadt if (cc < 4) { 150df930be7Sderaadt errno = EBADRPC; 151df930be7Sderaadt return (-1); 152df930be7Sderaadt } 153df930be7Sderaadt if (repl->errno) { 154df930be7Sderaadt errno = ntohl(repl->errno); 155df930be7Sderaadt return (-1); 156df930be7Sderaadt } 157df930be7Sderaadt bcopy(repl->fh, fhp, sizeof(repl->fh)); 158df930be7Sderaadt return (0); 159df930be7Sderaadt } 160df930be7Sderaadt 161df930be7Sderaadt /* 162df930be7Sderaadt * Lookup a file. Store handle and attributes. 163df930be7Sderaadt * Return zero or error number. 164df930be7Sderaadt */ 165*599546b3Sderaadt static int 166*599546b3Sderaadt nfs_lookupfh(struct nfs_iodesc *d, char *name, struct nfs_iodesc *newfd) 167df930be7Sderaadt { 168*599546b3Sderaadt int len, rlen; 169df930be7Sderaadt struct args { 170df930be7Sderaadt u_char fh[NFS_FHSIZE]; 171df930be7Sderaadt n_long len; 172df930be7Sderaadt char name[FNAME_SIZE]; 173df930be7Sderaadt } *args; 174df930be7Sderaadt struct repl { 175df930be7Sderaadt n_long errno; 176df930be7Sderaadt u_char fh[NFS_FHSIZE]; 177df930be7Sderaadt struct nfsv2_fattrs fa; 178df930be7Sderaadt } *repl; 179df930be7Sderaadt struct { 180df930be7Sderaadt n_long h[RPC_HEADER_WORDS]; 181df930be7Sderaadt struct args d; 182df930be7Sderaadt } sdata; 183df930be7Sderaadt struct { 184df930be7Sderaadt n_long h[RPC_HEADER_WORDS]; 185df930be7Sderaadt struct repl d; 186df930be7Sderaadt } rdata; 187df930be7Sderaadt ssize_t cc; 188df930be7Sderaadt 189df930be7Sderaadt #ifdef NFS_DEBUG 190df930be7Sderaadt if (debug) 191df930be7Sderaadt printf("lookupfh: called\n"); 192df930be7Sderaadt #endif 193df930be7Sderaadt 194df930be7Sderaadt args = &sdata.d; 195df930be7Sderaadt repl = &rdata.d; 196df930be7Sderaadt 197df930be7Sderaadt bzero(args, sizeof(*args)); 198df930be7Sderaadt bcopy(d->fh, args->fh, sizeof(args->fh)); 199df930be7Sderaadt len = strlen(name); 200df930be7Sderaadt if (len > sizeof(args->name)) 201df930be7Sderaadt len = sizeof(args->name); 202df930be7Sderaadt bcopy(name, args->name, len); 203df930be7Sderaadt args->len = htonl(len); 204df930be7Sderaadt len = 4 + roundup(len, 4); 205df930be7Sderaadt len += NFS_FHSIZE; 206df930be7Sderaadt 207df930be7Sderaadt rlen = sizeof(*repl); 208df930be7Sderaadt 209df930be7Sderaadt cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP, 210df930be7Sderaadt args, len, repl, rlen); 211df930be7Sderaadt if (cc == -1) 212df930be7Sderaadt return (errno); /* XXX - from rpc_call */ 213df930be7Sderaadt if (cc < 4) 214df930be7Sderaadt return (EIO); 215df930be7Sderaadt if (repl->errno) { 216df930be7Sderaadt /* saerrno.h now matches NFS error numbers. */ 217df930be7Sderaadt return (ntohl(repl->errno)); 218df930be7Sderaadt } 219df930be7Sderaadt bcopy( repl->fh, &newfd->fh, sizeof(newfd->fh)); 220df930be7Sderaadt bcopy(&repl->fa, &newfd->fa, sizeof(newfd->fa)); 221df930be7Sderaadt return (0); 222df930be7Sderaadt } 223df930be7Sderaadt 224df930be7Sderaadt /* 22579dbd5ceSniklas * Get the destination of a symbolic link. 22679dbd5ceSniklas */ 227*599546b3Sderaadt static int 228*599546b3Sderaadt nfs_readlink(struct nfs_iodesc *d, char *buf) 22979dbd5ceSniklas { 23079dbd5ceSniklas struct { 23179dbd5ceSniklas n_long h[RPC_HEADER_WORDS]; 23279dbd5ceSniklas u_char fh[NFS_FHSIZE]; 23379dbd5ceSniklas } sdata; 23479dbd5ceSniklas struct { 23579dbd5ceSniklas n_long h[RPC_HEADER_WORDS]; 23679dbd5ceSniklas struct nfs_readlnk_repl d; 23779dbd5ceSniklas } rdata; 23879dbd5ceSniklas ssize_t cc; 23979dbd5ceSniklas 24079dbd5ceSniklas #ifdef NFS_DEBUG 24179dbd5ceSniklas if (debug) 24279dbd5ceSniklas printf("readlink: called\n"); 24379dbd5ceSniklas #endif 24479dbd5ceSniklas 24579dbd5ceSniklas bcopy(d->fh, sdata.fh, NFS_FHSIZE); 24679dbd5ceSniklas cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK, 24779dbd5ceSniklas sdata.fh, NFS_FHSIZE, 24879dbd5ceSniklas &rdata.d, sizeof(rdata.d)); 24979dbd5ceSniklas if (cc == -1) 25079dbd5ceSniklas return (errno); 25179dbd5ceSniklas 25279dbd5ceSniklas if (cc < 4) 25379dbd5ceSniklas return (EIO); 25479dbd5ceSniklas 25579dbd5ceSniklas if (rdata.d.errno) 25679dbd5ceSniklas return (ntohl(rdata.d.errno)); 25779dbd5ceSniklas 25879dbd5ceSniklas rdata.d.len = ntohl(rdata.d.len); 25979dbd5ceSniklas if (rdata.d.len > NFS_MAXPATHLEN) 26079dbd5ceSniklas return (ENAMETOOLONG); 26179dbd5ceSniklas 26279dbd5ceSniklas bcopy(rdata.d.path, buf, rdata.d.len); 26379dbd5ceSniklas buf[rdata.d.len] = 0; 26479dbd5ceSniklas return (0); 26579dbd5ceSniklas } 26679dbd5ceSniklas 26779dbd5ceSniklas /* 268df930be7Sderaadt * Read data from a file. 269df930be7Sderaadt * Return transfer count or -1 (and set errno) 270df930be7Sderaadt */ 271*599546b3Sderaadt static ssize_t 272*599546b3Sderaadt nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len) 273df930be7Sderaadt { 274df930be7Sderaadt struct nfs_read_args *args; 275df930be7Sderaadt struct nfs_read_repl *repl; 276df930be7Sderaadt struct { 277df930be7Sderaadt n_long h[RPC_HEADER_WORDS]; 278df930be7Sderaadt struct nfs_read_args d; 279df930be7Sderaadt } sdata; 280df930be7Sderaadt struct { 281df930be7Sderaadt n_long h[RPC_HEADER_WORDS]; 282df930be7Sderaadt struct nfs_read_repl d; 283df930be7Sderaadt } rdata; 284df930be7Sderaadt size_t cc; 285df930be7Sderaadt long x; 286df930be7Sderaadt int hlen, rlen; 287df930be7Sderaadt 288df930be7Sderaadt args = &sdata.d; 289df930be7Sderaadt repl = &rdata.d; 290df930be7Sderaadt 291df930be7Sderaadt bcopy(d->fh, args->fh, NFS_FHSIZE); 2920c0430f8Sniklas args->off = htonl((n_long)off); 293df930be7Sderaadt if (len > NFSREAD_SIZE) 294df930be7Sderaadt len = NFSREAD_SIZE; 2950c0430f8Sniklas args->len = htonl((n_long)len); 2960c0430f8Sniklas args->xxx = htonl((n_long)0); 297df930be7Sderaadt hlen = sizeof(*repl) - NFSREAD_SIZE; 298df930be7Sderaadt 299df930be7Sderaadt cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ, 300df930be7Sderaadt args, sizeof(*args), 301df930be7Sderaadt repl, sizeof(*repl)); 302df930be7Sderaadt if (cc == -1) { 303df930be7Sderaadt /* errno was already set by rpc_call */ 304df930be7Sderaadt return (-1); 305df930be7Sderaadt } 306df930be7Sderaadt if (cc < hlen) { 307df930be7Sderaadt errno = EBADRPC; 308df930be7Sderaadt return (-1); 309df930be7Sderaadt } 310df930be7Sderaadt if (repl->errno) { 311df930be7Sderaadt errno = ntohl(repl->errno); 312df930be7Sderaadt return (-1); 313df930be7Sderaadt } 314df930be7Sderaadt rlen = cc - hlen; 315df930be7Sderaadt x = ntohl(repl->count); 316df930be7Sderaadt if (rlen < x) { 317a4bb608eSderaadt printf("nfsread: short packet, %d < %ld\n", rlen, x); 318df930be7Sderaadt errno = EBADRPC; 319df930be7Sderaadt return(-1); 320df930be7Sderaadt } 321df930be7Sderaadt bcopy(repl->data, addr, x); 322df930be7Sderaadt return (x); 323df930be7Sderaadt } 324df930be7Sderaadt 325df930be7Sderaadt /* 326df930be7Sderaadt * nfs_mount - mount this nfs filesystem to a host 327df930be7Sderaadt * On error, return non-zero and set errno. 328df930be7Sderaadt */ 329df930be7Sderaadt int 330*599546b3Sderaadt nfs_mount(int sock, struct in_addr ip, char *path) 331df930be7Sderaadt { 332df930be7Sderaadt struct iodesc *desc; 333df930be7Sderaadt struct nfsv2_fattrs *fa; 334df930be7Sderaadt 335df930be7Sderaadt if (!(desc = socktodesc(sock))) { 336df930be7Sderaadt errno = EINVAL; 337df930be7Sderaadt return(-1); 338df930be7Sderaadt } 339df930be7Sderaadt 340df930be7Sderaadt /* Bind to a reserved port. */ 341df930be7Sderaadt desc->myport = htons(--rpc_port); 342df930be7Sderaadt desc->destip = ip; 343df930be7Sderaadt if (nfs_getrootfh(desc, path, nfs_root_node.fh)) 344df930be7Sderaadt return (-1); 345df930be7Sderaadt nfs_root_node.iodesc = desc; 346df930be7Sderaadt /* Fake up attributes for the root dir. */ 347df930be7Sderaadt fa = &nfs_root_node.fa; 348df930be7Sderaadt fa->fa_type = htonl(NFDIR); 349df930be7Sderaadt fa->fa_mode = htonl(0755); 350df930be7Sderaadt fa->fa_nlink = htonl(2); 351df930be7Sderaadt 352df930be7Sderaadt #ifdef NFS_DEBUG 353df930be7Sderaadt if (debug) 354df930be7Sderaadt printf("nfs_mount: got fh for %s\n", path); 355df930be7Sderaadt #endif 356df930be7Sderaadt 357df930be7Sderaadt return(0); 358df930be7Sderaadt } 359df930be7Sderaadt 360df930be7Sderaadt /* 361df930be7Sderaadt * Open a file. 362df930be7Sderaadt * return zero or error number 363df930be7Sderaadt */ 364df930be7Sderaadt int 365*599546b3Sderaadt nfs_open(char *path, struct open_file *f) 366df930be7Sderaadt { 36779dbd5ceSniklas struct nfs_iodesc *newfd, *currfd; 368*599546b3Sderaadt char namebuf[NFS_MAXPATHLEN + 1], *cp, *ncp; 36979dbd5ceSniklas char linkbuf[NFS_MAXPATHLEN + 1]; 370*599546b3Sderaadt int nlinks = 0, error = 0, c; 371df930be7Sderaadt 372df930be7Sderaadt #ifdef NFS_DEBUG 373df930be7Sderaadt if (debug) 374df930be7Sderaadt printf("nfs_open: %s\n", path); 375df930be7Sderaadt #endif 376df930be7Sderaadt if (nfs_root_node.iodesc == NULL) { 377df930be7Sderaadt printf("nfs_open: must mount first.\n"); 378df930be7Sderaadt return (ENXIO); 379df930be7Sderaadt } 380df930be7Sderaadt 38179dbd5ceSniklas currfd = &nfs_root_node; 38279dbd5ceSniklas newfd = 0; 38379dbd5ceSniklas 38479dbd5ceSniklas cp = path; 38579dbd5ceSniklas while (*cp) { 38679dbd5ceSniklas /* 38779dbd5ceSniklas * Remove extra separators 38879dbd5ceSniklas */ 38979dbd5ceSniklas while (*cp == '/') 39079dbd5ceSniklas cp++; 39179dbd5ceSniklas 39279dbd5ceSniklas if (*cp == '\0') 39379dbd5ceSniklas break; 39479dbd5ceSniklas /* 39579dbd5ceSniklas * Check that current node is a directory. 39679dbd5ceSniklas */ 39779dbd5ceSniklas if (currfd->fa.fa_type != htonl(NFDIR)) { 39879dbd5ceSniklas error = ENOTDIR; 39979dbd5ceSniklas goto out; 40079dbd5ceSniklas } 40179dbd5ceSniklas 402df930be7Sderaadt /* allocate file system specific data structure */ 403df930be7Sderaadt newfd = alloc(sizeof(*newfd)); 40479dbd5ceSniklas newfd->iodesc = currfd->iodesc; 405df930be7Sderaadt newfd->off = 0; 406df930be7Sderaadt 40779dbd5ceSniklas /* 40879dbd5ceSniklas * Get next component of path name. 40979dbd5ceSniklas */ 41079dbd5ceSniklas { 411*599546b3Sderaadt int len = 0; 41279dbd5ceSniklas 41379dbd5ceSniklas ncp = cp; 41479dbd5ceSniklas while ((c = *cp) != '\0' && c != '/') { 41579dbd5ceSniklas if (++len > NFS_MAXNAMLEN) { 41679dbd5ceSniklas error = ENOENT; 41779dbd5ceSniklas goto out; 41879dbd5ceSniklas } 41979dbd5ceSniklas cp++; 42079dbd5ceSniklas } 42179dbd5ceSniklas *cp = '\0'; 42279dbd5ceSniklas } 42379dbd5ceSniklas 424df930be7Sderaadt /* lookup a file handle */ 42579dbd5ceSniklas error = nfs_lookupfh(currfd, ncp, newfd); 42679dbd5ceSniklas *cp = c; 42779dbd5ceSniklas if (error) 42879dbd5ceSniklas goto out; 42979dbd5ceSniklas 43079dbd5ceSniklas /* 43179dbd5ceSniklas * Check for symbolic link 43279dbd5ceSniklas */ 43379dbd5ceSniklas if (newfd->fa.fa_type == htonl(NFLNK)) { 43479dbd5ceSniklas int link_len, len; 43579dbd5ceSniklas 43679dbd5ceSniklas error = nfs_readlink(newfd, linkbuf); 43779dbd5ceSniklas if (error) 43879dbd5ceSniklas goto out; 43979dbd5ceSniklas 44079dbd5ceSniklas link_len = strlen(linkbuf); 44179dbd5ceSniklas len = strlen(cp); 44279dbd5ceSniklas 443*599546b3Sderaadt if (link_len + len > MAXPATHLEN || 444*599546b3Sderaadt ++nlinks > MAXSYMLINKS) { 44579dbd5ceSniklas error = ENOENT; 44679dbd5ceSniklas goto out; 44779dbd5ceSniklas } 44879dbd5ceSniklas 44979dbd5ceSniklas bcopy(cp, &namebuf[link_len], len + 1); 45079dbd5ceSniklas bcopy(linkbuf, namebuf, link_len); 45179dbd5ceSniklas 45279dbd5ceSniklas /* 45379dbd5ceSniklas * If absolute pathname, restart at root. 45479dbd5ceSniklas * If relative pathname, restart at parent directory. 45579dbd5ceSniklas */ 45679dbd5ceSniklas cp = namebuf; 45779dbd5ceSniklas if (*cp == '/') { 45879dbd5ceSniklas if (currfd != &nfs_root_node) 45979dbd5ceSniklas free(currfd, sizeof(*currfd)); 46079dbd5ceSniklas currfd = &nfs_root_node; 46179dbd5ceSniklas } 46279dbd5ceSniklas 46379dbd5ceSniklas free(newfd, sizeof(*newfd)); 46479dbd5ceSniklas newfd = 0; 46579dbd5ceSniklas 46679dbd5ceSniklas continue; 46779dbd5ceSniklas } 46879dbd5ceSniklas 46979dbd5ceSniklas if (currfd != &nfs_root_node) 47079dbd5ceSniklas free(currfd, sizeof(*currfd)); 47179dbd5ceSniklas currfd = newfd; 47279dbd5ceSniklas newfd = 0; 47379dbd5ceSniklas } 47479dbd5ceSniklas 47579dbd5ceSniklas error = 0; 47679dbd5ceSniklas 47779dbd5ceSniklas out: 478df930be7Sderaadt if (!error) { 47979dbd5ceSniklas f->f_fsdata = (void *)currfd; 480df930be7Sderaadt return (0); 481df930be7Sderaadt } 482df930be7Sderaadt 483df930be7Sderaadt #ifdef NFS_DEBUG 484df930be7Sderaadt if (debug) 485df930be7Sderaadt printf("nfs_open: %s lookupfh failed: %s\n", 486df930be7Sderaadt path, strerror(error)); 487df930be7Sderaadt #endif 48879dbd5ceSniklas if (currfd != &nfs_root_node) 48979dbd5ceSniklas free(currfd, sizeof(*currfd)); 49079dbd5ceSniklas if (newfd) 491df930be7Sderaadt free(newfd, sizeof(*newfd)); 49279dbd5ceSniklas 493df930be7Sderaadt return (error); 494df930be7Sderaadt } 495df930be7Sderaadt 496df930be7Sderaadt int 497*599546b3Sderaadt nfs_close(struct open_file *f) 498df930be7Sderaadt { 499*599546b3Sderaadt struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 500df930be7Sderaadt 501df930be7Sderaadt #ifdef NFS_DEBUG 502df930be7Sderaadt if (debug) 5036d86dcc1Smickey printf("nfs_close: fp=%p\n", fp); 504df930be7Sderaadt #endif 505df930be7Sderaadt 506df930be7Sderaadt if (fp) 507df930be7Sderaadt free(fp, sizeof(struct nfs_iodesc)); 508df930be7Sderaadt f->f_fsdata = (void *)0; 509df930be7Sderaadt 510df930be7Sderaadt return (0); 511df930be7Sderaadt } 512df930be7Sderaadt 513df930be7Sderaadt /* 514df930be7Sderaadt * read a portion of a file 515df930be7Sderaadt */ 516df930be7Sderaadt int 517*599546b3Sderaadt nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid) 518df930be7Sderaadt { 519*599546b3Sderaadt struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 520*599546b3Sderaadt ssize_t cc; 521*599546b3Sderaadt char *addr = buf; 522df930be7Sderaadt 523df930be7Sderaadt #ifdef NFS_DEBUG 524df930be7Sderaadt if (debug) 525df930be7Sderaadt printf("nfs_read: size=%d off=%d\n", size, (int)fp->off); 526df930be7Sderaadt #endif 527df930be7Sderaadt while ((int)size > 0) { 528df930be7Sderaadt twiddle(); 529df930be7Sderaadt cc = nfs_readdata(fp, fp->off, (void *)addr, size); 530df930be7Sderaadt /* XXX maybe should retry on certain errors */ 531df930be7Sderaadt if (cc == -1) { 532df930be7Sderaadt #ifdef NFS_DEBUG 533df930be7Sderaadt if (debug) 534df930be7Sderaadt printf("nfs_read: read: %s", strerror(errno)); 535df930be7Sderaadt #endif 536df930be7Sderaadt return (errno); /* XXX - from nfs_readdata */ 537df930be7Sderaadt } 538df930be7Sderaadt if (cc == 0) { 539df930be7Sderaadt if (debug) 540df930be7Sderaadt printf("nfs_read: hit EOF unexpectantly"); 541df930be7Sderaadt goto ret; 542df930be7Sderaadt } 543df930be7Sderaadt fp->off += cc; 544df930be7Sderaadt addr += cc; 545df930be7Sderaadt size -= cc; 546df930be7Sderaadt } 547df930be7Sderaadt ret: 548df930be7Sderaadt if (resid) 549df930be7Sderaadt *resid = size; 550df930be7Sderaadt 551df930be7Sderaadt return (0); 552df930be7Sderaadt } 553df930be7Sderaadt 554df930be7Sderaadt /* 555df930be7Sderaadt * Not implemented. 556df930be7Sderaadt */ 557df930be7Sderaadt int 558*599546b3Sderaadt nfs_write(struct open_file *f, void *buf, size_t size, size_t *resid) 559df930be7Sderaadt { 560df930be7Sderaadt return (EROFS); 561df930be7Sderaadt } 562df930be7Sderaadt 563df930be7Sderaadt off_t 564*599546b3Sderaadt nfs_seek(struct open_file *f, off_t offset, int where) 565df930be7Sderaadt { 566*599546b3Sderaadt struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata; 567df930be7Sderaadt n_long size = ntohl(d->fa.fa_size); 568df930be7Sderaadt 569df930be7Sderaadt switch (where) { 570df930be7Sderaadt case SEEK_SET: 571df930be7Sderaadt d->off = offset; 572df930be7Sderaadt break; 573df930be7Sderaadt case SEEK_CUR: 574df930be7Sderaadt d->off += offset; 575df930be7Sderaadt break; 576df930be7Sderaadt case SEEK_END: 577df930be7Sderaadt d->off = size - offset; 578df930be7Sderaadt break; 579df930be7Sderaadt default: 580df930be7Sderaadt return (-1); 581df930be7Sderaadt } 582df930be7Sderaadt 583df930be7Sderaadt return (d->off); 584df930be7Sderaadt } 585df930be7Sderaadt 586df930be7Sderaadt /* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */ 587df930be7Sderaadt int nfs_stat_types[8] = { 588df930be7Sderaadt 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0 }; 589df930be7Sderaadt 590df930be7Sderaadt int 591*599546b3Sderaadt nfs_stat(struct open_file *f, struct stat *sb) 592df930be7Sderaadt { 593df930be7Sderaadt struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; 594*599546b3Sderaadt n_long ftype, mode; 595df930be7Sderaadt 596df930be7Sderaadt ftype = ntohl(fp->fa.fa_type); 597df930be7Sderaadt mode = ntohl(fp->fa.fa_mode); 598df930be7Sderaadt mode |= nfs_stat_types[ftype & 7]; 599df930be7Sderaadt 600df930be7Sderaadt sb->st_mode = mode; 601df930be7Sderaadt sb->st_nlink = ntohl(fp->fa.fa_nlink); 602df930be7Sderaadt sb->st_uid = ntohl(fp->fa.fa_uid); 603df930be7Sderaadt sb->st_gid = ntohl(fp->fa.fa_gid); 604df930be7Sderaadt sb->st_size = ntohl(fp->fa.fa_size); 605df930be7Sderaadt 606df930be7Sderaadt return (0); 607df930be7Sderaadt } 608e76f679cSmickey 609e76f679cSmickey /* 610e76f679cSmickey * Not implemented. 611e76f679cSmickey */ 612e76f679cSmickey #ifndef NO_READDIR 613e76f679cSmickey int 614*599546b3Sderaadt nfs_readdir(struct open_file *f, char *name) 615e76f679cSmickey { 616e76f679cSmickey return (EROFS); 617e76f679cSmickey } 618e76f679cSmickey #endif 619