nfs.c revision 1.4 1 1.4 cgd /* $NetBSD: nfs.c,v 1.4 1994/10/26 05:44:55 cgd Exp $ */
2 1.4 cgd
3 1.1 brezak /*-
4 1.1 brezak * Copyright (c) 1993 John Brezak
5 1.1 brezak * All rights reserved.
6 1.1 brezak *
7 1.1 brezak * Redistribution and use in source and binary forms, with or without
8 1.1 brezak * modification, are permitted provided that the following conditions
9 1.1 brezak * are met:
10 1.1 brezak * 1. Redistributions of source code must retain the above copyright
11 1.1 brezak * notice, this list of conditions and the following disclaimer.
12 1.1 brezak * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 brezak * notice, this list of conditions and the following disclaimer in the
14 1.1 brezak * documentation and/or other materials provided with the distribution.
15 1.1 brezak * 3. The name of the author may not be used to endorse or promote products
16 1.1 brezak * derived from this software without specific prior written permission.
17 1.1 brezak *
18 1.1 brezak * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 1.1 brezak * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 1.1 brezak * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 1.1 brezak * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 1.1 brezak * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 1.1 brezak * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 1.1 brezak * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 1.1 brezak * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 1.1 brezak * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 1.1 brezak * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 1.1 brezak * POSSIBILITY OF SUCH DAMAGE.
29 1.1 brezak */
30 1.1 brezak
31 1.1 brezak #include <sys/param.h>
32 1.1 brezak #include <sys/time.h>
33 1.1 brezak #include <sys/socket.h>
34 1.1 brezak #include <sys/stat.h>
35 1.1 brezak #include <string.h>
36 1.1 brezak
37 1.1 brezak #include <netinet/in.h>
38 1.1 brezak #include <netinet/in_systm.h>
39 1.1 brezak
40 1.1 brezak #include <nfs/rpcv2.h>
41 1.1 brezak #include <nfs/nfsv2.h>
42 1.1 brezak #undef NFSX_FATTR
43 1.1 brezak
44 1.1 brezak #include "stand.h"
45 1.1 brezak #include "net.h"
46 1.1 brezak #include "netif.h"
47 1.1 brezak #include "nfs.h"
48 1.1 brezak #include "rpc.h"
49 1.1 brezak
50 1.1 brezak struct nfs_call_data {
51 1.1 brezak u_char fh[NFS_FHSIZE];
52 1.1 brezak u_long off;
53 1.1 brezak u_long len;
54 1.1 brezak u_long xxx; /* XXX what's this for? */
55 1.1 brezak };
56 1.1 brezak
57 1.1 brezak /* Data part of nfs rpc reply (also the largest thing we receive) */
58 1.1 brezak struct nfs_reply_data {
59 1.1 brezak u_long errno;
60 1.1 brezak #ifndef NFSX_FATTR
61 1.1 brezak struct nfsv2_fattr fa;
62 1.1 brezak #else
63 1.1 brezak u_char fa[NFSX_FATTR(0)];
64 1.1 brezak #endif
65 1.1 brezak u_long count;
66 1.1 brezak u_char data[1200];
67 1.1 brezak };
68 1.1 brezak #define NFSREAD_SIZE sizeof(((struct nfs_reply_data *)0)->data)
69 1.1 brezak
70 1.1 brezak /* max number of nfs reads pending */
71 1.1 brezak #define NFS_COUNT 10
72 1.1 brezak
73 1.1 brezak static struct nfsstate {
74 1.1 brezak u_long off;
75 1.1 brezak u_long len;
76 1.1 brezak int done;
77 1.1 brezak void *addr;
78 1.1 brezak u_long xid;
79 1.1 brezak } nfsstate[NFS_COUNT];
80 1.1 brezak
81 1.1 brezak static u_long nfscc;
82 1.1 brezak
83 1.1 brezak struct nfs_iodesc {
84 1.1 brezak off_t off;
85 1.1 brezak size_t size;
86 1.1 brezak u_char *fh;
87 1.1 brezak struct iodesc *iodesc;
88 1.1 brezak };
89 1.1 brezak
90 1.1 brezak /* Fetch (mount) file handle */
91 1.1 brezak static int
92 1.1 brezak getmountfh(d, path, fhp)
93 1.1 brezak register struct iodesc *d;
94 1.1 brezak char *path;
95 1.1 brezak u_char *fhp;
96 1.1 brezak {
97 1.1 brezak register int len;
98 1.1 brezak struct {
99 1.1 brezak u_long len;
100 1.1 brezak char path[FNAME_SIZE];
101 1.1 brezak } sdata;
102 1.1 brezak struct {
103 1.1 brezak u_long errno;
104 1.1 brezak u_char fh[NFS_FHSIZE];
105 1.1 brezak } rdata;
106 1.1 brezak int cc;
107 1.1 brezak
108 1.1 brezak #ifdef NFS_DEBUG
109 1.1 brezak if (debug)
110 1.1 brezak printf("getmountfh: called\n");
111 1.1 brezak #endif
112 1.1 brezak bzero(&sdata, sizeof(sdata));
113 1.1 brezak len = strlen(path);
114 1.1 brezak if (len > sizeof(sdata.path))
115 1.1 brezak len = sizeof(sdata.path);
116 1.1 brezak bcopy(path, sdata.path, len);
117 1.1 brezak sdata.len = htonl(len);
118 1.1 brezak len = sizeof(sdata) - sizeof(sdata.path) + roundup(len, sizeof(long));
119 1.1 brezak
120 1.1 brezak if ((cc = callrpc(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
121 1.1 brezak &sdata, len, &rdata, sizeof(rdata))) < 0)
122 1.1 brezak return(-1);
123 1.1 brezak if (cc < sizeof(rdata.errno))
124 1.1 brezak panic("getmountfh: callrpc small read");
125 1.1 brezak if (rdata.errno) {
126 1.1 brezak errno = ntohl(rdata.errno);
127 1.1 brezak return(-1);
128 1.1 brezak }
129 1.1 brezak bcopy(rdata.fh, fhp, sizeof(rdata.fh));
130 1.1 brezak return(0);
131 1.1 brezak }
132 1.1 brezak
133 1.1 brezak /* Fetch file timestamp and size */
134 1.1 brezak static int
135 1.1 brezak getnfsinfo(d, tp, sp, fp, mp, up, gp)
136 1.1 brezak register struct nfs_iodesc *d;
137 1.1 brezak register time_t *tp;
138 1.1 brezak u_long *sp, *fp;
139 1.1 brezak mode_t *mp;
140 1.1 brezak uid_t *up;
141 1.1 brezak gid_t *gp;
142 1.1 brezak {
143 1.1 brezak register int rlen;
144 1.1 brezak register u_long t;
145 1.1 brezak struct {
146 1.1 brezak u_long errno;
147 1.1 brezak struct nfsv2_fattr fa;
148 1.1 brezak } rdata;
149 1.1 brezak int cc;
150 1.1 brezak
151 1.1 brezak #ifdef NFS_DEBUG
152 1.1 brezak if (debug)
153 1.1 brezak printf("getnfsinfo: called\n");
154 1.1 brezak #endif
155 1.1 brezak rlen = sizeof(rdata);
156 1.1 brezak #if 0
157 1.1 brezak #ifdef NFSX_FATTR
158 1.1 brezak #if NFSX_FATTR(1) > NFSX_FATTR(0)
159 1.1 brezak /* nqnfs makes this more painful than it needs to be */
160 1.1 brezak rlen -= NFSX_FATTR(1) - NFSX_FATTR(0);
161 1.1 brezak #endif
162 1.1 brezak #endif
163 1.1 brezak #endif
164 1.1 brezak if ((cc = callrpc(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_GETATTR,
165 1.1 brezak d->fh, NFS_FHSIZE, &rdata, rlen)) < 0)
166 1.1 brezak return(-1);
167 1.1 brezak if (cc < sizeof(rdata.errno))
168 1.1 brezak panic("getnfsinfo: callrpc small read");
169 1.1 brezak if (rdata.errno) {
170 1.1 brezak errno = ntohl(rdata.errno);
171 1.1 brezak return(-1);
172 1.1 brezak }
173 1.1 brezak if (tp) {
174 1.2 glass *tp = ntohl(rdata.fa.fa_nfsmtime.nfs_sec);
175 1.2 glass t = ntohl(rdata.fa.fa_nfsatime.nfs_sec);
176 1.1 brezak if (*tp < t)
177 1.1 brezak *tp = t;
178 1.1 brezak }
179 1.1 brezak if (sp)
180 1.2 glass *sp = ntohl(rdata.fa.fa_nfssize);
181 1.1 brezak if (fp)
182 1.1 brezak *fp = ntohl(rdata.fa.fa_type);
183 1.1 brezak if (mp)
184 1.1 brezak *mp = ntohl(rdata.fa.fa_mode);
185 1.1 brezak if (up)
186 1.1 brezak *up = ntohl(rdata.fa.fa_uid);
187 1.1 brezak if (gp)
188 1.1 brezak *gp = ntohl(rdata.fa.fa_gid);
189 1.1 brezak return(0);
190 1.1 brezak }
191 1.1 brezak
192 1.1 brezak /* Lookup a file. Optionally return timestamp and size */
193 1.1 brezak static int
194 1.1 brezak lookupfh(d, name, fhp, tp, sp, fp)
195 1.1 brezak struct nfs_iodesc *d;
196 1.1 brezak char *name;
197 1.1 brezak u_char *fhp;
198 1.1 brezak time_t *tp;
199 1.1 brezak u_long *sp, *fp;
200 1.1 brezak {
201 1.1 brezak register int len, rlen;
202 1.1 brezak struct {
203 1.1 brezak u_char fh[NFS_FHSIZE];
204 1.1 brezak u_long len;
205 1.1 brezak char name[FNAME_SIZE];
206 1.1 brezak } sdata;
207 1.1 brezak struct {
208 1.1 brezak u_long errno;
209 1.1 brezak u_char fh[NFS_FHSIZE];
210 1.1 brezak struct nfsv2_fattr fa;
211 1.1 brezak } rdata;
212 1.1 brezak int cc;
213 1.1 brezak
214 1.1 brezak #ifdef NFS_DEBUG
215 1.1 brezak if (debug)
216 1.1 brezak printf("lookupfh: called\n");
217 1.1 brezak #endif
218 1.1 brezak
219 1.1 brezak bzero(&sdata, sizeof(sdata));
220 1.1 brezak bcopy(d->fh, sdata.fh, sizeof(sdata.fh));
221 1.1 brezak len = strlen(name);
222 1.1 brezak if (len > sizeof(sdata.name))
223 1.1 brezak len = sizeof(sdata.name);
224 1.1 brezak bcopy(name, sdata.name, len);
225 1.1 brezak sdata.len = htonl(len);
226 1.1 brezak len = sizeof(sdata) - sizeof(sdata.name) + roundup(len, sizeof(long));
227 1.1 brezak
228 1.1 brezak rlen = sizeof(rdata);
229 1.1 brezak #if 0
230 1.1 brezak #ifdef NFSX_FATTR
231 1.1 brezak #if NFSX_FATTR(1) > NFSX_FATTR(0)
232 1.1 brezak /* nqnfs makes this more painful than it needs to be */
233 1.1 brezak rlen -= NFSX_FATTR(1) - NFSX_FATTR(0);
234 1.1 brezak #endif
235 1.1 brezak #endif
236 1.1 brezak #endif
237 1.1 brezak if ((cc = callrpc(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
238 1.1 brezak &sdata, len, &rdata, rlen)) < 0)
239 1.1 brezak return (-1);
240 1.1 brezak if (cc < sizeof(rdata.errno))
241 1.1 brezak panic("lookupfh: callrpc small read");
242 1.1 brezak if (rdata.errno) {
243 1.1 brezak errno = ntohl(rdata.errno);
244 1.1 brezak return(-1);
245 1.1 brezak }
246 1.1 brezak bcopy(rdata.fh, fhp, sizeof(rdata.fh));
247 1.1 brezak if (tp)
248 1.2 glass *tp = ntohl(rdata.fa.fa_nfsctime.nfs_sec);
249 1.1 brezak if (sp)
250 1.2 glass *sp = ntohl(rdata.fa.fa_nfssize);
251 1.1 brezak if (fp)
252 1.1 brezak *fp = ntohl(rdata.fa.fa_type);
253 1.1 brezak return (0);
254 1.1 brezak }
255 1.1 brezak
256 1.1 brezak static int
257 1.1 brezak sendreaddata(d, pkt, len)
258 1.1 brezak register struct nfs_iodesc *d;
259 1.1 brezak register void *pkt;
260 1.1 brezak register int len;
261 1.1 brezak {
262 1.1 brezak register int i;
263 1.1 brezak register u_long cc;
264 1.1 brezak register struct rpc_call *rpc;
265 1.1 brezak register struct nfs_call_data *nfs;
266 1.1 brezak register struct nfsstate *ns;
267 1.1 brezak
268 1.1 brezak #ifdef NFS_DEBUG
269 1.1 brezak if (debug)
270 1.1 brezak printf("sendreaddata: called\n");
271 1.1 brezak #endif
272 1.1 brezak
273 1.1 brezak if (len != sizeof(*rpc) + sizeof(*nfs))
274 1.1 brezak panic("sendreaddata: bad buffer (%d != %d)",
275 1.1 brezak len, sizeof(*rpc) + sizeof(*nfs));
276 1.1 brezak rpc = pkt;
277 1.1 brezak nfs = (struct nfs_call_data *)(rpc + 1);
278 1.1 brezak for (i = 0, ns = nfsstate; i < NFS_COUNT; ++i, ++ns) {
279 1.1 brezak if (ns->done)
280 1.1 brezak continue;
281 1.1 brezak
282 1.1 brezak rpc->rp_xid = ns->xid;
283 1.1 brezak nfs->off = htonl(ns->off);
284 1.1 brezak nfs->len = htonl(ns->len);
285 1.1 brezak cc = sendudp(d->iodesc, rpc, len);
286 1.1 brezak
287 1.1 brezak if (cc != len)
288 1.1 brezak panic("sendreaddata: short write (%d != %d)", cc, len);
289 1.1 brezak }
290 1.1 brezak /* XXX we may have actually sent a lot more bytes... */
291 1.1 brezak
292 1.1 brezak return (len);
293 1.1 brezak }
294 1.1 brezak
295 1.1 brezak /* Returns char count if done else -1 (and errno == 0) */
296 1.1 brezak static int
297 1.1 brezak recvreaddata(d, pkt, len)
298 1.1 brezak register struct nfs_iodesc *d;
299 1.1 brezak register void *pkt;
300 1.1 brezak int len;
301 1.1 brezak {
302 1.1 brezak register int i;
303 1.1 brezak register struct rpc_reply *rpc;
304 1.1 brezak register struct nfs_reply_data *nfs;
305 1.1 brezak register struct nfsstate *ns;
306 1.1 brezak
307 1.1 brezak #ifdef NFS_DEBUG
308 1.1 brezak if (debug)
309 1.1 brezak printf("recvreaddata: called\n");
310 1.1 brezak #endif
311 1.1 brezak rpc = (struct rpc_reply *)checkudp(d->iodesc, pkt, &len);
312 1.1 brezak if (rpc == NULL || len < sizeof(*rpc)) {
313 1.1 brezak errno = 0;
314 1.1 brezak return (-1);
315 1.1 brezak }
316 1.1 brezak len -= sizeof(*rpc);
317 1.1 brezak
318 1.1 brezak NTOHL(rpc->rp_direction);
319 1.1 brezak NTOHL(rpc->rp_stat);
320 1.1 brezak
321 1.1 brezak if (rpc->rp_direction != REPLY || rpc->rp_stat != MSG_ACCEPTED) {
322 1.1 brezak errno = 0;
323 1.1 brezak return (-1);
324 1.1 brezak }
325 1.1 brezak
326 1.1 brezak for (i = 0, ns = nfsstate; i < NFS_COUNT; ++i, ++ns)
327 1.1 brezak if (rpc->rp_xid == ns->xid)
328 1.1 brezak break;
329 1.1 brezak if (i >= NFS_COUNT) {
330 1.1 brezak errno = 0;
331 1.1 brezak return (-1);
332 1.1 brezak }
333 1.1 brezak
334 1.1 brezak if (ns->done) {
335 1.1 brezak errno = 0;
336 1.1 brezak return (-1);
337 1.1 brezak }
338 1.1 brezak #ifdef NFS_DEBUG
339 1.1 brezak if (debug)
340 1.1 brezak printf("recvreaddata: ns=%x\n", (u_int)ns);
341 1.1 brezak #endif
342 1.1 brezak nfs = (struct nfs_reply_data *)(rpc + 1);
343 1.1 brezak if (len < sizeof(nfs->errno))
344 1.1 brezak panic("recvreaddata: bad read %d", len);
345 1.1 brezak if (nfs->errno) {
346 1.1 brezak errno = ntohl(nfs->errno);
347 1.1 brezak return (-1);
348 1.1 brezak }
349 1.1 brezak if (len < sizeof(*nfs) - sizeof(nfs->data))
350 1.1 brezak panic("recvreaddata: less than nfs sized %d", len);
351 1.1 brezak len -= sizeof(*nfs) - sizeof(nfs->data);
352 1.1 brezak
353 1.1 brezak if (len < nfs->count)
354 1.1 brezak panic("recvreaddata: short read (%d < %d)", len, nfs->count);
355 1.1 brezak len = nfs->count;
356 1.1 brezak if (len > ns->len)
357 1.1 brezak panic("recvreaddata: huge read (%d > %d)", len, ns->len);
358 1.1 brezak
359 1.1 brezak
360 1.1 brezak #ifdef NFS_DEBUG
361 1.1 brezak if (debug)
362 1.1 brezak printf("recvreaddata: read %d bytes.\n", len);
363 1.1 brezak #endif
364 1.1 brezak bcopy(nfs->data, ns->addr, len);
365 1.1 brezak ns->done = 1;
366 1.1 brezak nfscc += len;
367 1.1 brezak
368 1.1 brezak if (len < ns->len) {
369 1.1 brezak /* If first packet assume no more data to read */
370 1.1 brezak if (i == 0)
371 1.1 brezak return (0);
372 1.1 brezak
373 1.1 brezak /* Short read, assume we are at EOF */
374 1.1 brezak ++i;
375 1.1 brezak ++ns;
376 1.1 brezak while (i < NFS_COUNT) {
377 1.1 brezak ns->done = 1;
378 1.1 brezak ++i;
379 1.1 brezak ++ns;
380 1.1 brezak }
381 1.1 brezak }
382 1.1 brezak
383 1.1 brezak for (i = 0, ns = nfsstate; i < NFS_COUNT; ++i, ++ns)
384 1.1 brezak if (!ns->done) {
385 1.1 brezak errno = 0;
386 1.1 brezak return (-1);
387 1.1 brezak }
388 1.1 brezak
389 1.1 brezak /* Return data count (thus indicating success) */
390 1.1 brezak return (nfscc);
391 1.1 brezak }
392 1.1 brezak
393 1.1 brezak /* Read data from a file */
394 1.1 brezak static int
395 1.1 brezak readdata(d, off, addr, len)
396 1.1 brezak register struct nfs_iodesc *d;
397 1.3 brezak register off_t off;
398 1.1 brezak register void *addr;
399 1.1 brezak register u_long len;
400 1.1 brezak {
401 1.1 brezak register int i, cc;
402 1.1 brezak register struct rpc_call *rpc;
403 1.1 brezak register struct nfsstate *ns;
404 1.1 brezak struct {
405 1.1 brezak u_char header[HEADER_SIZE];
406 1.1 brezak struct rpc_call rpc;
407 1.1 brezak struct nfs_call_data nfs;
408 1.1 brezak } sdata;
409 1.1 brezak struct {
410 1.1 brezak u_char header[HEADER_SIZE];
411 1.1 brezak struct rpc_call rpc;
412 1.1 brezak struct nfs_reply_data nfs;
413 1.1 brezak } rdata;
414 1.1 brezak
415 1.1 brezak #ifdef NFS_DEBUG
416 1.1 brezak if (debug)
417 1.3 brezak printf("readdata: addr=%x, off=%d len=%d\n", (u_int)addr, (u_int)off, len);
418 1.1 brezak #endif
419 1.1 brezak if (len == 0)
420 1.1 brezak return (0);
421 1.1 brezak d->iodesc->destport = getport(d->iodesc, NFS_PROG, NFS_VER2);
422 1.1 brezak
423 1.1 brezak bzero(&sdata, sizeof(sdata));
424 1.1 brezak
425 1.1 brezak for (i = 0, ns = nfsstate; i < NFS_COUNT; ++i, ++ns) {
426 1.1 brezak if (len <= 0) {
427 1.1 brezak ns->done = 1;
428 1.1 brezak continue;
429 1.1 brezak }
430 1.1 brezak ns->done = 0;
431 1.1 brezak
432 1.1 brezak ns->xid = d->iodesc->xid;
433 1.1 brezak ++d->iodesc->xid;
434 1.1 brezak
435 1.3 brezak ns->off = (u_int)off;
436 1.1 brezak ns->len = len;
437 1.1 brezak if (ns->len > NFSREAD_SIZE)
438 1.1 brezak ns->len = NFSREAD_SIZE;
439 1.1 brezak #ifdef notdef
440 1.1 brezak /* XXX to align or not align? It doesn't seem to speed things up... */
441 1.1 brezak if ((ns->off % NFSREAD_SIZE) != 0)
442 1.1 brezak ns->len -= off % NFSREAD_SIZE;
443 1.1 brezak #endif
444 1.1 brezak
445 1.1 brezak off += ns->len;
446 1.1 brezak len -= ns->len;
447 1.1 brezak
448 1.1 brezak ns->addr = addr;
449 1.1 brezak addr += NFSREAD_SIZE;
450 1.1 brezak }
451 1.1 brezak
452 1.1 brezak rpc = &sdata.rpc;
453 1.1 brezak rpc->rp_rpcvers = htonl(RPC_MSG_VERSION);
454 1.1 brezak rpc->rp_prog = htonl(NFS_PROG);
455 1.1 brezak rpc->rp_vers = htonl(NFS_VER2);
456 1.1 brezak rpc->rp_proc = htonl(NFSPROC_READ);
457 1.1 brezak bcopy(d->fh, sdata.nfs.fh, sizeof(sdata.nfs.fh));
458 1.1 brezak
459 1.1 brezak nfscc = 0;
460 1.1 brezak cc = sendrecv(d->iodesc,
461 1.1 brezak sendreaddata, &sdata.rpc,
462 1.1 brezak sizeof(struct rpc_call) + sizeof(struct nfs_call_data),
463 1.1 brezak recvreaddata,
464 1.1 brezak ((u_char *)&rdata.rpc) - HEADER_SIZE, HEADER_SIZE +
465 1.1 brezak sizeof(struct rpc_call) + sizeof(struct nfs_reply_data));
466 1.1 brezak return (cc);
467 1.1 brezak }
468 1.1 brezak
469 1.1 brezak static struct iodesc *mountfs;
470 1.1 brezak static u_char mountfh[NFS_FHSIZE];
471 1.1 brezak static time_t mounttime;
472 1.1 brezak
473 1.1 brezak /*
474 1.1 brezak * nfs_mount - mount this nfs filesystem to a host
475 1.1 brezak */
476 1.1 brezak int
477 1.1 brezak nfs_mount(sock, ip, path)
478 1.1 brezak int sock;
479 1.1 brezak n_long ip;
480 1.1 brezak char *path;
481 1.1 brezak {
482 1.1 brezak struct iodesc *desc;
483 1.1 brezak struct nfs_iodesc *fp;
484 1.1 brezak u_long ftype;
485 1.1 brezak
486 1.1 brezak if (!(desc = socktodesc(sock))) {
487 1.1 brezak errno = EINVAL;
488 1.1 brezak return(-1);
489 1.1 brezak }
490 1.1 brezak bcopy(&desc->myea[4], &desc->myport, 2);
491 1.1 brezak desc->destip = ip;
492 1.1 brezak getmountfh(desc, path, mountfh);
493 1.1 brezak
494 1.1 brezak fp = alloc(sizeof(struct nfs_iodesc));
495 1.1 brezak fp->iodesc = desc;
496 1.1 brezak fp->fh = mountfh;
497 1.1 brezak fp->off = 0;
498 1.1 brezak if (getnfsinfo(fp, &mounttime, NULL, &ftype, NULL, NULL, NULL) < 0) {
499 1.1 brezak free(fp, sizeof(struct nfs_iodesc));
500 1.1 brezak return(-1);
501 1.1 brezak }
502 1.1 brezak
503 1.1 brezak if (ftype != NFDIR) {
504 1.1 brezak free(fp, sizeof(struct nfs_iodesc));
505 1.1 brezak errno = EINVAL;
506 1.1 brezak printf("nfs_mount: bad mount ftype %d", ftype);
507 1.1 brezak return(-1);
508 1.1 brezak }
509 1.1 brezak #ifdef NFS_DEBUG
510 1.1 brezak if (debug)
511 1.1 brezak printf("nfs_mount: got fh for %s, mtime=%d, ftype=%d\n",
512 1.1 brezak path, mounttime, ftype);
513 1.1 brezak #endif
514 1.1 brezak mountfs = desc;
515 1.1 brezak free(fp, sizeof(struct nfs_iodesc));
516 1.1 brezak
517 1.1 brezak return(0);
518 1.1 brezak }
519 1.1 brezak
520 1.1 brezak /*
521 1.1 brezak * Open a file.
522 1.1 brezak */
523 1.1 brezak int
524 1.1 brezak nfs_open(path, f)
525 1.1 brezak char *path;
526 1.1 brezak struct open_file *f;
527 1.1 brezak {
528 1.1 brezak register struct nfs_iodesc *fp;
529 1.1 brezak u_char *imagefh;
530 1.1 brezak u_long size, ftype;
531 1.1 brezak int rc = 0;
532 1.1 brezak
533 1.1 brezak #ifdef NFS_DEBUG
534 1.1 brezak if (debug)
535 1.1 brezak printf("nfs_open: %s\n", path);
536 1.1 brezak #endif
537 1.1 brezak if (!mountfs) {
538 1.1 brezak errno = EIO;
539 1.1 brezak printf("nfs_open: must mount first.\n");
540 1.1 brezak return(-1);
541 1.1 brezak }
542 1.1 brezak
543 1.1 brezak /* allocate file system specific data structure */
544 1.1 brezak fp = alloc(sizeof(struct nfs_iodesc));
545 1.1 brezak fp->iodesc = mountfs;
546 1.1 brezak fp->fh = mountfh;
547 1.1 brezak fp->off = 0;
548 1.1 brezak
549 1.1 brezak f->f_fsdata = (void *)fp;
550 1.1 brezak imagefh = alloc(NFS_FHSIZE);
551 1.1 brezak bzero(imagefh, NFS_FHSIZE);
552 1.1 brezak
553 1.1 brezak /* lookup a file handle */
554 1.1 brezak rc = lookupfh(fp, path, imagefh, NULL, &size, &ftype);
555 1.1 brezak if (rc < 0) {
556 1.1 brezak #ifdef NFS_DEBUG
557 1.1 brezak if (debug)
558 1.1 brezak printf("nfs_open: %s lookupfh failed: %s\n", path, strerror(errno));
559 1.1 brezak #endif
560 1.1 brezak f->f_fsdata = (void *)0;
561 1.1 brezak free(fp, sizeof(struct nfs_iodesc));
562 1.1 brezak free(imagefh, NFS_FHSIZE);
563 1.1 brezak return(rc);
564 1.1 brezak }
565 1.1 brezak fp->fh = imagefh;
566 1.1 brezak
567 1.1 brezak #ifdef NFS_DEBUG
568 1.1 brezak if (debug)
569 1.1 brezak printf("nfs_open: %s success, size=%d ftype=%d\n",
570 1.1 brezak path, size, ftype);
571 1.1 brezak #endif
572 1.1 brezak fp->size = size;
573 1.1 brezak
574 1.1 brezak return(rc);
575 1.1 brezak }
576 1.1 brezak
577 1.1 brezak int
578 1.1 brezak nfs_close(f)
579 1.1 brezak struct open_file *f;
580 1.1 brezak {
581 1.1 brezak register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
582 1.1 brezak
583 1.1 brezak #ifdef NFS_DEBUG
584 1.1 brezak if (debug)
585 1.1 brezak printf("nfs_close: called\n");
586 1.1 brezak #endif
587 1.1 brezak f->f_fsdata = (void *)0;
588 1.1 brezak if (fp == (struct nfs_iodesc *)0)
589 1.1 brezak return (0);
590 1.1 brezak
591 1.1 brezak free(fp->fh, NFS_FHSIZE);
592 1.1 brezak free(fp, sizeof(struct nfs_iodesc));
593 1.1 brezak
594 1.1 brezak return (0);
595 1.1 brezak }
596 1.1 brezak
597 1.1 brezak /*
598 1.1 brezak * read a portion of a file
599 1.1 brezak */
600 1.1 brezak int
601 1.1 brezak nfs_read(f, addr, size, resid)
602 1.1 brezak struct open_file *f;
603 1.1 brezak char *addr;
604 1.1 brezak u_int size;
605 1.1 brezak u_int *resid; /* out */
606 1.1 brezak {
607 1.1 brezak register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
608 1.1 brezak register int cc;
609 1.1 brezak
610 1.1 brezak #ifdef NFS_DEBUG
611 1.1 brezak if (debug)
612 1.3 brezak printf("nfs_read: size=%d off=%d\n", size, (int)fp->off);
613 1.1 brezak #endif
614 1.1 brezak while (size > 0) {
615 1.1 brezak cc = readdata(fp->iodesc, fp->off, (void *)addr, size);
616 1.1 brezak if (cc <= 0) {
617 1.1 brezak /* XXX maybe should retry on certain errors */
618 1.1 brezak if (cc < 0) {
619 1.1 brezak #ifdef NFS_DEBUG
620 1.1 brezak if (debug)
621 1.1 brezak printf("nfs_read: read: %s",
622 1.1 brezak strerror(errno));
623 1.1 brezak #endif
624 1.1 brezak return (-1);
625 1.1 brezak }
626 1.1 brezak if (debug)
627 1.1 brezak printf("nfs_read: hit EOF unexpectantly");
628 1.1 brezak goto ret;
629 1.1 brezak }
630 1.1 brezak fp->off += cc;
631 1.1 brezak addr += cc;
632 1.1 brezak size -= cc;
633 1.1 brezak }
634 1.1 brezak ret:
635 1.1 brezak if (resid)
636 1.1 brezak *resid = size;
637 1.1 brezak
638 1.1 brezak return (0);
639 1.1 brezak }
640 1.1 brezak
641 1.1 brezak /*
642 1.1 brezak * Not implemented.
643 1.1 brezak */
644 1.1 brezak int
645 1.1 brezak nfs_write(f, start, size, resid)
646 1.1 brezak struct open_file *f;
647 1.1 brezak char *start;
648 1.1 brezak u_int size;
649 1.1 brezak u_int *resid; /* out */
650 1.1 brezak {
651 1.1 brezak errno = EROFS;
652 1.1 brezak
653 1.1 brezak return (-1);
654 1.1 brezak }
655 1.1 brezak
656 1.1 brezak off_t
657 1.1 brezak nfs_seek(f, offset, where)
658 1.1 brezak struct open_file *f;
659 1.1 brezak off_t offset;
660 1.1 brezak int where;
661 1.1 brezak {
662 1.1 brezak register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
663 1.1 brezak
664 1.1 brezak switch (where) {
665 1.1 brezak case SEEK_SET:
666 1.1 brezak fp->off = offset;
667 1.1 brezak break;
668 1.1 brezak case SEEK_CUR:
669 1.1 brezak fp->off += offset;
670 1.1 brezak break;
671 1.1 brezak case SEEK_END:
672 1.1 brezak fp->off = fp->size - offset;
673 1.1 brezak break;
674 1.1 brezak default:
675 1.1 brezak return (-1);
676 1.1 brezak }
677 1.1 brezak return (fp->off);
678 1.1 brezak }
679 1.1 brezak
680 1.1 brezak int
681 1.1 brezak nfs_stat(f, sb)
682 1.1 brezak struct open_file *f;
683 1.1 brezak struct stat *sb;
684 1.1 brezak {
685 1.1 brezak register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
686 1.1 brezak mode_t mode = 0;
687 1.1 brezak u_long ftype = 0;
688 1.1 brezak
689 1.1 brezak #ifdef NFS_DEBUG
690 1.1 brezak if (debug)
691 1.1 brezak printf("nfs_stat: called\n");
692 1.1 brezak #endif
693 1.1 brezak if (getnfsinfo(fp, &mounttime, &sb->st_size, &ftype, &mode, &sb->st_uid, &sb->st_gid) < 0)
694 1.1 brezak return(-1);
695 1.1 brezak
696 1.1 brezak /* create a mode */
697 1.1 brezak switch (ftype) {
698 1.1 brezak case NFNON:
699 1.1 brezak sb->st_mode = 0;
700 1.1 brezak break;
701 1.1 brezak case NFREG:
702 1.1 brezak sb->st_mode = S_IFREG;
703 1.1 brezak break;
704 1.1 brezak case NFDIR:
705 1.1 brezak sb->st_mode = S_IFDIR;
706 1.1 brezak break;
707 1.1 brezak case NFBLK:
708 1.1 brezak sb->st_mode = S_IFBLK;
709 1.1 brezak break;
710 1.1 brezak case NFCHR:
711 1.1 brezak sb->st_mode = S_IFCHR;
712 1.1 brezak break;
713 1.1 brezak case NFLNK:
714 1.1 brezak sb->st_mode = S_IFLNK;
715 1.1 brezak break;
716 1.1 brezak }
717 1.1 brezak sb->st_mode |= mode;
718 1.1 brezak
719 1.1 brezak return (0);
720 1.1 brezak }
721