This source file includes following definitions.
- nfs_getrootfh
- nfs_lookupfh
- nfs_readlink
- nfs_readdata
- nfs_mount
- nfs_open
- nfs_close
- nfs_read
- nfs_write
- nfs_seek
- nfs_stat
- nfs_readdir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 #include <sys/param.h>
33 #include <sys/time.h>
34 #include <sys/socket.h>
35 #include <sys/stat.h>
36
37 #include <netinet/in.h>
38 #include <netinet/in_systm.h>
39
40 #include "rpcv2.h"
41 #include "nfsv2.h"
42
43 #include "stand.h"
44 #include "saerrno.h"
45 #include "net.h"
46 #include "netif.h"
47 #include "nfs.h"
48 #include "rpc.h"
49
50
51 struct nfsv2_fattrs {
52 n_long fa_type;
53 n_long fa_mode;
54 n_long fa_nlink;
55 n_long fa_uid;
56 n_long fa_gid;
57 n_long fa_size;
58 n_long fa_blocksize;
59 n_long fa_rdev;
60 n_long fa_blocks;
61 n_long fa_fsid;
62 n_long fa_fileid;
63 struct nfsv2_time fa_atime;
64 struct nfsv2_time fa_mtime;
65 struct nfsv2_time fa_ctime;
66 };
67
68
69 struct nfs_read_args {
70 u_char fh[NFS_FHSIZE];
71 n_long off;
72 n_long len;
73 n_long xxx;
74 };
75
76
77 #define NFSREAD_SIZE 1024
78 struct nfs_read_repl {
79 n_long errno;
80 struct nfsv2_fattrs fa;
81 n_long count;
82 u_char data[NFSREAD_SIZE];
83 };
84
85 struct nfs_readlnk_repl {
86 n_long errno;
87 n_long len;
88 char path[NFS_MAXPATHLEN];
89 };
90
91 struct nfs_iodesc {
92 struct iodesc *iodesc;
93 off_t off;
94 u_char fh[NFS_FHSIZE];
95 struct nfsv2_fattrs fa;
96 };
97
98 struct nfs_iodesc nfs_root_node;
99
100
101
102
103
104
105 static int
106 nfs_getrootfh(struct iodesc *d, char *path, u_char *fhp)
107 {
108 int len;
109 struct args {
110 n_long len;
111 char path[FNAME_SIZE];
112 } *args;
113 struct repl {
114 n_long errno;
115 u_char fh[NFS_FHSIZE];
116 } *repl;
117 struct {
118 n_long h[RPC_HEADER_WORDS];
119 struct args d;
120 } sdata;
121 struct {
122 n_long h[RPC_HEADER_WORDS];
123 struct repl d;
124 } rdata;
125 size_t cc;
126
127 #ifdef NFS_DEBUG
128 if (debug)
129 printf("nfs_getrootfh: %s\n", path);
130 #endif
131
132 args = &sdata.d;
133 repl = &rdata.d;
134
135 bzero(args, sizeof(*args));
136 len = strlen(path);
137 if (len > sizeof(args->path))
138 len = sizeof(args->path);
139 args->len = htonl(len);
140 bcopy(path, args->path, len);
141 len = 4 + roundup(len, 4);
142
143 cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
144 args, len, repl, sizeof(*repl));
145 if (cc == -1) {
146
147 return (-1);
148 }
149 if (cc < 4) {
150 errno = EBADRPC;
151 return (-1);
152 }
153 if (repl->errno) {
154 errno = ntohl(repl->errno);
155 return (-1);
156 }
157 bcopy(repl->fh, fhp, sizeof(repl->fh));
158 return (0);
159 }
160
161
162
163
164
165 static int
166 nfs_lookupfh(struct nfs_iodesc *d, char *name, struct nfs_iodesc *newfd)
167 {
168 int len, rlen;
169 struct args {
170 u_char fh[NFS_FHSIZE];
171 n_long len;
172 char name[FNAME_SIZE];
173 } *args;
174 struct repl {
175 n_long errno;
176 u_char fh[NFS_FHSIZE];
177 struct nfsv2_fattrs fa;
178 } *repl;
179 struct {
180 n_long h[RPC_HEADER_WORDS];
181 struct args d;
182 } sdata;
183 struct {
184 n_long h[RPC_HEADER_WORDS];
185 struct repl d;
186 } rdata;
187 ssize_t cc;
188
189 #ifdef NFS_DEBUG
190 if (debug)
191 printf("lookupfh: called\n");
192 #endif
193
194 args = &sdata.d;
195 repl = &rdata.d;
196
197 bzero(args, sizeof(*args));
198 bcopy(d->fh, args->fh, sizeof(args->fh));
199 len = strlen(name);
200 if (len > sizeof(args->name))
201 len = sizeof(args->name);
202 bcopy(name, args->name, len);
203 args->len = htonl(len);
204 len = 4 + roundup(len, 4);
205 len += NFS_FHSIZE;
206
207 rlen = sizeof(*repl);
208
209 cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
210 args, len, repl, rlen);
211 if (cc == -1)
212 return (errno);
213 if (cc < 4)
214 return (EIO);
215 if (repl->errno) {
216
217 return (ntohl(repl->errno));
218 }
219 bcopy( repl->fh, &newfd->fh, sizeof(newfd->fh));
220 bcopy(&repl->fa, &newfd->fa, sizeof(newfd->fa));
221 return (0);
222 }
223
224
225
226
227 static int
228 nfs_readlink(struct nfs_iodesc *d, char *buf)
229 {
230 struct {
231 n_long h[RPC_HEADER_WORDS];
232 u_char fh[NFS_FHSIZE];
233 } sdata;
234 struct {
235 n_long h[RPC_HEADER_WORDS];
236 struct nfs_readlnk_repl d;
237 } rdata;
238 ssize_t cc;
239
240 #ifdef NFS_DEBUG
241 if (debug)
242 printf("readlink: called\n");
243 #endif
244
245 bcopy(d->fh, sdata.fh, NFS_FHSIZE);
246 cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK,
247 sdata.fh, NFS_FHSIZE,
248 &rdata.d, sizeof(rdata.d));
249 if (cc == -1)
250 return (errno);
251
252 if (cc < 4)
253 return (EIO);
254
255 if (rdata.d.errno)
256 return (ntohl(rdata.d.errno));
257
258 rdata.d.len = ntohl(rdata.d.len);
259 if (rdata.d.len > NFS_MAXPATHLEN)
260 return (ENAMETOOLONG);
261
262 bcopy(rdata.d.path, buf, rdata.d.len);
263 buf[rdata.d.len] = 0;
264 return (0);
265 }
266
267
268
269
270
271 static ssize_t
272 nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len)
273 {
274 struct nfs_read_args *args;
275 struct nfs_read_repl *repl;
276 struct {
277 n_long h[RPC_HEADER_WORDS];
278 struct nfs_read_args d;
279 } sdata;
280 struct {
281 n_long h[RPC_HEADER_WORDS];
282 struct nfs_read_repl d;
283 } rdata;
284 size_t cc;
285 long x;
286 int hlen, rlen;
287
288 args = &sdata.d;
289 repl = &rdata.d;
290
291 bcopy(d->fh, args->fh, NFS_FHSIZE);
292 args->off = htonl((n_long)off);
293 if (len > NFSREAD_SIZE)
294 len = NFSREAD_SIZE;
295 args->len = htonl((n_long)len);
296 args->xxx = htonl((n_long)0);
297 hlen = sizeof(*repl) - NFSREAD_SIZE;
298
299 cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ,
300 args, sizeof(*args),
301 repl, sizeof(*repl));
302 if (cc == -1) {
303
304 return (-1);
305 }
306 if (cc < hlen) {
307 errno = EBADRPC;
308 return (-1);
309 }
310 if (repl->errno) {
311 errno = ntohl(repl->errno);
312 return (-1);
313 }
314 rlen = cc - hlen;
315 x = ntohl(repl->count);
316 if (rlen < x) {
317 printf("nfsread: short packet, %d < %ld\n", rlen, x);
318 errno = EBADRPC;
319 return(-1);
320 }
321 bcopy(repl->data, addr, x);
322 return (x);
323 }
324
325
326
327
328
329 int
330 nfs_mount(int sock, struct in_addr ip, char *path)
331 {
332 struct iodesc *desc;
333 struct nfsv2_fattrs *fa;
334
335 if (!(desc = socktodesc(sock))) {
336 errno = EINVAL;
337 return(-1);
338 }
339
340
341 desc->myport = htons(--rpc_port);
342 desc->destip = ip;
343 if (nfs_getrootfh(desc, path, nfs_root_node.fh))
344 return (-1);
345 nfs_root_node.iodesc = desc;
346
347 fa = &nfs_root_node.fa;
348 fa->fa_type = htonl(NFDIR);
349 fa->fa_mode = htonl(0755);
350 fa->fa_nlink = htonl(2);
351
352 #ifdef NFS_DEBUG
353 if (debug)
354 printf("nfs_mount: got fh for %s\n", path);
355 #endif
356
357 return(0);
358 }
359
360
361
362
363
364 int
365 nfs_open(char *path, struct open_file *f)
366 {
367 struct nfs_iodesc *newfd, *currfd;
368 char namebuf[NFS_MAXPATHLEN + 1], *cp, *ncp;
369 char linkbuf[NFS_MAXPATHLEN + 1];
370 int nlinks = 0, error = 0, c;
371
372 #ifdef NFS_DEBUG
373 if (debug)
374 printf("nfs_open: %s\n", path);
375 #endif
376 if (nfs_root_node.iodesc == NULL) {
377 printf("nfs_open: must mount first.\n");
378 return (ENXIO);
379 }
380
381 currfd = &nfs_root_node;
382 newfd = 0;
383
384 cp = path;
385 while (*cp) {
386
387
388
389 while (*cp == '/')
390 cp++;
391
392 if (*cp == '\0')
393 break;
394
395
396
397 if (currfd->fa.fa_type != htonl(NFDIR)) {
398 error = ENOTDIR;
399 goto out;
400 }
401
402
403 newfd = alloc(sizeof(*newfd));
404 newfd->iodesc = currfd->iodesc;
405 newfd->off = 0;
406
407
408
409
410 {
411 int len = 0;
412
413 ncp = cp;
414 while ((c = *cp) != '\0' && c != '/') {
415 if (++len > NFS_MAXNAMLEN) {
416 error = ENOENT;
417 goto out;
418 }
419 cp++;
420 }
421 *cp = '\0';
422 }
423
424
425 error = nfs_lookupfh(currfd, ncp, newfd);
426 *cp = c;
427 if (error)
428 goto out;
429
430
431
432
433 if (newfd->fa.fa_type == htonl(NFLNK)) {
434 int link_len, len;
435
436 error = nfs_readlink(newfd, linkbuf);
437 if (error)
438 goto out;
439
440 link_len = strlen(linkbuf);
441 len = strlen(cp);
442
443 if (link_len + len > MAXPATHLEN ||
444 ++nlinks > MAXSYMLINKS) {
445 error = ENOENT;
446 goto out;
447 }
448
449 bcopy(cp, &namebuf[link_len], len + 1);
450 bcopy(linkbuf, namebuf, link_len);
451
452
453
454
455
456 cp = namebuf;
457 if (*cp == '/') {
458 if (currfd != &nfs_root_node)
459 free(currfd, sizeof(*currfd));
460 currfd = &nfs_root_node;
461 }
462
463 free(newfd, sizeof(*newfd));
464 newfd = 0;
465
466 continue;
467 }
468
469 if (currfd != &nfs_root_node)
470 free(currfd, sizeof(*currfd));
471 currfd = newfd;
472 newfd = 0;
473 }
474
475 error = 0;
476
477 out:
478 if (!error) {
479 f->f_fsdata = (void *)currfd;
480 return (0);
481 }
482
483 #ifdef NFS_DEBUG
484 if (debug)
485 printf("nfs_open: %s lookupfh failed: %s\n",
486 path, strerror(error));
487 #endif
488 if (currfd != &nfs_root_node)
489 free(currfd, sizeof(*currfd));
490 if (newfd)
491 free(newfd, sizeof(*newfd));
492
493 return (error);
494 }
495
496 int
497 nfs_close(struct open_file *f)
498 {
499 struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
500
501 #ifdef NFS_DEBUG
502 if (debug)
503 printf("nfs_close: fp=%p\n", fp);
504 #endif
505
506 if (fp)
507 free(fp, sizeof(struct nfs_iodesc));
508 f->f_fsdata = (void *)0;
509
510 return (0);
511 }
512
513
514
515
516 int
517 nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid)
518 {
519 struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
520 ssize_t cc;
521 char *addr = buf;
522
523 #ifdef NFS_DEBUG
524 if (debug)
525 printf("nfs_read: size=%d off=%d\n", size, (int)fp->off);
526 #endif
527 while ((int)size > 0) {
528 twiddle();
529 cc = nfs_readdata(fp, fp->off, (void *)addr, size);
530
531 if (cc == -1) {
532 #ifdef NFS_DEBUG
533 if (debug)
534 printf("nfs_read: read: %s", strerror(errno));
535 #endif
536 return (errno);
537 }
538 if (cc == 0) {
539 if (debug)
540 printf("nfs_read: hit EOF unexpectantly");
541 goto ret;
542 }
543 fp->off += cc;
544 addr += cc;
545 size -= cc;
546 }
547 ret:
548 if (resid)
549 *resid = size;
550
551 return (0);
552 }
553
554
555
556
557 int
558 nfs_write(struct open_file *f, void *buf, size_t size, size_t *resid)
559 {
560 return (EROFS);
561 }
562
563 off_t
564 nfs_seek(struct open_file *f, off_t offset, int where)
565 {
566 struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata;
567 n_long size = ntohl(d->fa.fa_size);
568
569 switch (where) {
570 case SEEK_SET:
571 d->off = offset;
572 break;
573 case SEEK_CUR:
574 d->off += offset;
575 break;
576 case SEEK_END:
577 d->off = size - offset;
578 break;
579 default:
580 return (-1);
581 }
582
583 return (d->off);
584 }
585
586
587 int nfs_stat_types[8] = {
588 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0 };
589
590 int
591 nfs_stat(struct open_file *f, struct stat *sb)
592 {
593 struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
594 n_long ftype, mode;
595
596 ftype = ntohl(fp->fa.fa_type);
597 mode = ntohl(fp->fa.fa_mode);
598 mode |= nfs_stat_types[ftype & 7];
599
600 sb->st_mode = mode;
601 sb->st_nlink = ntohl(fp->fa.fa_nlink);
602 sb->st_uid = ntohl(fp->fa.fa_uid);
603 sb->st_gid = ntohl(fp->fa.fa_gid);
604 sb->st_size = ntohl(fp->fa.fa_size);
605
606 return (0);
607 }
608
609
610
611
612 #ifndef NO_READDIR
613 int
614 nfs_readdir(struct open_file *f, char *name)
615 {
616 return (EROFS);
617 }
618 #endif