1*f14fb602SLionel Sambuc /* $NetBSD: nfs.c,v 1.19 2011/12/25 06:09:09 tsutsui Exp $ */
2*f14fb602SLionel Sambuc
3*f14fb602SLionel Sambuc /*-
4*f14fb602SLionel Sambuc * Copyright (c) 1993 John Brezak
5*f14fb602SLionel Sambuc * All rights reserved.
6*f14fb602SLionel Sambuc *
7*f14fb602SLionel Sambuc * Redistribution and use in source and binary forms, with or without
8*f14fb602SLionel Sambuc * modification, are permitted provided that the following conditions
9*f14fb602SLionel Sambuc * are met:
10*f14fb602SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
11*f14fb602SLionel Sambuc * notice, this list of conditions and the following disclaimer.
12*f14fb602SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
13*f14fb602SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
14*f14fb602SLionel Sambuc * documentation and/or other materials provided with the distribution.
15*f14fb602SLionel Sambuc * 3. The name of the author may not be used to endorse or promote products
16*f14fb602SLionel Sambuc * derived from this software without specific prior written permission.
17*f14fb602SLionel Sambuc *
18*f14fb602SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19*f14fb602SLionel Sambuc * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20*f14fb602SLionel Sambuc * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21*f14fb602SLionel Sambuc * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22*f14fb602SLionel Sambuc * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23*f14fb602SLionel Sambuc * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24*f14fb602SLionel Sambuc * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*f14fb602SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26*f14fb602SLionel Sambuc * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27*f14fb602SLionel Sambuc * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*f14fb602SLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
29*f14fb602SLionel Sambuc */
30*f14fb602SLionel Sambuc
31*f14fb602SLionel Sambuc #include <sys/param.h>
32*f14fb602SLionel Sambuc #include <sys/time.h>
33*f14fb602SLionel Sambuc #include <sys/socket.h>
34*f14fb602SLionel Sambuc #include <sys/stat.h>
35*f14fb602SLionel Sambuc #ifdef _STANDALONE
36*f14fb602SLionel Sambuc #include <lib/libkern/libkern.h>
37*f14fb602SLionel Sambuc #else
38*f14fb602SLionel Sambuc #include <string.h>
39*f14fb602SLionel Sambuc #endif
40*f14fb602SLionel Sambuc
41*f14fb602SLionel Sambuc #include <netinet/in.h>
42*f14fb602SLionel Sambuc #include <netinet/in_systm.h>
43*f14fb602SLionel Sambuc
44*f14fb602SLionel Sambuc #include "rpcv2.h"
45*f14fb602SLionel Sambuc #include "nfsv2.h"
46*f14fb602SLionel Sambuc
47*f14fb602SLionel Sambuc #include <lib/libsa/stand.h>
48*f14fb602SLionel Sambuc #include "net.h"
49*f14fb602SLionel Sambuc #include "netif.h"
50*f14fb602SLionel Sambuc #include "nfs.h"
51*f14fb602SLionel Sambuc #include "rpc.h"
52*f14fb602SLionel Sambuc
53*f14fb602SLionel Sambuc /* Define our own NFS attributes. */
54*f14fb602SLionel Sambuc struct nfsv2_fattrs {
55*f14fb602SLionel Sambuc n_long fa_type;
56*f14fb602SLionel Sambuc n_long fa_mode;
57*f14fb602SLionel Sambuc n_long fa_nlink;
58*f14fb602SLionel Sambuc n_long fa_uid;
59*f14fb602SLionel Sambuc n_long fa_gid;
60*f14fb602SLionel Sambuc n_long fa_size;
61*f14fb602SLionel Sambuc n_long fa_blocksize;
62*f14fb602SLionel Sambuc n_long fa_rdev;
63*f14fb602SLionel Sambuc n_long fa_blocks;
64*f14fb602SLionel Sambuc n_long fa_fsid;
65*f14fb602SLionel Sambuc n_long fa_fileid;
66*f14fb602SLionel Sambuc struct nfsv2_time fa_atime;
67*f14fb602SLionel Sambuc struct nfsv2_time fa_mtime;
68*f14fb602SLionel Sambuc struct nfsv2_time fa_ctime;
69*f14fb602SLionel Sambuc };
70*f14fb602SLionel Sambuc
71*f14fb602SLionel Sambuc
72*f14fb602SLionel Sambuc struct nfs_read_args {
73*f14fb602SLionel Sambuc u_char fh[NFS_FHSIZE];
74*f14fb602SLionel Sambuc n_long off;
75*f14fb602SLionel Sambuc n_long len;
76*f14fb602SLionel Sambuc n_long xxx; /* XXX what's this for? */
77*f14fb602SLionel Sambuc };
78*f14fb602SLionel Sambuc
79*f14fb602SLionel Sambuc /* Data part of nfs rpc reply (also the largest thing we receive) */
80*f14fb602SLionel Sambuc #define NFSREAD_SIZE 1024
81*f14fb602SLionel Sambuc struct nfs_read_repl {
82*f14fb602SLionel Sambuc n_long errno;
83*f14fb602SLionel Sambuc struct nfsv2_fattrs fa;
84*f14fb602SLionel Sambuc n_long count;
85*f14fb602SLionel Sambuc u_char data[NFSREAD_SIZE];
86*f14fb602SLionel Sambuc };
87*f14fb602SLionel Sambuc
88*f14fb602SLionel Sambuc #ifndef NFS_NOSYMLINK
89*f14fb602SLionel Sambuc struct nfs_readlnk_repl {
90*f14fb602SLionel Sambuc n_long errno;
91*f14fb602SLionel Sambuc n_long len;
92*f14fb602SLionel Sambuc char path[NFS_MAXPATHLEN];
93*f14fb602SLionel Sambuc };
94*f14fb602SLionel Sambuc #endif
95*f14fb602SLionel Sambuc
96*f14fb602SLionel Sambuc struct nfs_iodesc {
97*f14fb602SLionel Sambuc struct iodesc *iodesc;
98*f14fb602SLionel Sambuc off_t off;
99*f14fb602SLionel Sambuc u_char fh[NFS_FHSIZE];
100*f14fb602SLionel Sambuc struct nfsv2_fattrs fa; /* all in network order */
101*f14fb602SLionel Sambuc };
102*f14fb602SLionel Sambuc
103*f14fb602SLionel Sambuc int nfs_getrootfh(struct iodesc *, char *, u_char *);
104*f14fb602SLionel Sambuc int nfs_lookupfh(struct nfs_iodesc *, const char *, int,
105*f14fb602SLionel Sambuc struct nfs_iodesc *);
106*f14fb602SLionel Sambuc #ifndef NFS_NOSYMLINK
107*f14fb602SLionel Sambuc int nfs_readlink(struct nfs_iodesc *, char *);
108*f14fb602SLionel Sambuc #endif
109*f14fb602SLionel Sambuc ssize_t nfs_readdata(struct nfs_iodesc *, off_t, void *, size_t);
110*f14fb602SLionel Sambuc
111*f14fb602SLionel Sambuc /*
112*f14fb602SLionel Sambuc * Fetch the root file handle (call mount daemon)
113*f14fb602SLionel Sambuc * Return zero or error number.
114*f14fb602SLionel Sambuc */
115*f14fb602SLionel Sambuc int
nfs_getrootfh(struct iodesc * d,char * path,u_char * fhp)116*f14fb602SLionel Sambuc nfs_getrootfh(struct iodesc *d, char *path, u_char *fhp)
117*f14fb602SLionel Sambuc {
118*f14fb602SLionel Sambuc size_t len;
119*f14fb602SLionel Sambuc struct args {
120*f14fb602SLionel Sambuc n_long len;
121*f14fb602SLionel Sambuc char path[FNAME_SIZE];
122*f14fb602SLionel Sambuc } *args;
123*f14fb602SLionel Sambuc struct repl {
124*f14fb602SLionel Sambuc n_long errno;
125*f14fb602SLionel Sambuc u_char fh[NFS_FHSIZE];
126*f14fb602SLionel Sambuc } *repl;
127*f14fb602SLionel Sambuc struct {
128*f14fb602SLionel Sambuc n_long h[RPC_HEADER_WORDS];
129*f14fb602SLionel Sambuc struct args d;
130*f14fb602SLionel Sambuc } sdata;
131*f14fb602SLionel Sambuc struct {
132*f14fb602SLionel Sambuc n_long h[RPC_HEADER_WORDS];
133*f14fb602SLionel Sambuc struct repl d;
134*f14fb602SLionel Sambuc } rdata;
135*f14fb602SLionel Sambuc ssize_t cc;
136*f14fb602SLionel Sambuc
137*f14fb602SLionel Sambuc #ifdef NFS_DEBUG
138*f14fb602SLionel Sambuc if (debug)
139*f14fb602SLionel Sambuc printf("nfs_getrootfh: %s\n", path);
140*f14fb602SLionel Sambuc #endif
141*f14fb602SLionel Sambuc
142*f14fb602SLionel Sambuc args = &sdata.d;
143*f14fb602SLionel Sambuc repl = &rdata.d;
144*f14fb602SLionel Sambuc
145*f14fb602SLionel Sambuc memset(args, 0, sizeof(*args));
146*f14fb602SLionel Sambuc len = strlen(path);
147*f14fb602SLionel Sambuc if (len > sizeof(args->path))
148*f14fb602SLionel Sambuc len = sizeof(args->path);
149*f14fb602SLionel Sambuc args->len = htonl(len);
150*f14fb602SLionel Sambuc memcpy(args->path, path, len);
151*f14fb602SLionel Sambuc len = 4 + roundup(len, 4);
152*f14fb602SLionel Sambuc
153*f14fb602SLionel Sambuc cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
154*f14fb602SLionel Sambuc args, len, repl, sizeof(*repl));
155*f14fb602SLionel Sambuc if (cc == -1) {
156*f14fb602SLionel Sambuc /* errno was set by rpc_call */
157*f14fb602SLionel Sambuc return (errno);
158*f14fb602SLionel Sambuc }
159*f14fb602SLionel Sambuc if (cc < 4)
160*f14fb602SLionel Sambuc return (EBADRPC);
161*f14fb602SLionel Sambuc if (repl->errno)
162*f14fb602SLionel Sambuc return (ntohl(repl->errno));
163*f14fb602SLionel Sambuc memcpy(fhp, repl->fh, sizeof(repl->fh));
164*f14fb602SLionel Sambuc return (0);
165*f14fb602SLionel Sambuc }
166*f14fb602SLionel Sambuc
167*f14fb602SLionel Sambuc /*
168*f14fb602SLionel Sambuc * Lookup a file. Store handle and attributes.
169*f14fb602SLionel Sambuc * Return zero or error number.
170*f14fb602SLionel Sambuc */
171*f14fb602SLionel Sambuc int
nfs_lookupfh(struct nfs_iodesc * d,const char * name,int len,struct nfs_iodesc * newfd)172*f14fb602SLionel Sambuc nfs_lookupfh(struct nfs_iodesc *d, const char *name, int len, struct nfs_iodesc *newfd)
173*f14fb602SLionel Sambuc {
174*f14fb602SLionel Sambuc int rlen;
175*f14fb602SLionel Sambuc struct args {
176*f14fb602SLionel Sambuc u_char fh[NFS_FHSIZE];
177*f14fb602SLionel Sambuc n_long len;
178*f14fb602SLionel Sambuc char name[FNAME_SIZE];
179*f14fb602SLionel Sambuc } *args;
180*f14fb602SLionel Sambuc struct repl {
181*f14fb602SLionel Sambuc n_long errno;
182*f14fb602SLionel Sambuc u_char fh[NFS_FHSIZE];
183*f14fb602SLionel Sambuc struct nfsv2_fattrs fa;
184*f14fb602SLionel Sambuc } *repl;
185*f14fb602SLionel Sambuc struct {
186*f14fb602SLionel Sambuc n_long h[RPC_HEADER_WORDS];
187*f14fb602SLionel Sambuc struct args d;
188*f14fb602SLionel Sambuc } sdata;
189*f14fb602SLionel Sambuc struct {
190*f14fb602SLionel Sambuc n_long h[RPC_HEADER_WORDS];
191*f14fb602SLionel Sambuc struct repl d;
192*f14fb602SLionel Sambuc } rdata;
193*f14fb602SLionel Sambuc ssize_t cc;
194*f14fb602SLionel Sambuc
195*f14fb602SLionel Sambuc #ifdef NFS_DEBUG
196*f14fb602SLionel Sambuc if (debug)
197*f14fb602SLionel Sambuc printf("lookupfh: called\n");
198*f14fb602SLionel Sambuc #endif
199*f14fb602SLionel Sambuc
200*f14fb602SLionel Sambuc args = &sdata.d;
201*f14fb602SLionel Sambuc repl = &rdata.d;
202*f14fb602SLionel Sambuc
203*f14fb602SLionel Sambuc memset(args, 0, sizeof(*args));
204*f14fb602SLionel Sambuc memcpy(args->fh, d->fh, sizeof(args->fh));
205*f14fb602SLionel Sambuc if ((size_t)len > sizeof(args->name))
206*f14fb602SLionel Sambuc len = sizeof(args->name);
207*f14fb602SLionel Sambuc memcpy(args->name, name, len);
208*f14fb602SLionel Sambuc args->len = htonl(len);
209*f14fb602SLionel Sambuc len = 4 + roundup(len, 4);
210*f14fb602SLionel Sambuc len += NFS_FHSIZE;
211*f14fb602SLionel Sambuc
212*f14fb602SLionel Sambuc rlen = sizeof(*repl);
213*f14fb602SLionel Sambuc
214*f14fb602SLionel Sambuc cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
215*f14fb602SLionel Sambuc args, len, repl, rlen);
216*f14fb602SLionel Sambuc if (cc == -1)
217*f14fb602SLionel Sambuc return (errno); /* XXX - from rpc_call */
218*f14fb602SLionel Sambuc if (cc < 4)
219*f14fb602SLionel Sambuc return (EIO);
220*f14fb602SLionel Sambuc if (repl->errno) {
221*f14fb602SLionel Sambuc /* saerrno.h now matches NFS error numbers. */
222*f14fb602SLionel Sambuc return (ntohl(repl->errno));
223*f14fb602SLionel Sambuc }
224*f14fb602SLionel Sambuc memcpy(&newfd->fh, repl->fh, sizeof(newfd->fh));
225*f14fb602SLionel Sambuc memcpy(&newfd->fa, &repl->fa, sizeof(newfd->fa));
226*f14fb602SLionel Sambuc return (0);
227*f14fb602SLionel Sambuc }
228*f14fb602SLionel Sambuc
229*f14fb602SLionel Sambuc #ifndef NFS_NOSYMLINK
230*f14fb602SLionel Sambuc /*
231*f14fb602SLionel Sambuc * Get the destination of a symbolic link.
232*f14fb602SLionel Sambuc */
233*f14fb602SLionel Sambuc int
nfs_readlink(struct nfs_iodesc * d,char * buf)234*f14fb602SLionel Sambuc nfs_readlink(struct nfs_iodesc *d, char *buf)
235*f14fb602SLionel Sambuc {
236*f14fb602SLionel Sambuc struct {
237*f14fb602SLionel Sambuc n_long h[RPC_HEADER_WORDS];
238*f14fb602SLionel Sambuc u_char fh[NFS_FHSIZE];
239*f14fb602SLionel Sambuc } sdata;
240*f14fb602SLionel Sambuc struct {
241*f14fb602SLionel Sambuc n_long h[RPC_HEADER_WORDS];
242*f14fb602SLionel Sambuc struct nfs_readlnk_repl d;
243*f14fb602SLionel Sambuc } rdata;
244*f14fb602SLionel Sambuc ssize_t cc;
245*f14fb602SLionel Sambuc
246*f14fb602SLionel Sambuc #ifdef NFS_DEBUG
247*f14fb602SLionel Sambuc if (debug)
248*f14fb602SLionel Sambuc printf("readlink: called\n");
249*f14fb602SLionel Sambuc #endif
250*f14fb602SLionel Sambuc
251*f14fb602SLionel Sambuc memcpy(sdata.fh, d->fh, NFS_FHSIZE);
252*f14fb602SLionel Sambuc cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK,
253*f14fb602SLionel Sambuc sdata.fh, NFS_FHSIZE,
254*f14fb602SLionel Sambuc &rdata.d, sizeof(rdata.d));
255*f14fb602SLionel Sambuc if (cc == -1)
256*f14fb602SLionel Sambuc return (errno);
257*f14fb602SLionel Sambuc
258*f14fb602SLionel Sambuc if (cc < 4)
259*f14fb602SLionel Sambuc return (EIO);
260*f14fb602SLionel Sambuc
261*f14fb602SLionel Sambuc if (rdata.d.errno)
262*f14fb602SLionel Sambuc return (ntohl(rdata.d.errno));
263*f14fb602SLionel Sambuc
264*f14fb602SLionel Sambuc rdata.d.len = ntohl(rdata.d.len);
265*f14fb602SLionel Sambuc if (rdata.d.len > NFS_MAXPATHLEN)
266*f14fb602SLionel Sambuc return (ENAMETOOLONG);
267*f14fb602SLionel Sambuc
268*f14fb602SLionel Sambuc memcpy(buf, rdata.d.path, rdata.d.len);
269*f14fb602SLionel Sambuc buf[rdata.d.len] = 0;
270*f14fb602SLionel Sambuc return (0);
271*f14fb602SLionel Sambuc }
272*f14fb602SLionel Sambuc #endif
273*f14fb602SLionel Sambuc
274*f14fb602SLionel Sambuc /*
275*f14fb602SLionel Sambuc * Read data from a file.
276*f14fb602SLionel Sambuc * Return transfer count or -1 (and set errno)
277*f14fb602SLionel Sambuc */
278*f14fb602SLionel Sambuc ssize_t
nfs_readdata(struct nfs_iodesc * d,off_t off,void * addr,size_t len)279*f14fb602SLionel Sambuc nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len)
280*f14fb602SLionel Sambuc {
281*f14fb602SLionel Sambuc struct nfs_read_args *args;
282*f14fb602SLionel Sambuc struct nfs_read_repl *repl;
283*f14fb602SLionel Sambuc struct {
284*f14fb602SLionel Sambuc n_long h[RPC_HEADER_WORDS];
285*f14fb602SLionel Sambuc struct nfs_read_args d;
286*f14fb602SLionel Sambuc } sdata;
287*f14fb602SLionel Sambuc struct {
288*f14fb602SLionel Sambuc n_long h[RPC_HEADER_WORDS];
289*f14fb602SLionel Sambuc struct nfs_read_repl d;
290*f14fb602SLionel Sambuc } rdata;
291*f14fb602SLionel Sambuc ssize_t cc;
292*f14fb602SLionel Sambuc long x;
293*f14fb602SLionel Sambuc int hlen, rlen;
294*f14fb602SLionel Sambuc
295*f14fb602SLionel Sambuc args = &sdata.d;
296*f14fb602SLionel Sambuc repl = &rdata.d;
297*f14fb602SLionel Sambuc
298*f14fb602SLionel Sambuc memcpy(args->fh, d->fh, NFS_FHSIZE);
299*f14fb602SLionel Sambuc args->off = htonl((n_long)off);
300*f14fb602SLionel Sambuc if (len > NFSREAD_SIZE)
301*f14fb602SLionel Sambuc len = NFSREAD_SIZE;
302*f14fb602SLionel Sambuc args->len = htonl((n_long)len);
303*f14fb602SLionel Sambuc args->xxx = htonl((n_long)0);
304*f14fb602SLionel Sambuc hlen = sizeof(*repl) - NFSREAD_SIZE;
305*f14fb602SLionel Sambuc
306*f14fb602SLionel Sambuc cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ,
307*f14fb602SLionel Sambuc args, sizeof(*args),
308*f14fb602SLionel Sambuc repl, sizeof(*repl));
309*f14fb602SLionel Sambuc if (cc == -1) {
310*f14fb602SLionel Sambuc /* errno was already set by rpc_call */
311*f14fb602SLionel Sambuc return (-1);
312*f14fb602SLionel Sambuc }
313*f14fb602SLionel Sambuc if (cc < hlen) {
314*f14fb602SLionel Sambuc errno = EBADRPC;
315*f14fb602SLionel Sambuc return (-1);
316*f14fb602SLionel Sambuc }
317*f14fb602SLionel Sambuc if (repl->errno) {
318*f14fb602SLionel Sambuc errno = ntohl(repl->errno);
319*f14fb602SLionel Sambuc return (-1);
320*f14fb602SLionel Sambuc }
321*f14fb602SLionel Sambuc rlen = cc - hlen;
322*f14fb602SLionel Sambuc x = ntohl(repl->count);
323*f14fb602SLionel Sambuc if (rlen < x) {
324*f14fb602SLionel Sambuc printf("nfsread: short packet, %d < %ld\n", rlen, x);
325*f14fb602SLionel Sambuc errno = EBADRPC;
326*f14fb602SLionel Sambuc return (-1);
327*f14fb602SLionel Sambuc }
328*f14fb602SLionel Sambuc memcpy(addr, repl->data, x);
329*f14fb602SLionel Sambuc return (x);
330*f14fb602SLionel Sambuc }
331*f14fb602SLionel Sambuc
332*f14fb602SLionel Sambuc /*
333*f14fb602SLionel Sambuc * Open a file.
334*f14fb602SLionel Sambuc * return zero or error number
335*f14fb602SLionel Sambuc */
336*f14fb602SLionel Sambuc __compactcall int
nfs_open(const char * path,struct open_file * f)337*f14fb602SLionel Sambuc nfs_open(const char *path, struct open_file *f)
338*f14fb602SLionel Sambuc {
339*f14fb602SLionel Sambuc static struct nfs_iodesc nfs_root_node;
340*f14fb602SLionel Sambuc struct iodesc *desc;
341*f14fb602SLionel Sambuc struct nfs_iodesc *currfd;
342*f14fb602SLionel Sambuc const char *cp;
343*f14fb602SLionel Sambuc #ifndef NFS_NOSYMLINK
344*f14fb602SLionel Sambuc struct nfs_iodesc *newfd;
345*f14fb602SLionel Sambuc struct nfsv2_fattrs *fa;
346*f14fb602SLionel Sambuc const char *ncp;
347*f14fb602SLionel Sambuc int c;
348*f14fb602SLionel Sambuc char namebuf[NFS_MAXPATHLEN + 1];
349*f14fb602SLionel Sambuc char linkbuf[NFS_MAXPATHLEN + 1];
350*f14fb602SLionel Sambuc int nlinks = 0;
351*f14fb602SLionel Sambuc #endif
352*f14fb602SLionel Sambuc int error;
353*f14fb602SLionel Sambuc
354*f14fb602SLionel Sambuc #ifdef NFS_DEBUG
355*f14fb602SLionel Sambuc if (debug)
356*f14fb602SLionel Sambuc printf("nfs_open: %s\n", path);
357*f14fb602SLionel Sambuc #endif
358*f14fb602SLionel Sambuc if (!rootpath[0]) {
359*f14fb602SLionel Sambuc printf("no rootpath, no nfs\n");
360*f14fb602SLionel Sambuc return (ENXIO);
361*f14fb602SLionel Sambuc }
362*f14fb602SLionel Sambuc
363*f14fb602SLionel Sambuc if (!(desc = socktodesc(*(int *)(f->f_devdata))))
364*f14fb602SLionel Sambuc return (EINVAL);
365*f14fb602SLionel Sambuc
366*f14fb602SLionel Sambuc /* Bind to a reserved port. */
367*f14fb602SLionel Sambuc desc->myport = htons(--rpc_port);
368*f14fb602SLionel Sambuc desc->destip = rootip;
369*f14fb602SLionel Sambuc if ((error = nfs_getrootfh(desc, rootpath, nfs_root_node.fh)))
370*f14fb602SLionel Sambuc return (error);
371*f14fb602SLionel Sambuc nfs_root_node.iodesc = desc;
372*f14fb602SLionel Sambuc
373*f14fb602SLionel Sambuc #ifndef NFS_NOSYMLINK
374*f14fb602SLionel Sambuc /* Fake up attributes for the root dir. */
375*f14fb602SLionel Sambuc fa = &nfs_root_node.fa;
376*f14fb602SLionel Sambuc fa->fa_type = htonl(NFDIR);
377*f14fb602SLionel Sambuc fa->fa_mode = htonl(0755);
378*f14fb602SLionel Sambuc fa->fa_nlink = htonl(2);
379*f14fb602SLionel Sambuc
380*f14fb602SLionel Sambuc currfd = &nfs_root_node;
381*f14fb602SLionel Sambuc newfd = 0;
382*f14fb602SLionel Sambuc
383*f14fb602SLionel Sambuc cp = path;
384*f14fb602SLionel Sambuc while (*cp) {
385*f14fb602SLionel Sambuc /*
386*f14fb602SLionel Sambuc * Remove extra separators
387*f14fb602SLionel Sambuc */
388*f14fb602SLionel Sambuc while (*cp == '/')
389*f14fb602SLionel Sambuc cp++;
390*f14fb602SLionel Sambuc
391*f14fb602SLionel Sambuc if (*cp == '\0')
392*f14fb602SLionel Sambuc break;
393*f14fb602SLionel Sambuc /*
394*f14fb602SLionel Sambuc * Check that current node is a directory.
395*f14fb602SLionel Sambuc */
396*f14fb602SLionel Sambuc if (currfd->fa.fa_type != htonl(NFDIR)) {
397*f14fb602SLionel Sambuc error = ENOTDIR;
398*f14fb602SLionel Sambuc goto out;
399*f14fb602SLionel Sambuc }
400*f14fb602SLionel Sambuc
401*f14fb602SLionel Sambuc /* allocate file system specific data structure */
402*f14fb602SLionel Sambuc newfd = alloc(sizeof(*newfd));
403*f14fb602SLionel Sambuc newfd->iodesc = currfd->iodesc;
404*f14fb602SLionel Sambuc newfd->off = 0;
405*f14fb602SLionel Sambuc
406*f14fb602SLionel Sambuc /*
407*f14fb602SLionel Sambuc * Get next component of path name.
408*f14fb602SLionel Sambuc */
409*f14fb602SLionel Sambuc {
410*f14fb602SLionel Sambuc int len = 0;
411*f14fb602SLionel Sambuc
412*f14fb602SLionel Sambuc ncp = cp;
413*f14fb602SLionel Sambuc while ((c = *cp) != '\0' && c != '/') {
414*f14fb602SLionel Sambuc if (++len > NFS_MAXNAMLEN) {
415*f14fb602SLionel Sambuc error = ENOENT;
416*f14fb602SLionel Sambuc goto out;
417*f14fb602SLionel Sambuc }
418*f14fb602SLionel Sambuc cp++;
419*f14fb602SLionel Sambuc }
420*f14fb602SLionel Sambuc }
421*f14fb602SLionel Sambuc
422*f14fb602SLionel Sambuc /* lookup a file handle */
423*f14fb602SLionel Sambuc error = nfs_lookupfh(currfd, ncp, cp - ncp, newfd);
424*f14fb602SLionel Sambuc if (error)
425*f14fb602SLionel Sambuc goto out;
426*f14fb602SLionel Sambuc
427*f14fb602SLionel Sambuc /*
428*f14fb602SLionel Sambuc * Check for symbolic link
429*f14fb602SLionel Sambuc */
430*f14fb602SLionel Sambuc if (newfd->fa.fa_type == htonl(NFLNK)) {
431*f14fb602SLionel Sambuc int link_len, len;
432*f14fb602SLionel Sambuc
433*f14fb602SLionel Sambuc error = nfs_readlink(newfd, linkbuf);
434*f14fb602SLionel Sambuc if (error)
435*f14fb602SLionel Sambuc goto out;
436*f14fb602SLionel Sambuc
437*f14fb602SLionel Sambuc link_len = strlen(linkbuf);
438*f14fb602SLionel Sambuc len = strlen(cp);
439*f14fb602SLionel Sambuc
440*f14fb602SLionel Sambuc if (link_len + len > MAXPATHLEN
441*f14fb602SLionel Sambuc || ++nlinks > MAXSYMLINKS) {
442*f14fb602SLionel Sambuc error = ENOENT;
443*f14fb602SLionel Sambuc goto out;
444*f14fb602SLionel Sambuc }
445*f14fb602SLionel Sambuc
446*f14fb602SLionel Sambuc memcpy(&namebuf[link_len], cp, len + 1);
447*f14fb602SLionel Sambuc memcpy(namebuf, linkbuf, link_len);
448*f14fb602SLionel Sambuc
449*f14fb602SLionel Sambuc /*
450*f14fb602SLionel Sambuc * If absolute pathname, restart at root.
451*f14fb602SLionel Sambuc * If relative pathname, restart at parent directory.
452*f14fb602SLionel Sambuc */
453*f14fb602SLionel Sambuc cp = namebuf;
454*f14fb602SLionel Sambuc if (*cp == '/') {
455*f14fb602SLionel Sambuc if (currfd != &nfs_root_node)
456*f14fb602SLionel Sambuc dealloc(currfd, sizeof(*currfd));
457*f14fb602SLionel Sambuc currfd = &nfs_root_node;
458*f14fb602SLionel Sambuc }
459*f14fb602SLionel Sambuc
460*f14fb602SLionel Sambuc dealloc(newfd, sizeof(*newfd));
461*f14fb602SLionel Sambuc newfd = 0;
462*f14fb602SLionel Sambuc
463*f14fb602SLionel Sambuc continue;
464*f14fb602SLionel Sambuc }
465*f14fb602SLionel Sambuc
466*f14fb602SLionel Sambuc if (currfd != &nfs_root_node)
467*f14fb602SLionel Sambuc dealloc(currfd, sizeof(*currfd));
468*f14fb602SLionel Sambuc currfd = newfd;
469*f14fb602SLionel Sambuc newfd = 0;
470*f14fb602SLionel Sambuc }
471*f14fb602SLionel Sambuc
472*f14fb602SLionel Sambuc error = 0;
473*f14fb602SLionel Sambuc
474*f14fb602SLionel Sambuc out:
475*f14fb602SLionel Sambuc if (newfd)
476*f14fb602SLionel Sambuc dealloc(newfd, sizeof(*newfd));
477*f14fb602SLionel Sambuc #else
478*f14fb602SLionel Sambuc /* allocate file system specific data structure */
479*f14fb602SLionel Sambuc currfd = alloc(sizeof(*currfd));
480*f14fb602SLionel Sambuc currfd->iodesc = desc;
481*f14fb602SLionel Sambuc currfd->off = 0;
482*f14fb602SLionel Sambuc
483*f14fb602SLionel Sambuc cp = path;
484*f14fb602SLionel Sambuc /*
485*f14fb602SLionel Sambuc * Remove extra separators
486*f14fb602SLionel Sambuc */
487*f14fb602SLionel Sambuc while (*cp == '/')
488*f14fb602SLionel Sambuc cp++;
489*f14fb602SLionel Sambuc
490*f14fb602SLionel Sambuc /* XXX: Check for empty path here? */
491*f14fb602SLionel Sambuc
492*f14fb602SLionel Sambuc error = nfs_lookupfh(&nfs_root_node, cp, strlen(cp), currfd);
493*f14fb602SLionel Sambuc #endif
494*f14fb602SLionel Sambuc if (!error) {
495*f14fb602SLionel Sambuc f->f_fsdata = (void *)currfd;
496*f14fb602SLionel Sambuc fsmod = "nfs";
497*f14fb602SLionel Sambuc return (0);
498*f14fb602SLionel Sambuc }
499*f14fb602SLionel Sambuc
500*f14fb602SLionel Sambuc #ifdef NFS_DEBUG
501*f14fb602SLionel Sambuc if (debug)
502*f14fb602SLionel Sambuc printf("nfs_open: %s lookupfh failed: %s\n",
503*f14fb602SLionel Sambuc path, strerror(error));
504*f14fb602SLionel Sambuc #endif
505*f14fb602SLionel Sambuc #ifndef NFS_NOSYMLINK
506*f14fb602SLionel Sambuc if (currfd != &nfs_root_node)
507*f14fb602SLionel Sambuc #endif
508*f14fb602SLionel Sambuc dealloc(currfd, sizeof(*currfd));
509*f14fb602SLionel Sambuc
510*f14fb602SLionel Sambuc return (error);
511*f14fb602SLionel Sambuc }
512*f14fb602SLionel Sambuc
513*f14fb602SLionel Sambuc __compactcall int
nfs_close(struct open_file * f)514*f14fb602SLionel Sambuc nfs_close(struct open_file *f)
515*f14fb602SLionel Sambuc {
516*f14fb602SLionel Sambuc struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
517*f14fb602SLionel Sambuc
518*f14fb602SLionel Sambuc #ifdef NFS_DEBUG
519*f14fb602SLionel Sambuc if (debug)
520*f14fb602SLionel Sambuc printf("nfs_close: fp=0x%lx\n", (u_long)fp);
521*f14fb602SLionel Sambuc #endif
522*f14fb602SLionel Sambuc
523*f14fb602SLionel Sambuc if (fp)
524*f14fb602SLionel Sambuc dealloc(fp, sizeof(struct nfs_iodesc));
525*f14fb602SLionel Sambuc f->f_fsdata = (void *)0;
526*f14fb602SLionel Sambuc
527*f14fb602SLionel Sambuc return (0);
528*f14fb602SLionel Sambuc }
529*f14fb602SLionel Sambuc
530*f14fb602SLionel Sambuc /*
531*f14fb602SLionel Sambuc * read a portion of a file
532*f14fb602SLionel Sambuc */
533*f14fb602SLionel Sambuc __compactcall int
nfs_read(struct open_file * f,void * buf,size_t size,size_t * resid)534*f14fb602SLionel Sambuc nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid)
535*f14fb602SLionel Sambuc /* resid: out */
536*f14fb602SLionel Sambuc {
537*f14fb602SLionel Sambuc struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
538*f14fb602SLionel Sambuc ssize_t cc;
539*f14fb602SLionel Sambuc char *addr = buf;
540*f14fb602SLionel Sambuc
541*f14fb602SLionel Sambuc #ifdef NFS_DEBUG
542*f14fb602SLionel Sambuc if (debug)
543*f14fb602SLionel Sambuc printf("nfs_read: size=%lu off=%d\n", (u_long)size,
544*f14fb602SLionel Sambuc (int)fp->off);
545*f14fb602SLionel Sambuc #endif
546*f14fb602SLionel Sambuc while ((int)size > 0) {
547*f14fb602SLionel Sambuc #if !defined(LIBSA_NO_TWIDDLE)
548*f14fb602SLionel Sambuc twiddle();
549*f14fb602SLionel Sambuc #endif
550*f14fb602SLionel Sambuc cc = nfs_readdata(fp, fp->off, (void *)addr, size);
551*f14fb602SLionel Sambuc /* XXX maybe should retry on certain errors */
552*f14fb602SLionel Sambuc if (cc == -1) {
553*f14fb602SLionel Sambuc #ifdef NFS_DEBUG
554*f14fb602SLionel Sambuc if (debug)
555*f14fb602SLionel Sambuc printf("nfs_read: read: %s", strerror(errno));
556*f14fb602SLionel Sambuc #endif
557*f14fb602SLionel Sambuc return (errno); /* XXX - from nfs_readdata */
558*f14fb602SLionel Sambuc }
559*f14fb602SLionel Sambuc if (cc == 0) {
560*f14fb602SLionel Sambuc #ifdef NFS_DEBUG
561*f14fb602SLionel Sambuc if (debug)
562*f14fb602SLionel Sambuc printf("nfs_read: hit EOF unexpectantly");
563*f14fb602SLionel Sambuc #endif
564*f14fb602SLionel Sambuc goto ret;
565*f14fb602SLionel Sambuc }
566*f14fb602SLionel Sambuc fp->off += cc;
567*f14fb602SLionel Sambuc addr += cc;
568*f14fb602SLionel Sambuc size -= cc;
569*f14fb602SLionel Sambuc }
570*f14fb602SLionel Sambuc ret:
571*f14fb602SLionel Sambuc if (resid)
572*f14fb602SLionel Sambuc *resid = size;
573*f14fb602SLionel Sambuc
574*f14fb602SLionel Sambuc return (0);
575*f14fb602SLionel Sambuc }
576*f14fb602SLionel Sambuc
577*f14fb602SLionel Sambuc /*
578*f14fb602SLionel Sambuc * Not implemented.
579*f14fb602SLionel Sambuc */
580*f14fb602SLionel Sambuc __compactcall int
nfs_write(struct open_file * f,void * buf,size_t size,size_t * resid)581*f14fb602SLionel Sambuc nfs_write(struct open_file *f, void *buf, size_t size, size_t *resid)
582*f14fb602SLionel Sambuc /* resid: out */
583*f14fb602SLionel Sambuc {
584*f14fb602SLionel Sambuc
585*f14fb602SLionel Sambuc return (EROFS);
586*f14fb602SLionel Sambuc }
587*f14fb602SLionel Sambuc
588*f14fb602SLionel Sambuc __compactcall off_t
nfs_seek(struct open_file * f,off_t offset,int where)589*f14fb602SLionel Sambuc nfs_seek(struct open_file *f, off_t offset, int where)
590*f14fb602SLionel Sambuc {
591*f14fb602SLionel Sambuc struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata;
592*f14fb602SLionel Sambuc n_long size = ntohl(d->fa.fa_size);
593*f14fb602SLionel Sambuc
594*f14fb602SLionel Sambuc switch (where) {
595*f14fb602SLionel Sambuc case SEEK_SET:
596*f14fb602SLionel Sambuc d->off = offset;
597*f14fb602SLionel Sambuc break;
598*f14fb602SLionel Sambuc case SEEK_CUR:
599*f14fb602SLionel Sambuc d->off += offset;
600*f14fb602SLionel Sambuc break;
601*f14fb602SLionel Sambuc case SEEK_END:
602*f14fb602SLionel Sambuc d->off = size - offset;
603*f14fb602SLionel Sambuc break;
604*f14fb602SLionel Sambuc default:
605*f14fb602SLionel Sambuc return (-1);
606*f14fb602SLionel Sambuc }
607*f14fb602SLionel Sambuc
608*f14fb602SLionel Sambuc return (d->off);
609*f14fb602SLionel Sambuc }
610*f14fb602SLionel Sambuc
611*f14fb602SLionel Sambuc /* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */
612*f14fb602SLionel Sambuc const int nfs_stat_types[8] = {
613*f14fb602SLionel Sambuc 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0 };
614*f14fb602SLionel Sambuc
615*f14fb602SLionel Sambuc __compactcall int
nfs_stat(struct open_file * f,struct stat * sb)616*f14fb602SLionel Sambuc nfs_stat(struct open_file *f, struct stat *sb)
617*f14fb602SLionel Sambuc {
618*f14fb602SLionel Sambuc struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
619*f14fb602SLionel Sambuc n_long ftype, mode;
620*f14fb602SLionel Sambuc
621*f14fb602SLionel Sambuc ftype = ntohl(fp->fa.fa_type);
622*f14fb602SLionel Sambuc mode = ntohl(fp->fa.fa_mode);
623*f14fb602SLionel Sambuc mode |= nfs_stat_types[ftype & 7];
624*f14fb602SLionel Sambuc
625*f14fb602SLionel Sambuc sb->st_mode = mode;
626*f14fb602SLionel Sambuc sb->st_nlink = ntohl(fp->fa.fa_nlink);
627*f14fb602SLionel Sambuc sb->st_uid = ntohl(fp->fa.fa_uid);
628*f14fb602SLionel Sambuc sb->st_gid = ntohl(fp->fa.fa_gid);
629*f14fb602SLionel Sambuc sb->st_size = ntohl(fp->fa.fa_size);
630*f14fb602SLionel Sambuc
631*f14fb602SLionel Sambuc return (0);
632*f14fb602SLionel Sambuc }
633*f14fb602SLionel Sambuc
634*f14fb602SLionel Sambuc #if defined(LIBSA_ENABLE_LS_OP)
635*f14fb602SLionel Sambuc __compactcall void
nfs_ls(struct open_file * f,const char * pattern)636*f14fb602SLionel Sambuc nfs_ls(struct open_file *f, const char *pattern)
637*f14fb602SLionel Sambuc {
638*f14fb602SLionel Sambuc printf("Currently ls command is unsupported by nfs\n");
639*f14fb602SLionel Sambuc return;
640*f14fb602SLionel Sambuc }
641*f14fb602SLionel Sambuc #endif
642