nfs.c revision 1.13 1 1.13 scottr /* $NetBSD: nfs.c,v 1.13 1996/02/26 21:50:09 scottr 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.13 scottr #include "nfsv2.h"
42 1.6 mycroft #include <nfs/xdr_subs.h>
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.7 gwr /* Define our own NFS attributes without NQNFS stuff. */
51 1.7 gwr struct nfsv2_fattrs {
52 1.7 gwr n_long fa_type;
53 1.7 gwr n_long fa_mode;
54 1.7 gwr n_long fa_nlink;
55 1.7 gwr n_long fa_uid;
56 1.7 gwr n_long fa_gid;
57 1.7 gwr n_long fa_size;
58 1.7 gwr n_long fa_blocksize;
59 1.7 gwr n_long fa_rdev;
60 1.7 gwr n_long fa_blocks;
61 1.7 gwr n_long fa_fsid;
62 1.7 gwr n_long fa_fileid;
63 1.7 gwr struct nfsv2_time fa_atime;
64 1.7 gwr struct nfsv2_time fa_mtime;
65 1.7 gwr struct nfsv2_time fa_ctime;
66 1.7 gwr };
67 1.7 gwr
68 1.7 gwr
69 1.7 gwr struct nfs_read_args {
70 1.1 brezak u_char fh[NFS_FHSIZE];
71 1.7 gwr n_long off;
72 1.7 gwr n_long len;
73 1.7 gwr n_long xxx; /* XXX what's this for? */
74 1.1 brezak };
75 1.1 brezak
76 1.1 brezak /* Data part of nfs rpc reply (also the largest thing we receive) */
77 1.7 gwr #define NFSREAD_SIZE 1024
78 1.7 gwr struct nfs_read_repl {
79 1.7 gwr n_long errno;
80 1.7 gwr struct nfsv2_fattrs fa;
81 1.7 gwr n_long count;
82 1.7 gwr u_char data[NFSREAD_SIZE];
83 1.1 brezak };
84 1.1 brezak
85 1.1 brezak struct nfs_iodesc {
86 1.7 gwr struct iodesc *iodesc;
87 1.1 brezak off_t off;
88 1.7 gwr u_char fh[NFS_FHSIZE];
89 1.7 gwr struct nfsv2_fattrs fa; /* all in network order */
90 1.7 gwr };
91 1.7 gwr
92 1.8 gwr struct nfs_iodesc nfs_root_node;
93 1.1 brezak
94 1.7 gwr
95 1.12 gwr /*
96 1.12 gwr * Fetch the root file handle (call mount daemon)
97 1.12 gwr * On error, return non-zero and set errno.
98 1.12 gwr */
99 1.7 gwr int
100 1.7 gwr nfs_getrootfh(d, path, fhp)
101 1.1 brezak register struct iodesc *d;
102 1.1 brezak char *path;
103 1.1 brezak u_char *fhp;
104 1.1 brezak {
105 1.1 brezak register int len;
106 1.7 gwr struct args {
107 1.7 gwr n_long len;
108 1.7 gwr char path[FNAME_SIZE];
109 1.7 gwr } *args;
110 1.7 gwr struct repl {
111 1.7 gwr n_long errno;
112 1.7 gwr u_char fh[NFS_FHSIZE];
113 1.7 gwr } *repl;
114 1.1 brezak struct {
115 1.7 gwr n_long h[RPC_HEADER_WORDS];
116 1.7 gwr struct args d;
117 1.7 gwr } sdata;
118 1.1 brezak struct {
119 1.7 gwr n_long h[RPC_HEADER_WORDS];
120 1.7 gwr struct repl d;
121 1.7 gwr } rdata;
122 1.6 mycroft size_t cc;
123 1.1 brezak
124 1.1 brezak #ifdef NFS_DEBUG
125 1.1 brezak if (debug)
126 1.7 gwr printf("nfs_getrootfh: %s\n", path);
127 1.1 brezak #endif
128 1.6 mycroft
129 1.7 gwr args = &sdata.d;
130 1.7 gwr repl = &rdata.d;
131 1.7 gwr
132 1.7 gwr bzero(args, sizeof(*args));
133 1.1 brezak len = strlen(path);
134 1.7 gwr if (len > sizeof(args->path))
135 1.7 gwr len = sizeof(args->path);
136 1.7 gwr args->len = htonl(len);
137 1.7 gwr bcopy(path, args->path, len);
138 1.7 gwr len = 4 + roundup(len, 4);
139 1.7 gwr
140 1.7 gwr cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
141 1.7 gwr args, len, repl, sizeof(*repl));
142 1.12 gwr if (cc == -1) {
143 1.12 gwr /* errno was set by rpc_call */
144 1.12 gwr return (-1);
145 1.12 gwr }
146 1.12 gwr if (cc < 4) {
147 1.12 gwr errno = EBADRPC;
148 1.7 gwr return (-1);
149 1.12 gwr }
150 1.7 gwr if (repl->errno) {
151 1.7 gwr errno = ntohl(repl->errno);
152 1.6 mycroft return (-1);
153 1.1 brezak }
154 1.7 gwr bcopy(repl->fh, fhp, sizeof(repl->fh));
155 1.6 mycroft return (0);
156 1.1 brezak }
157 1.1 brezak
158 1.12 gwr /*
159 1.12 gwr * Lookup a file. Store handle and attributes.
160 1.12 gwr * Return zero or error number.
161 1.12 gwr */
162 1.7 gwr int
163 1.7 gwr nfs_lookupfh(d, name, newfd)
164 1.1 brezak struct nfs_iodesc *d;
165 1.1 brezak char *name;
166 1.7 gwr struct nfs_iodesc *newfd;
167 1.1 brezak {
168 1.1 brezak register int len, rlen;
169 1.7 gwr struct args {
170 1.1 brezak u_char fh[NFS_FHSIZE];
171 1.7 gwr n_long len;
172 1.1 brezak char name[FNAME_SIZE];
173 1.7 gwr } *args;
174 1.7 gwr struct repl {
175 1.7 gwr n_long errno;
176 1.7 gwr u_char fh[NFS_FHSIZE];
177 1.7 gwr struct nfsv2_fattrs fa;
178 1.7 gwr } *repl;
179 1.7 gwr struct {
180 1.7 gwr n_long h[RPC_HEADER_WORDS];
181 1.7 gwr struct args d;
182 1.7 gwr } sdata;
183 1.1 brezak struct {
184 1.7 gwr n_long h[RPC_HEADER_WORDS];
185 1.7 gwr struct repl d;
186 1.7 gwr } rdata;
187 1.9 pk ssize_t cc;
188 1.1 brezak
189 1.1 brezak #ifdef NFS_DEBUG
190 1.1 brezak if (debug)
191 1.6 mycroft printf("lookupfh: called\n");
192 1.1 brezak #endif
193 1.1 brezak
194 1.7 gwr args = &sdata.d;
195 1.7 gwr repl = &rdata.d;
196 1.7 gwr
197 1.7 gwr bzero(args, sizeof(*args));
198 1.7 gwr bcopy(d->fh, args->fh, sizeof(args->fh));
199 1.1 brezak len = strlen(name);
200 1.7 gwr if (len > sizeof(args->name))
201 1.7 gwr len = sizeof(args->name);
202 1.7 gwr bcopy(name, args->name, len);
203 1.7 gwr args->len = htonl(len);
204 1.7 gwr len = 4 + roundup(len, 4);
205 1.7 gwr len += NFS_FHSIZE;
206 1.7 gwr
207 1.7 gwr rlen = sizeof(*repl);
208 1.7 gwr
209 1.7 gwr cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
210 1.7 gwr args, len, repl, rlen);
211 1.12 gwr if (cc == -1)
212 1.12 gwr return (errno); /* XXX - from rpc_call */
213 1.7 gwr if (cc < 4)
214 1.7 gwr return (EIO);
215 1.7 gwr if (repl->errno) {
216 1.12 gwr /* saerrno.h now matches NFS error numbers. */
217 1.12 gwr return (ntohl(repl->errno));
218 1.1 brezak }
219 1.7 gwr bcopy( repl->fh, &newfd->fh, sizeof(newfd->fh));
220 1.7 gwr bcopy(&repl->fa, &newfd->fa, sizeof(newfd->fa));
221 1.1 brezak return (0);
222 1.1 brezak }
223 1.1 brezak
224 1.12 gwr /*
225 1.12 gwr * Read data from a file.
226 1.12 gwr * Return transfer count or -1 (and set errno)
227 1.12 gwr */
228 1.9 pk ssize_t
229 1.7 gwr nfs_readdata(d, off, addr, len)
230 1.7 gwr struct nfs_iodesc *d;
231 1.7 gwr off_t off;
232 1.7 gwr void *addr;
233 1.7 gwr size_t len;
234 1.1 brezak {
235 1.7 gwr struct nfs_read_args *args;
236 1.7 gwr struct nfs_read_repl *repl;
237 1.7 gwr struct {
238 1.7 gwr n_long h[RPC_HEADER_WORDS];
239 1.7 gwr struct nfs_read_args d;
240 1.7 gwr } sdata;
241 1.7 gwr struct {
242 1.7 gwr n_long h[RPC_HEADER_WORDS];
243 1.7 gwr struct nfs_read_repl d;
244 1.7 gwr } rdata;
245 1.6 mycroft size_t cc;
246 1.9 pk long x;
247 1.9 pk int hlen, rlen;
248 1.7 gwr
249 1.7 gwr args = &sdata.d;
250 1.7 gwr repl = &rdata.d;
251 1.6 mycroft
252 1.7 gwr bcopy(d->fh, args->fh, NFS_FHSIZE);
253 1.7 gwr args->off = txdr_unsigned(off);
254 1.6 mycroft if (len > NFSREAD_SIZE)
255 1.6 mycroft len = NFSREAD_SIZE;
256 1.7 gwr args->len = txdr_unsigned(len);
257 1.7 gwr args->xxx = txdr_unsigned(0);
258 1.7 gwr hlen = sizeof(*repl) - NFSREAD_SIZE;
259 1.7 gwr
260 1.7 gwr cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ,
261 1.7 gwr args, sizeof(*args),
262 1.7 gwr repl, sizeof(*repl));
263 1.12 gwr if (cc == -1) {
264 1.12 gwr /* errno was already set by rpc_call */
265 1.12 gwr return (-1);
266 1.12 gwr }
267 1.9 pk if (cc < hlen) {
268 1.12 gwr errno = EBADRPC;
269 1.7 gwr return (-1);
270 1.9 pk }
271 1.7 gwr if (repl->errno) {
272 1.7 gwr errno = ntohl(repl->errno);
273 1.6 mycroft return (-1);
274 1.7 gwr }
275 1.7 gwr rlen = cc - hlen;
276 1.7 gwr x = ntohl(repl->count);
277 1.7 gwr if (rlen < x) {
278 1.7 gwr printf("nfsread: short packet, %d < %d\n", rlen, x);
279 1.9 pk errno = EBADRPC;
280 1.7 gwr return(-1);
281 1.7 gwr }
282 1.7 gwr bcopy(repl->data, addr, x);
283 1.7 gwr return (x);
284 1.1 brezak }
285 1.1 brezak
286 1.1 brezak /*
287 1.1 brezak * nfs_mount - mount this nfs filesystem to a host
288 1.12 gwr * On error, return non-zero and set errno.
289 1.1 brezak */
290 1.1 brezak int
291 1.1 brezak nfs_mount(sock, ip, path)
292 1.1 brezak int sock;
293 1.11 pk struct in_addr ip;
294 1.1 brezak char *path;
295 1.1 brezak {
296 1.1 brezak struct iodesc *desc;
297 1.8 gwr struct nfsv2_fattrs *fa;
298 1.7 gwr
299 1.1 brezak if (!(desc = socktodesc(sock))) {
300 1.1 brezak errno = EINVAL;
301 1.1 brezak return(-1);
302 1.1 brezak }
303 1.7 gwr
304 1.7 gwr /* Bind to a reserved port. */
305 1.7 gwr desc->myport = htons(--rpc_port);
306 1.1 brezak desc->destip = ip;
307 1.7 gwr if (nfs_getrootfh(desc, path, nfs_root_node.fh))
308 1.7 gwr return (-1);
309 1.7 gwr nfs_root_node.iodesc = desc;
310 1.8 gwr /* Fake up attributes for the root dir. */
311 1.8 gwr fa = &nfs_root_node.fa;
312 1.8 gwr fa->fa_type = htonl(NFDIR);
313 1.8 gwr fa->fa_mode = htonl(0755);
314 1.8 gwr fa->fa_nlink = htonl(2);
315 1.1 brezak
316 1.1 brezak #ifdef NFS_DEBUG
317 1.1 brezak if (debug)
318 1.7 gwr printf("nfs_mount: got fh for %s\n", path);
319 1.1 brezak #endif
320 1.1 brezak
321 1.1 brezak return(0);
322 1.1 brezak }
323 1.1 brezak
324 1.1 brezak /*
325 1.1 brezak * Open a file.
326 1.12 gwr * return zero or error number
327 1.1 brezak */
328 1.1 brezak int
329 1.1 brezak nfs_open(path, f)
330 1.1 brezak char *path;
331 1.1 brezak struct open_file *f;
332 1.1 brezak {
333 1.7 gwr struct nfs_iodesc *newfd;
334 1.12 gwr int error = 0;
335 1.1 brezak
336 1.1 brezak #ifdef NFS_DEBUG
337 1.1 brezak if (debug)
338 1.1 brezak printf("nfs_open: %s\n", path);
339 1.1 brezak #endif
340 1.7 gwr if (nfs_root_node.iodesc == NULL) {
341 1.1 brezak printf("nfs_open: must mount first.\n");
342 1.12 gwr return (ENXIO);
343 1.1 brezak }
344 1.1 brezak
345 1.1 brezak /* allocate file system specific data structure */
346 1.7 gwr newfd = alloc(sizeof(*newfd));
347 1.7 gwr newfd->iodesc = nfs_root_node.iodesc;
348 1.7 gwr newfd->off = 0;
349 1.1 brezak
350 1.1 brezak /* lookup a file handle */
351 1.12 gwr error = nfs_lookupfh(&nfs_root_node, path, newfd);
352 1.12 gwr if (!error) {
353 1.12 gwr f->f_fsdata = (void *)newfd;
354 1.12 gwr return (0);
355 1.1 brezak }
356 1.7 gwr
357 1.1 brezak #ifdef NFS_DEBUG
358 1.1 brezak if (debug)
359 1.12 gwr printf("nfs_open: %s lookupfh failed: %s\n",
360 1.12 gwr path, strerror(error));
361 1.1 brezak #endif
362 1.12 gwr free(newfd, sizeof(*newfd));
363 1.12 gwr return (error);
364 1.1 brezak }
365 1.1 brezak
366 1.1 brezak int
367 1.1 brezak nfs_close(f)
368 1.1 brezak struct open_file *f;
369 1.1 brezak {
370 1.1 brezak register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
371 1.1 brezak
372 1.1 brezak #ifdef NFS_DEBUG
373 1.1 brezak if (debug)
374 1.7 gwr printf("nfs_close: fp=0x%x\n", fp);
375 1.1 brezak #endif
376 1.7 gwr
377 1.7 gwr if (fp)
378 1.7 gwr free(fp, sizeof(struct nfs_iodesc));
379 1.1 brezak f->f_fsdata = (void *)0;
380 1.1 brezak
381 1.1 brezak return (0);
382 1.1 brezak }
383 1.1 brezak
384 1.1 brezak /*
385 1.1 brezak * read a portion of a file
386 1.1 brezak */
387 1.10 pk int
388 1.9 pk nfs_read(f, buf, size, resid)
389 1.1 brezak struct open_file *f;
390 1.9 pk void *buf;
391 1.9 pk size_t size;
392 1.9 pk size_t *resid; /* out */
393 1.1 brezak {
394 1.1 brezak register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
395 1.9 pk register ssize_t cc;
396 1.9 pk register char *addr = buf;
397 1.1 brezak
398 1.1 brezak #ifdef NFS_DEBUG
399 1.1 brezak if (debug)
400 1.3 brezak printf("nfs_read: size=%d off=%d\n", size, (int)fp->off);
401 1.1 brezak #endif
402 1.9 pk while ((int)size > 0) {
403 1.7 gwr twiddle();
404 1.7 gwr cc = nfs_readdata(fp, fp->off, (void *)addr, size);
405 1.6 mycroft /* XXX maybe should retry on certain errors */
406 1.6 mycroft if (cc == -1) {
407 1.6 mycroft #ifdef NFS_DEBUG
408 1.6 mycroft if (debug)
409 1.6 mycroft printf("nfs_read: read: %s", strerror(errno));
410 1.1 brezak #endif
411 1.12 gwr return (errno); /* XXX - from nfs_readdata */
412 1.6 mycroft }
413 1.6 mycroft if (cc == 0) {
414 1.1 brezak if (debug)
415 1.1 brezak printf("nfs_read: hit EOF unexpectantly");
416 1.1 brezak goto ret;
417 1.1 brezak }
418 1.1 brezak fp->off += cc;
419 1.1 brezak addr += cc;
420 1.1 brezak size -= cc;
421 1.1 brezak }
422 1.1 brezak ret:
423 1.1 brezak if (resid)
424 1.1 brezak *resid = size;
425 1.1 brezak
426 1.1 brezak return (0);
427 1.1 brezak }
428 1.1 brezak
429 1.1 brezak /*
430 1.1 brezak * Not implemented.
431 1.1 brezak */
432 1.10 pk int
433 1.9 pk nfs_write(f, buf, size, resid)
434 1.1 brezak struct open_file *f;
435 1.9 pk void *buf;
436 1.9 pk size_t size;
437 1.9 pk size_t *resid; /* out */
438 1.1 brezak {
439 1.10 pk return (EROFS);
440 1.1 brezak }
441 1.1 brezak
442 1.1 brezak off_t
443 1.1 brezak nfs_seek(f, offset, where)
444 1.1 brezak struct open_file *f;
445 1.1 brezak off_t offset;
446 1.1 brezak int where;
447 1.1 brezak {
448 1.7 gwr register struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata;
449 1.7 gwr n_long size = ntohl(d->fa.fa_size);
450 1.1 brezak
451 1.1 brezak switch (where) {
452 1.1 brezak case SEEK_SET:
453 1.7 gwr d->off = offset;
454 1.1 brezak break;
455 1.1 brezak case SEEK_CUR:
456 1.7 gwr d->off += offset;
457 1.1 brezak break;
458 1.1 brezak case SEEK_END:
459 1.7 gwr d->off = size - offset;
460 1.1 brezak break;
461 1.1 brezak default:
462 1.1 brezak return (-1);
463 1.1 brezak }
464 1.7 gwr
465 1.7 gwr return (d->off);
466 1.1 brezak }
467 1.1 brezak
468 1.7 gwr /* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */
469 1.7 gwr int nfs_stat_types[8] = {
470 1.7 gwr 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0 };
471 1.7 gwr
472 1.1 brezak int
473 1.1 brezak nfs_stat(f, sb)
474 1.1 brezak struct open_file *f;
475 1.1 brezak struct stat *sb;
476 1.1 brezak {
477 1.7 gwr struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
478 1.7 gwr register n_long ftype, mode;
479 1.1 brezak
480 1.7 gwr ftype = ntohl(fp->fa.fa_type);
481 1.7 gwr mode = ntohl(fp->fa.fa_mode);
482 1.7 gwr mode |= nfs_stat_types[ftype & 7];
483 1.7 gwr
484 1.7 gwr sb->st_mode = mode;
485 1.7 gwr sb->st_nlink = ntohl(fp->fa.fa_nlink);
486 1.7 gwr sb->st_uid = ntohl(fp->fa.fa_uid);
487 1.7 gwr sb->st_gid = ntohl(fp->fa.fa_gid);
488 1.7 gwr sb->st_size = ntohl(fp->fa.fa_size);
489 1.1 brezak
490 1.1 brezak return (0);
491 1.1 brezak }
492