nfs.c revision 1.24 1 1.24 pk /* $NetBSD: nfs.c,v 1.24 1999/02/11 09:10:44 pk 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.22 drochner #ifdef _STANDALONE
36 1.22 drochner #include <lib/libkern/libkern.h>
37 1.22 drochner #else
38 1.1 brezak #include <string.h>
39 1.22 drochner #endif
40 1.1 brezak
41 1.1 brezak #include <netinet/in.h>
42 1.1 brezak #include <netinet/in_systm.h>
43 1.1 brezak
44 1.14 gwr #include "rpcv2.h"
45 1.13 scottr #include "nfsv2.h"
46 1.1 brezak
47 1.1 brezak #include "stand.h"
48 1.1 brezak #include "net.h"
49 1.1 brezak #include "netif.h"
50 1.1 brezak #include "nfs.h"
51 1.1 brezak #include "rpc.h"
52 1.1 brezak
53 1.7 gwr /* Define our own NFS attributes without NQNFS stuff. */
54 1.7 gwr struct nfsv2_fattrs {
55 1.7 gwr n_long fa_type;
56 1.7 gwr n_long fa_mode;
57 1.7 gwr n_long fa_nlink;
58 1.7 gwr n_long fa_uid;
59 1.7 gwr n_long fa_gid;
60 1.7 gwr n_long fa_size;
61 1.7 gwr n_long fa_blocksize;
62 1.7 gwr n_long fa_rdev;
63 1.7 gwr n_long fa_blocks;
64 1.7 gwr n_long fa_fsid;
65 1.7 gwr n_long fa_fileid;
66 1.7 gwr struct nfsv2_time fa_atime;
67 1.7 gwr struct nfsv2_time fa_mtime;
68 1.7 gwr struct nfsv2_time fa_ctime;
69 1.7 gwr };
70 1.7 gwr
71 1.7 gwr
72 1.7 gwr struct nfs_read_args {
73 1.1 brezak u_char fh[NFS_FHSIZE];
74 1.7 gwr n_long off;
75 1.7 gwr n_long len;
76 1.7 gwr n_long xxx; /* XXX what's this for? */
77 1.1 brezak };
78 1.1 brezak
79 1.1 brezak /* Data part of nfs rpc reply (also the largest thing we receive) */
80 1.7 gwr #define NFSREAD_SIZE 1024
81 1.7 gwr struct nfs_read_repl {
82 1.7 gwr n_long errno;
83 1.7 gwr struct nfsv2_fattrs fa;
84 1.7 gwr n_long count;
85 1.7 gwr u_char data[NFSREAD_SIZE];
86 1.1 brezak };
87 1.1 brezak
88 1.21 drochner #ifndef NFS_NOSYMLINK
89 1.16 ws struct nfs_readlnk_repl {
90 1.16 ws n_long errno;
91 1.16 ws n_long len;
92 1.16 ws char path[NFS_MAXPATHLEN];
93 1.16 ws };
94 1.21 drochner #endif
95 1.16 ws
96 1.1 brezak struct nfs_iodesc {
97 1.7 gwr struct iodesc *iodesc;
98 1.1 brezak off_t off;
99 1.7 gwr u_char fh[NFS_FHSIZE];
100 1.7 gwr struct nfsv2_fattrs fa; /* all in network order */
101 1.7 gwr };
102 1.7 gwr
103 1.8 gwr struct nfs_iodesc nfs_root_node;
104 1.1 brezak
105 1.24 pk int nfs_getrootfh __P((struct iodesc *, char *, u_char *));
106 1.24 pk int nfs_lookupfh __P((struct nfs_iodesc *, char *, struct nfs_iodesc *));
107 1.24 pk int nfs_readlink __P((struct nfs_iodesc *, char *));
108 1.24 pk ssize_t nfs_readdata __P((struct nfs_iodesc *, off_t, void *, size_t));
109 1.7 gwr
110 1.12 gwr /*
111 1.12 gwr * Fetch the root file handle (call mount daemon)
112 1.12 gwr * On error, return non-zero and set errno.
113 1.12 gwr */
114 1.7 gwr int
115 1.7 gwr nfs_getrootfh(d, path, fhp)
116 1.1 brezak register struct iodesc *d;
117 1.1 brezak char *path;
118 1.1 brezak u_char *fhp;
119 1.1 brezak {
120 1.1 brezak register int len;
121 1.7 gwr struct args {
122 1.7 gwr n_long len;
123 1.7 gwr char path[FNAME_SIZE];
124 1.7 gwr } *args;
125 1.7 gwr struct repl {
126 1.7 gwr n_long errno;
127 1.7 gwr u_char fh[NFS_FHSIZE];
128 1.7 gwr } *repl;
129 1.1 brezak struct {
130 1.7 gwr n_long h[RPC_HEADER_WORDS];
131 1.7 gwr struct args d;
132 1.7 gwr } sdata;
133 1.1 brezak struct {
134 1.7 gwr n_long h[RPC_HEADER_WORDS];
135 1.7 gwr struct repl d;
136 1.7 gwr } rdata;
137 1.6 mycroft size_t cc;
138 1.1 brezak
139 1.1 brezak #ifdef NFS_DEBUG
140 1.1 brezak if (debug)
141 1.19 christos printf("nfs_getrootfh: %s\n", path);
142 1.1 brezak #endif
143 1.6 mycroft
144 1.7 gwr args = &sdata.d;
145 1.7 gwr repl = &rdata.d;
146 1.7 gwr
147 1.7 gwr bzero(args, sizeof(*args));
148 1.1 brezak len = strlen(path);
149 1.7 gwr if (len > sizeof(args->path))
150 1.7 gwr len = sizeof(args->path);
151 1.7 gwr args->len = htonl(len);
152 1.7 gwr bcopy(path, args->path, len);
153 1.7 gwr len = 4 + roundup(len, 4);
154 1.7 gwr
155 1.7 gwr cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
156 1.7 gwr args, len, repl, sizeof(*repl));
157 1.12 gwr if (cc == -1) {
158 1.12 gwr /* errno was set by rpc_call */
159 1.12 gwr return (-1);
160 1.12 gwr }
161 1.12 gwr if (cc < 4) {
162 1.12 gwr errno = EBADRPC;
163 1.7 gwr return (-1);
164 1.12 gwr }
165 1.7 gwr if (repl->errno) {
166 1.7 gwr errno = ntohl(repl->errno);
167 1.6 mycroft return (-1);
168 1.1 brezak }
169 1.7 gwr bcopy(repl->fh, fhp, sizeof(repl->fh));
170 1.6 mycroft return (0);
171 1.1 brezak }
172 1.1 brezak
173 1.12 gwr /*
174 1.12 gwr * Lookup a file. Store handle and attributes.
175 1.12 gwr * Return zero or error number.
176 1.12 gwr */
177 1.7 gwr int
178 1.7 gwr nfs_lookupfh(d, name, newfd)
179 1.1 brezak struct nfs_iodesc *d;
180 1.1 brezak char *name;
181 1.7 gwr struct nfs_iodesc *newfd;
182 1.1 brezak {
183 1.1 brezak register int len, rlen;
184 1.7 gwr struct args {
185 1.1 brezak u_char fh[NFS_FHSIZE];
186 1.7 gwr n_long len;
187 1.1 brezak char name[FNAME_SIZE];
188 1.7 gwr } *args;
189 1.7 gwr struct repl {
190 1.7 gwr n_long errno;
191 1.7 gwr u_char fh[NFS_FHSIZE];
192 1.7 gwr struct nfsv2_fattrs fa;
193 1.7 gwr } *repl;
194 1.7 gwr struct {
195 1.7 gwr n_long h[RPC_HEADER_WORDS];
196 1.7 gwr struct args d;
197 1.7 gwr } sdata;
198 1.1 brezak struct {
199 1.7 gwr n_long h[RPC_HEADER_WORDS];
200 1.7 gwr struct repl d;
201 1.7 gwr } rdata;
202 1.9 pk ssize_t cc;
203 1.1 brezak
204 1.1 brezak #ifdef NFS_DEBUG
205 1.1 brezak if (debug)
206 1.19 christos printf("lookupfh: called\n");
207 1.1 brezak #endif
208 1.1 brezak
209 1.7 gwr args = &sdata.d;
210 1.7 gwr repl = &rdata.d;
211 1.7 gwr
212 1.7 gwr bzero(args, sizeof(*args));
213 1.7 gwr bcopy(d->fh, args->fh, sizeof(args->fh));
214 1.1 brezak len = strlen(name);
215 1.7 gwr if (len > sizeof(args->name))
216 1.7 gwr len = sizeof(args->name);
217 1.7 gwr bcopy(name, args->name, len);
218 1.7 gwr args->len = htonl(len);
219 1.7 gwr len = 4 + roundup(len, 4);
220 1.7 gwr len += NFS_FHSIZE;
221 1.7 gwr
222 1.7 gwr rlen = sizeof(*repl);
223 1.7 gwr
224 1.7 gwr cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
225 1.7 gwr args, len, repl, rlen);
226 1.12 gwr if (cc == -1)
227 1.12 gwr return (errno); /* XXX - from rpc_call */
228 1.7 gwr if (cc < 4)
229 1.7 gwr return (EIO);
230 1.7 gwr if (repl->errno) {
231 1.12 gwr /* saerrno.h now matches NFS error numbers. */
232 1.12 gwr return (ntohl(repl->errno));
233 1.1 brezak }
234 1.7 gwr bcopy( repl->fh, &newfd->fh, sizeof(newfd->fh));
235 1.7 gwr bcopy(&repl->fa, &newfd->fa, sizeof(newfd->fa));
236 1.1 brezak return (0);
237 1.1 brezak }
238 1.1 brezak
239 1.21 drochner #ifndef NFS_NOSYMLINK
240 1.12 gwr /*
241 1.16 ws * Get the destination of a symbolic link.
242 1.16 ws */
243 1.16 ws int
244 1.16 ws nfs_readlink(d, buf)
245 1.16 ws struct nfs_iodesc *d;
246 1.16 ws char *buf;
247 1.16 ws {
248 1.16 ws struct {
249 1.16 ws n_long h[RPC_HEADER_WORDS];
250 1.16 ws u_char fh[NFS_FHSIZE];
251 1.16 ws } sdata;
252 1.16 ws struct {
253 1.16 ws n_long h[RPC_HEADER_WORDS];
254 1.16 ws struct nfs_readlnk_repl d;
255 1.16 ws } rdata;
256 1.16 ws ssize_t cc;
257 1.16 ws
258 1.16 ws #ifdef NFS_DEBUG
259 1.16 ws if (debug)
260 1.19 christos printf("readlink: called\n");
261 1.16 ws #endif
262 1.16 ws
263 1.16 ws bcopy(d->fh, sdata.fh, NFS_FHSIZE);
264 1.16 ws cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK,
265 1.16 ws sdata.fh, NFS_FHSIZE,
266 1.16 ws &rdata.d, sizeof(rdata.d));
267 1.16 ws if (cc == -1)
268 1.16 ws return (errno);
269 1.16 ws
270 1.16 ws if (cc < 4)
271 1.16 ws return (EIO);
272 1.16 ws
273 1.16 ws if (rdata.d.errno)
274 1.16 ws return (ntohl(rdata.d.errno));
275 1.17 cgd
276 1.17 cgd rdata.d.len = ntohl(rdata.d.len);
277 1.16 ws if (rdata.d.len > NFS_MAXPATHLEN)
278 1.16 ws return (ENAMETOOLONG);
279 1.16 ws
280 1.16 ws bcopy(rdata.d.path, buf, rdata.d.len);
281 1.16 ws buf[rdata.d.len] = 0;
282 1.16 ws return (0);
283 1.16 ws }
284 1.21 drochner #endif
285 1.16 ws
286 1.16 ws /*
287 1.12 gwr * Read data from a file.
288 1.12 gwr * Return transfer count or -1 (and set errno)
289 1.12 gwr */
290 1.9 pk ssize_t
291 1.7 gwr nfs_readdata(d, off, addr, len)
292 1.7 gwr struct nfs_iodesc *d;
293 1.7 gwr off_t off;
294 1.7 gwr void *addr;
295 1.7 gwr size_t len;
296 1.1 brezak {
297 1.7 gwr struct nfs_read_args *args;
298 1.7 gwr struct nfs_read_repl *repl;
299 1.7 gwr struct {
300 1.7 gwr n_long h[RPC_HEADER_WORDS];
301 1.7 gwr struct nfs_read_args d;
302 1.7 gwr } sdata;
303 1.7 gwr struct {
304 1.7 gwr n_long h[RPC_HEADER_WORDS];
305 1.7 gwr struct nfs_read_repl d;
306 1.7 gwr } rdata;
307 1.6 mycroft size_t cc;
308 1.9 pk long x;
309 1.9 pk int hlen, rlen;
310 1.7 gwr
311 1.7 gwr args = &sdata.d;
312 1.7 gwr repl = &rdata.d;
313 1.6 mycroft
314 1.7 gwr bcopy(d->fh, args->fh, NFS_FHSIZE);
315 1.14 gwr args->off = htonl((n_long)off);
316 1.6 mycroft if (len > NFSREAD_SIZE)
317 1.6 mycroft len = NFSREAD_SIZE;
318 1.14 gwr args->len = htonl((n_long)len);
319 1.14 gwr args->xxx = htonl((n_long)0);
320 1.7 gwr hlen = sizeof(*repl) - NFSREAD_SIZE;
321 1.7 gwr
322 1.7 gwr cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ,
323 1.7 gwr args, sizeof(*args),
324 1.7 gwr repl, sizeof(*repl));
325 1.12 gwr if (cc == -1) {
326 1.12 gwr /* errno was already set by rpc_call */
327 1.12 gwr return (-1);
328 1.12 gwr }
329 1.9 pk if (cc < hlen) {
330 1.12 gwr errno = EBADRPC;
331 1.7 gwr return (-1);
332 1.9 pk }
333 1.7 gwr if (repl->errno) {
334 1.7 gwr errno = ntohl(repl->errno);
335 1.6 mycroft return (-1);
336 1.7 gwr }
337 1.7 gwr rlen = cc - hlen;
338 1.7 gwr x = ntohl(repl->count);
339 1.7 gwr if (rlen < x) {
340 1.19 christos printf("nfsread: short packet, %d < %ld\n", rlen, x);
341 1.9 pk errno = EBADRPC;
342 1.7 gwr return(-1);
343 1.7 gwr }
344 1.7 gwr bcopy(repl->data, addr, x);
345 1.7 gwr return (x);
346 1.1 brezak }
347 1.1 brezak
348 1.1 brezak /*
349 1.1 brezak * nfs_mount - mount this nfs filesystem to a host
350 1.12 gwr * On error, return non-zero and set errno.
351 1.1 brezak */
352 1.1 brezak int
353 1.1 brezak nfs_mount(sock, ip, path)
354 1.1 brezak int sock;
355 1.11 pk struct in_addr ip;
356 1.1 brezak char *path;
357 1.1 brezak {
358 1.1 brezak struct iodesc *desc;
359 1.8 gwr struct nfsv2_fattrs *fa;
360 1.7 gwr
361 1.1 brezak if (!(desc = socktodesc(sock))) {
362 1.1 brezak errno = EINVAL;
363 1.1 brezak return(-1);
364 1.1 brezak }
365 1.7 gwr
366 1.7 gwr /* Bind to a reserved port. */
367 1.7 gwr desc->myport = htons(--rpc_port);
368 1.1 brezak desc->destip = ip;
369 1.7 gwr if (nfs_getrootfh(desc, path, nfs_root_node.fh))
370 1.7 gwr return (-1);
371 1.7 gwr nfs_root_node.iodesc = desc;
372 1.8 gwr /* Fake up attributes for the root dir. */
373 1.8 gwr fa = &nfs_root_node.fa;
374 1.8 gwr fa->fa_type = htonl(NFDIR);
375 1.8 gwr fa->fa_mode = htonl(0755);
376 1.8 gwr fa->fa_nlink = htonl(2);
377 1.1 brezak
378 1.1 brezak #ifdef NFS_DEBUG
379 1.1 brezak if (debug)
380 1.19 christos printf("nfs_mount: got fh for %s\n", path);
381 1.1 brezak #endif
382 1.1 brezak
383 1.1 brezak return(0);
384 1.1 brezak }
385 1.1 brezak
386 1.1 brezak /*
387 1.1 brezak * Open a file.
388 1.12 gwr * return zero or error number
389 1.1 brezak */
390 1.1 brezak int
391 1.1 brezak nfs_open(path, f)
392 1.1 brezak char *path;
393 1.1 brezak struct open_file *f;
394 1.1 brezak {
395 1.16 ws struct nfs_iodesc *newfd, *currfd;
396 1.21 drochner #ifndef NFS_NOSYMLINK
397 1.16 ws register char *cp, *ncp;
398 1.16 ws register int c;
399 1.16 ws char namebuf[NFS_MAXPATHLEN + 1];
400 1.16 ws char linkbuf[NFS_MAXPATHLEN + 1];
401 1.16 ws int nlinks = 0;
402 1.21 drochner #endif
403 1.12 gwr int error = 0;
404 1.1 brezak
405 1.1 brezak #ifdef NFS_DEBUG
406 1.1 brezak if (debug)
407 1.19 christos printf("nfs_open: %s\n", path);
408 1.1 brezak #endif
409 1.7 gwr if (nfs_root_node.iodesc == NULL) {
410 1.19 christos printf("nfs_open: must mount first.\n");
411 1.12 gwr return (ENXIO);
412 1.1 brezak }
413 1.1 brezak
414 1.16 ws currfd = &nfs_root_node;
415 1.16 ws newfd = 0;
416 1.21 drochner
417 1.21 drochner #ifndef NFS_NOSYMLINK
418 1.16 ws cp = path;
419 1.16 ws while (*cp) {
420 1.16 ws /*
421 1.16 ws * Remove extra separators
422 1.16 ws */
423 1.16 ws while (*cp == '/')
424 1.16 ws cp++;
425 1.16 ws
426 1.16 ws if (*cp == '\0')
427 1.16 ws break;
428 1.16 ws /*
429 1.16 ws * Check that current node is a directory.
430 1.16 ws */
431 1.17 cgd if (currfd->fa.fa_type != htonl(NFDIR)) {
432 1.16 ws error = ENOTDIR;
433 1.16 ws goto out;
434 1.16 ws }
435 1.16 ws
436 1.16 ws /* allocate file system specific data structure */
437 1.16 ws newfd = alloc(sizeof(*newfd));
438 1.16 ws newfd->iodesc = currfd->iodesc;
439 1.16 ws newfd->off = 0;
440 1.16 ws
441 1.16 ws /*
442 1.16 ws * Get next component of path name.
443 1.16 ws */
444 1.16 ws {
445 1.16 ws register int len = 0;
446 1.16 ws
447 1.16 ws ncp = cp;
448 1.16 ws while ((c = *cp) != '\0' && c != '/') {
449 1.16 ws if (++len > NFS_MAXNAMLEN) {
450 1.16 ws error = ENOENT;
451 1.16 ws goto out;
452 1.16 ws }
453 1.16 ws cp++;
454 1.16 ws }
455 1.16 ws *cp = '\0';
456 1.16 ws }
457 1.16 ws
458 1.16 ws /* lookup a file handle */
459 1.16 ws error = nfs_lookupfh(currfd, ncp, newfd);
460 1.16 ws *cp = c;
461 1.16 ws if (error)
462 1.16 ws goto out;
463 1.16 ws
464 1.16 ws /*
465 1.16 ws * Check for symbolic link
466 1.16 ws */
467 1.17 cgd if (newfd->fa.fa_type == htonl(NFLNK)) {
468 1.16 ws int link_len, len;
469 1.16 ws
470 1.16 ws error = nfs_readlink(newfd, linkbuf);
471 1.16 ws if (error)
472 1.16 ws goto out;
473 1.16 ws
474 1.16 ws link_len = strlen(linkbuf);
475 1.16 ws len = strlen(cp);
476 1.16 ws
477 1.16 ws if (link_len + len > MAXPATHLEN
478 1.16 ws || ++nlinks > MAXSYMLINKS) {
479 1.16 ws error = ENOENT;
480 1.16 ws goto out;
481 1.16 ws }
482 1.16 ws
483 1.16 ws bcopy(cp, &namebuf[link_len], len + 1);
484 1.16 ws bcopy(linkbuf, namebuf, link_len);
485 1.16 ws
486 1.16 ws /*
487 1.16 ws * If absolute pathname, restart at root.
488 1.16 ws * If relative pathname, restart at parent directory.
489 1.16 ws */
490 1.16 ws cp = namebuf;
491 1.16 ws if (*cp == '/') {
492 1.16 ws if (currfd != &nfs_root_node)
493 1.16 ws free(currfd, sizeof(*currfd));
494 1.16 ws currfd = &nfs_root_node;
495 1.16 ws }
496 1.16 ws
497 1.16 ws free(newfd, sizeof(*newfd));
498 1.16 ws newfd = 0;
499 1.16 ws
500 1.16 ws continue;
501 1.16 ws }
502 1.16 ws
503 1.16 ws if (currfd != &nfs_root_node)
504 1.16 ws free(currfd, sizeof(*currfd));
505 1.16 ws currfd = newfd;
506 1.16 ws newfd = 0;
507 1.16 ws }
508 1.16 ws
509 1.16 ws error = 0;
510 1.1 brezak
511 1.16 ws out:
512 1.21 drochner #else
513 1.21 drochner /* allocate file system specific data structure */
514 1.21 drochner currfd = alloc(sizeof(*currfd));
515 1.21 drochner currfd->iodesc = nfs_root_node.iodesc;
516 1.21 drochner currfd->off = 0;
517 1.21 drochner
518 1.21 drochner error = nfs_lookupfh(&nfs_root_node, path, currfd);
519 1.21 drochner #endif
520 1.12 gwr if (!error) {
521 1.16 ws f->f_fsdata = (void *)currfd;
522 1.12 gwr return (0);
523 1.1 brezak }
524 1.16 ws
525 1.1 brezak #ifdef NFS_DEBUG
526 1.1 brezak if (debug)
527 1.19 christos printf("nfs_open: %s lookupfh failed: %s\n",
528 1.18 christos path, strerror(error));
529 1.1 brezak #endif
530 1.16 ws if (currfd != &nfs_root_node)
531 1.16 ws free(currfd, sizeof(*currfd));
532 1.16 ws if (newfd)
533 1.16 ws free(newfd, sizeof(*newfd));
534 1.16 ws
535 1.12 gwr return (error);
536 1.1 brezak }
537 1.1 brezak
538 1.1 brezak int
539 1.1 brezak nfs_close(f)
540 1.1 brezak struct open_file *f;
541 1.1 brezak {
542 1.1 brezak register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
543 1.1 brezak
544 1.1 brezak #ifdef NFS_DEBUG
545 1.1 brezak if (debug)
546 1.23 thorpej printf("nfs_close: fp=0x%lx\n", (u_long)fp);
547 1.1 brezak #endif
548 1.7 gwr
549 1.7 gwr if (fp)
550 1.7 gwr free(fp, sizeof(struct nfs_iodesc));
551 1.1 brezak f->f_fsdata = (void *)0;
552 1.1 brezak
553 1.1 brezak return (0);
554 1.1 brezak }
555 1.1 brezak
556 1.1 brezak /*
557 1.1 brezak * read a portion of a file
558 1.1 brezak */
559 1.10 pk int
560 1.9 pk nfs_read(f, buf, size, resid)
561 1.1 brezak struct open_file *f;
562 1.9 pk void *buf;
563 1.9 pk size_t size;
564 1.9 pk size_t *resid; /* out */
565 1.1 brezak {
566 1.1 brezak register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
567 1.9 pk register ssize_t cc;
568 1.9 pk register char *addr = buf;
569 1.1 brezak
570 1.1 brezak #ifdef NFS_DEBUG
571 1.1 brezak if (debug)
572 1.23 thorpej printf("nfs_read: size=%lu off=%d\n", (u_long)size,
573 1.23 thorpej (int)fp->off);
574 1.1 brezak #endif
575 1.9 pk while ((int)size > 0) {
576 1.7 gwr twiddle();
577 1.7 gwr cc = nfs_readdata(fp, fp->off, (void *)addr, size);
578 1.6 mycroft /* XXX maybe should retry on certain errors */
579 1.6 mycroft if (cc == -1) {
580 1.6 mycroft #ifdef NFS_DEBUG
581 1.6 mycroft if (debug)
582 1.19 christos printf("nfs_read: read: %s", strerror(errno));
583 1.1 brezak #endif
584 1.12 gwr return (errno); /* XXX - from nfs_readdata */
585 1.6 mycroft }
586 1.6 mycroft if (cc == 0) {
587 1.20 pk #ifdef NFS_DEBUG
588 1.1 brezak if (debug)
589 1.19 christos printf("nfs_read: hit EOF unexpectantly");
590 1.20 pk #endif
591 1.1 brezak goto ret;
592 1.1 brezak }
593 1.1 brezak fp->off += cc;
594 1.1 brezak addr += cc;
595 1.1 brezak size -= cc;
596 1.1 brezak }
597 1.1 brezak ret:
598 1.1 brezak if (resid)
599 1.1 brezak *resid = size;
600 1.1 brezak
601 1.1 brezak return (0);
602 1.1 brezak }
603 1.1 brezak
604 1.1 brezak /*
605 1.1 brezak * Not implemented.
606 1.1 brezak */
607 1.10 pk int
608 1.9 pk nfs_write(f, buf, size, resid)
609 1.1 brezak struct open_file *f;
610 1.9 pk void *buf;
611 1.9 pk size_t size;
612 1.9 pk size_t *resid; /* out */
613 1.1 brezak {
614 1.10 pk return (EROFS);
615 1.1 brezak }
616 1.1 brezak
617 1.1 brezak off_t
618 1.1 brezak nfs_seek(f, offset, where)
619 1.1 brezak struct open_file *f;
620 1.1 brezak off_t offset;
621 1.1 brezak int where;
622 1.1 brezak {
623 1.7 gwr register struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata;
624 1.7 gwr n_long size = ntohl(d->fa.fa_size);
625 1.1 brezak
626 1.1 brezak switch (where) {
627 1.1 brezak case SEEK_SET:
628 1.7 gwr d->off = offset;
629 1.1 brezak break;
630 1.1 brezak case SEEK_CUR:
631 1.7 gwr d->off += offset;
632 1.1 brezak break;
633 1.1 brezak case SEEK_END:
634 1.7 gwr d->off = size - offset;
635 1.1 brezak break;
636 1.1 brezak default:
637 1.1 brezak return (-1);
638 1.1 brezak }
639 1.7 gwr
640 1.7 gwr return (d->off);
641 1.1 brezak }
642 1.1 brezak
643 1.7 gwr /* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */
644 1.7 gwr int nfs_stat_types[8] = {
645 1.7 gwr 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0 };
646 1.7 gwr
647 1.1 brezak int
648 1.1 brezak nfs_stat(f, sb)
649 1.1 brezak struct open_file *f;
650 1.1 brezak struct stat *sb;
651 1.1 brezak {
652 1.7 gwr struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
653 1.7 gwr register n_long ftype, mode;
654 1.1 brezak
655 1.7 gwr ftype = ntohl(fp->fa.fa_type);
656 1.7 gwr mode = ntohl(fp->fa.fa_mode);
657 1.7 gwr mode |= nfs_stat_types[ftype & 7];
658 1.7 gwr
659 1.7 gwr sb->st_mode = mode;
660 1.7 gwr sb->st_nlink = ntohl(fp->fa.fa_nlink);
661 1.7 gwr sb->st_uid = ntohl(fp->fa.fa_uid);
662 1.7 gwr sb->st_gid = ntohl(fp->fa.fa_gid);
663 1.7 gwr sb->st_size = ntohl(fp->fa.fa_size);
664 1.1 brezak
665 1.1 brezak return (0);
666 1.1 brezak }
667