nfs.c revision 1.6 1 1.6 mycroft /* $NetBSD: nfs.c,v 1.6 1995/02/20 11:04:12 mycroft 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.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.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 struct nfsv2_fattr fa;
61 1.1 brezak u_long count;
62 1.1 brezak u_char data[1200];
63 1.1 brezak };
64 1.1 brezak #define NFSREAD_SIZE sizeof(((struct nfs_reply_data *)0)->data)
65 1.1 brezak
66 1.1 brezak struct nfs_iodesc {
67 1.1 brezak off_t off;
68 1.1 brezak size_t size;
69 1.1 brezak u_char *fh;
70 1.1 brezak struct iodesc *iodesc;
71 1.1 brezak };
72 1.1 brezak
73 1.1 brezak /* Fetch (mount) file handle */
74 1.1 brezak static int
75 1.1 brezak getmountfh(d, path, fhp)
76 1.1 brezak register struct iodesc *d;
77 1.1 brezak char *path;
78 1.1 brezak u_char *fhp;
79 1.1 brezak {
80 1.1 brezak register int len;
81 1.1 brezak struct {
82 1.1 brezak u_long len;
83 1.1 brezak char path[FNAME_SIZE];
84 1.6 mycroft } wbuf;
85 1.1 brezak struct {
86 1.1 brezak u_long errno;
87 1.1 brezak u_char fh[NFS_FHSIZE];
88 1.6 mycroft } rbuf;
89 1.6 mycroft size_t cc;
90 1.1 brezak
91 1.1 brezak #ifdef NFS_DEBUG
92 1.1 brezak if (debug)
93 1.6 mycroft printf("getmountfh: called\n");
94 1.1 brezak #endif
95 1.6 mycroft
96 1.6 mycroft bzero(&wbuf, sizeof(wbuf));
97 1.1 brezak len = strlen(path);
98 1.6 mycroft if (len > sizeof(wbuf.path))
99 1.6 mycroft len = sizeof(wbuf.path);
100 1.6 mycroft bcopy(path, wbuf.path, len);
101 1.6 mycroft wbuf.len = htonl(len);
102 1.6 mycroft len = sizeof(wbuf) - sizeof(wbuf.path) + roundup(len, sizeof(long));
103 1.1 brezak
104 1.1 brezak if ((cc = callrpc(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
105 1.6 mycroft &wbuf, len, &rbuf, sizeof(rbuf))) == -1)
106 1.6 mycroft return (-1);
107 1.6 mycroft if (cc < sizeof(rbuf.errno))
108 1.1 brezak panic("getmountfh: callrpc small read");
109 1.6 mycroft if (rbuf.errno) {
110 1.6 mycroft errno = ntohl(rbuf.errno);
111 1.6 mycroft return (-1);
112 1.1 brezak }
113 1.6 mycroft bcopy(rbuf.fh, fhp, sizeof(rbuf.fh));
114 1.6 mycroft return (0);
115 1.1 brezak }
116 1.1 brezak
117 1.1 brezak /* Fetch file timestamp and size */
118 1.1 brezak static int
119 1.1 brezak getnfsinfo(d, tp, sp, fp, mp, up, gp)
120 1.1 brezak register struct nfs_iodesc *d;
121 1.1 brezak register time_t *tp;
122 1.1 brezak u_long *sp, *fp;
123 1.1 brezak mode_t *mp;
124 1.1 brezak uid_t *up;
125 1.1 brezak gid_t *gp;
126 1.1 brezak {
127 1.1 brezak register int rlen;
128 1.1 brezak register u_long t;
129 1.1 brezak struct {
130 1.1 brezak u_long errno;
131 1.1 brezak struct nfsv2_fattr fa;
132 1.6 mycroft } rbuf;
133 1.6 mycroft size_t cc;
134 1.1 brezak
135 1.1 brezak #ifdef NFS_DEBUG
136 1.1 brezak if (debug)
137 1.1 brezak printf("getnfsinfo: called\n");
138 1.1 brezak #endif
139 1.6 mycroft rlen = sizeof(rbuf);
140 1.1 brezak #if NFSX_FATTR(1) > NFSX_FATTR(0)
141 1.1 brezak /* nqnfs makes this more painful than it needs to be */
142 1.1 brezak rlen -= NFSX_FATTR(1) - NFSX_FATTR(0);
143 1.1 brezak #endif
144 1.1 brezak if ((cc = callrpc(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_GETATTR,
145 1.6 mycroft d->fh, NFS_FHSIZE, &rbuf, rlen)) == -1)
146 1.6 mycroft return (-1);
147 1.6 mycroft if (cc < sizeof(rbuf.errno))
148 1.1 brezak panic("getnfsinfo: callrpc small read");
149 1.6 mycroft if (rbuf.errno) {
150 1.6 mycroft errno = ntohl(rbuf.errno);
151 1.6 mycroft return (-1);
152 1.1 brezak }
153 1.1 brezak if (tp) {
154 1.6 mycroft *tp = ntohl(rbuf.fa.fa_nfsmtime.nfs_sec);
155 1.6 mycroft t = ntohl(rbuf.fa.fa_nfsatime.nfs_sec);
156 1.1 brezak if (*tp < t)
157 1.1 brezak *tp = t;
158 1.1 brezak }
159 1.1 brezak if (sp)
160 1.6 mycroft *sp = ntohl(rbuf.fa.fa_nfssize);
161 1.1 brezak if (fp)
162 1.6 mycroft *fp = ntohl(rbuf.fa.fa_type);
163 1.1 brezak if (mp)
164 1.6 mycroft *mp = ntohl(rbuf.fa.fa_mode);
165 1.1 brezak if (up)
166 1.6 mycroft *up = ntohl(rbuf.fa.fa_uid);
167 1.1 brezak if (gp)
168 1.6 mycroft *gp = ntohl(rbuf.fa.fa_gid);
169 1.1 brezak return(0);
170 1.1 brezak }
171 1.1 brezak
172 1.1 brezak /* Lookup a file. Optionally return timestamp and size */
173 1.1 brezak static int
174 1.1 brezak lookupfh(d, name, fhp, tp, sp, fp)
175 1.1 brezak struct nfs_iodesc *d;
176 1.1 brezak char *name;
177 1.1 brezak u_char *fhp;
178 1.1 brezak time_t *tp;
179 1.1 brezak u_long *sp, *fp;
180 1.1 brezak {
181 1.1 brezak register int len, rlen;
182 1.1 brezak struct {
183 1.1 brezak u_char fh[NFS_FHSIZE];
184 1.1 brezak u_long len;
185 1.1 brezak char name[FNAME_SIZE];
186 1.6 mycroft } wbuf;
187 1.1 brezak struct {
188 1.1 brezak u_long errno;
189 1.1 brezak u_char fh[NFS_FHSIZE];
190 1.1 brezak struct nfsv2_fattr fa;
191 1.6 mycroft } rbuf;
192 1.6 mycroft size_t cc;
193 1.1 brezak
194 1.1 brezak #ifdef NFS_DEBUG
195 1.1 brezak if (debug)
196 1.6 mycroft printf("lookupfh: called\n");
197 1.1 brezak #endif
198 1.1 brezak
199 1.6 mycroft bzero(&wbuf, sizeof(wbuf));
200 1.6 mycroft bcopy(d->fh, wbuf.fh, sizeof(wbuf.fh));
201 1.1 brezak len = strlen(name);
202 1.6 mycroft if (len > sizeof(wbuf.name))
203 1.6 mycroft len = sizeof(wbuf.name);
204 1.6 mycroft bcopy(name, wbuf.name, len);
205 1.6 mycroft wbuf.len = htonl(len);
206 1.6 mycroft len = sizeof(wbuf) - sizeof(wbuf.name) + roundup(len, sizeof(long));
207 1.1 brezak
208 1.6 mycroft rlen = sizeof(rbuf);
209 1.1 brezak #ifdef NFSX_FATTR
210 1.1 brezak #if NFSX_FATTR(1) > NFSX_FATTR(0)
211 1.1 brezak /* nqnfs makes this more painful than it needs to be */
212 1.1 brezak rlen -= NFSX_FATTR(1) - NFSX_FATTR(0);
213 1.1 brezak #endif
214 1.1 brezak #endif
215 1.6 mycroft
216 1.1 brezak if ((cc = callrpc(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
217 1.6 mycroft &wbuf, len, &rbuf, rlen)) == -1)
218 1.1 brezak return (-1);
219 1.6 mycroft if (cc < sizeof(rbuf.errno))
220 1.1 brezak panic("lookupfh: callrpc small read");
221 1.6 mycroft if (rbuf.errno) {
222 1.6 mycroft errno = ntohl(rbuf.errno);
223 1.6 mycroft return (-1);
224 1.1 brezak }
225 1.6 mycroft bcopy(rbuf.fh, fhp, sizeof(rbuf.fh));
226 1.1 brezak if (tp)
227 1.6 mycroft *tp = ntohl(rbuf.fa.fa_nfsctime.nfs_sec);
228 1.1 brezak if (sp)
229 1.6 mycroft *sp = ntohl(rbuf.fa.fa_nfssize);
230 1.1 brezak if (fp)
231 1.6 mycroft *fp = ntohl(rbuf.fa.fa_type);
232 1.1 brezak return (0);
233 1.1 brezak }
234 1.1 brezak
235 1.1 brezak /* Read data from a file */
236 1.6 mycroft static size_t
237 1.1 brezak readdata(d, off, addr, len)
238 1.1 brezak register struct nfs_iodesc *d;
239 1.3 brezak register off_t off;
240 1.1 brezak register void *addr;
241 1.6 mycroft register size_t len;
242 1.1 brezak {
243 1.6 mycroft size_t cc;
244 1.6 mycroft struct nfs_call_data wbuf;
245 1.6 mycroft struct nfs_reply_data rbuf;
246 1.6 mycroft
247 1.6 mycroft bcopy(d->fh, wbuf.fh, NFS_FHSIZE);
248 1.6 mycroft wbuf.off = txdr_unsigned(off);
249 1.6 mycroft if (len > NFSREAD_SIZE)
250 1.6 mycroft len = NFSREAD_SIZE;
251 1.6 mycroft wbuf.len = txdr_unsigned(len);
252 1.6 mycroft wbuf.xxx = txdr_unsigned(0);
253 1.6 mycroft
254 1.6 mycroft cc = callrpc(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ,
255 1.6 mycroft &wbuf, sizeof(wbuf),
256 1.6 mycroft &rbuf, sizeof(rbuf) - NFSREAD_SIZE + len);
257 1.6 mycroft if (cc == -1 || cc < sizeof(rbuf) - NFSREAD_SIZE)
258 1.6 mycroft return (-1);
259 1.1 brezak
260 1.6 mycroft cc -= sizeof(rbuf) - NFSREAD_SIZE;
261 1.6 mycroft bcopy(rbuf.data, addr, cc);
262 1.1 brezak return (cc);
263 1.1 brezak }
264 1.1 brezak
265 1.1 brezak static struct iodesc *mountfs;
266 1.1 brezak static u_char mountfh[NFS_FHSIZE];
267 1.1 brezak static time_t mounttime;
268 1.1 brezak
269 1.1 brezak /*
270 1.1 brezak * nfs_mount - mount this nfs filesystem to a host
271 1.1 brezak */
272 1.1 brezak int
273 1.1 brezak nfs_mount(sock, ip, path)
274 1.1 brezak int sock;
275 1.1 brezak n_long ip;
276 1.1 brezak char *path;
277 1.1 brezak {
278 1.1 brezak struct iodesc *desc;
279 1.1 brezak struct nfs_iodesc *fp;
280 1.1 brezak u_long ftype;
281 1.1 brezak
282 1.1 brezak if (!(desc = socktodesc(sock))) {
283 1.1 brezak errno = EINVAL;
284 1.1 brezak return(-1);
285 1.1 brezak }
286 1.1 brezak bcopy(&desc->myea[4], &desc->myport, 2);
287 1.1 brezak desc->destip = ip;
288 1.1 brezak getmountfh(desc, path, mountfh);
289 1.1 brezak
290 1.1 brezak fp = alloc(sizeof(struct nfs_iodesc));
291 1.1 brezak fp->iodesc = desc;
292 1.1 brezak fp->fh = mountfh;
293 1.1 brezak fp->off = 0;
294 1.1 brezak if (getnfsinfo(fp, &mounttime, NULL, &ftype, NULL, NULL, NULL) < 0) {
295 1.1 brezak free(fp, sizeof(struct nfs_iodesc));
296 1.1 brezak return(-1);
297 1.1 brezak }
298 1.1 brezak
299 1.1 brezak if (ftype != NFDIR) {
300 1.1 brezak free(fp, sizeof(struct nfs_iodesc));
301 1.1 brezak errno = EINVAL;
302 1.1 brezak printf("nfs_mount: bad mount ftype %d", ftype);
303 1.1 brezak return(-1);
304 1.1 brezak }
305 1.1 brezak #ifdef NFS_DEBUG
306 1.1 brezak if (debug)
307 1.1 brezak printf("nfs_mount: got fh for %s, mtime=%d, ftype=%d\n",
308 1.1 brezak path, mounttime, ftype);
309 1.1 brezak #endif
310 1.1 brezak mountfs = desc;
311 1.1 brezak free(fp, sizeof(struct nfs_iodesc));
312 1.1 brezak
313 1.1 brezak return(0);
314 1.1 brezak }
315 1.1 brezak
316 1.1 brezak /*
317 1.1 brezak * Open a file.
318 1.1 brezak */
319 1.1 brezak int
320 1.1 brezak nfs_open(path, f)
321 1.1 brezak char *path;
322 1.1 brezak struct open_file *f;
323 1.1 brezak {
324 1.1 brezak register struct nfs_iodesc *fp;
325 1.1 brezak u_char *imagefh;
326 1.1 brezak u_long size, ftype;
327 1.1 brezak int rc = 0;
328 1.1 brezak
329 1.1 brezak #ifdef NFS_DEBUG
330 1.1 brezak if (debug)
331 1.1 brezak printf("nfs_open: %s\n", path);
332 1.1 brezak #endif
333 1.1 brezak if (!mountfs) {
334 1.1 brezak errno = EIO;
335 1.1 brezak printf("nfs_open: must mount first.\n");
336 1.1 brezak return(-1);
337 1.1 brezak }
338 1.1 brezak
339 1.1 brezak /* allocate file system specific data structure */
340 1.1 brezak fp = alloc(sizeof(struct nfs_iodesc));
341 1.1 brezak fp->iodesc = mountfs;
342 1.1 brezak fp->fh = mountfh;
343 1.1 brezak fp->off = 0;
344 1.1 brezak
345 1.1 brezak f->f_fsdata = (void *)fp;
346 1.1 brezak imagefh = alloc(NFS_FHSIZE);
347 1.1 brezak bzero(imagefh, NFS_FHSIZE);
348 1.1 brezak
349 1.1 brezak /* lookup a file handle */
350 1.1 brezak rc = lookupfh(fp, path, imagefh, NULL, &size, &ftype);
351 1.1 brezak if (rc < 0) {
352 1.1 brezak #ifdef NFS_DEBUG
353 1.1 brezak if (debug)
354 1.1 brezak printf("nfs_open: %s lookupfh failed: %s\n", path, strerror(errno));
355 1.1 brezak #endif
356 1.1 brezak f->f_fsdata = (void *)0;
357 1.1 brezak free(fp, sizeof(struct nfs_iodesc));
358 1.1 brezak free(imagefh, NFS_FHSIZE);
359 1.1 brezak return(rc);
360 1.1 brezak }
361 1.1 brezak fp->fh = imagefh;
362 1.1 brezak
363 1.1 brezak #ifdef NFS_DEBUG
364 1.1 brezak if (debug)
365 1.1 brezak printf("nfs_open: %s success, size=%d ftype=%d\n",
366 1.1 brezak path, size, ftype);
367 1.1 brezak #endif
368 1.1 brezak fp->size = size;
369 1.1 brezak
370 1.1 brezak return(rc);
371 1.1 brezak }
372 1.1 brezak
373 1.1 brezak int
374 1.1 brezak nfs_close(f)
375 1.1 brezak struct open_file *f;
376 1.1 brezak {
377 1.1 brezak register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
378 1.1 brezak
379 1.1 brezak #ifdef NFS_DEBUG
380 1.1 brezak if (debug)
381 1.1 brezak printf("nfs_close: called\n");
382 1.1 brezak #endif
383 1.1 brezak f->f_fsdata = (void *)0;
384 1.1 brezak if (fp == (struct nfs_iodesc *)0)
385 1.1 brezak return (0);
386 1.1 brezak
387 1.1 brezak free(fp->fh, NFS_FHSIZE);
388 1.1 brezak free(fp, sizeof(struct nfs_iodesc));
389 1.1 brezak
390 1.1 brezak return (0);
391 1.1 brezak }
392 1.1 brezak
393 1.1 brezak /*
394 1.1 brezak * read a portion of a file
395 1.1 brezak */
396 1.1 brezak int
397 1.1 brezak nfs_read(f, addr, size, resid)
398 1.1 brezak struct open_file *f;
399 1.1 brezak char *addr;
400 1.1 brezak u_int size;
401 1.1 brezak u_int *resid; /* out */
402 1.1 brezak {
403 1.1 brezak register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
404 1.6 mycroft register size_t cc;
405 1.1 brezak
406 1.1 brezak #ifdef NFS_DEBUG
407 1.1 brezak if (debug)
408 1.3 brezak printf("nfs_read: size=%d off=%d\n", size, (int)fp->off);
409 1.1 brezak #endif
410 1.1 brezak while (size > 0) {
411 1.1 brezak cc = readdata(fp->iodesc, fp->off, (void *)addr, size);
412 1.6 mycroft /* XXX maybe should retry on certain errors */
413 1.6 mycroft if (cc == -1) {
414 1.6 mycroft #ifdef NFS_DEBUG
415 1.6 mycroft if (debug)
416 1.6 mycroft printf("nfs_read: read: %s", strerror(errno));
417 1.1 brezak #endif
418 1.6 mycroft return (-1);
419 1.6 mycroft }
420 1.6 mycroft if (cc == 0) {
421 1.1 brezak if (debug)
422 1.1 brezak printf("nfs_read: hit EOF unexpectantly");
423 1.1 brezak goto ret;
424 1.1 brezak }
425 1.1 brezak fp->off += cc;
426 1.1 brezak addr += cc;
427 1.1 brezak size -= cc;
428 1.1 brezak }
429 1.1 brezak ret:
430 1.1 brezak if (resid)
431 1.1 brezak *resid = size;
432 1.1 brezak
433 1.1 brezak return (0);
434 1.1 brezak }
435 1.1 brezak
436 1.1 brezak /*
437 1.1 brezak * Not implemented.
438 1.1 brezak */
439 1.1 brezak int
440 1.1 brezak nfs_write(f, start, size, resid)
441 1.1 brezak struct open_file *f;
442 1.1 brezak char *start;
443 1.1 brezak u_int size;
444 1.1 brezak u_int *resid; /* out */
445 1.1 brezak {
446 1.1 brezak errno = EROFS;
447 1.1 brezak
448 1.1 brezak return (-1);
449 1.1 brezak }
450 1.1 brezak
451 1.1 brezak off_t
452 1.1 brezak nfs_seek(f, offset, where)
453 1.1 brezak struct open_file *f;
454 1.1 brezak off_t offset;
455 1.1 brezak int where;
456 1.1 brezak {
457 1.1 brezak register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
458 1.1 brezak
459 1.1 brezak switch (where) {
460 1.1 brezak case SEEK_SET:
461 1.1 brezak fp->off = offset;
462 1.1 brezak break;
463 1.1 brezak case SEEK_CUR:
464 1.1 brezak fp->off += offset;
465 1.1 brezak break;
466 1.1 brezak case SEEK_END:
467 1.1 brezak fp->off = fp->size - offset;
468 1.1 brezak break;
469 1.1 brezak default:
470 1.1 brezak return (-1);
471 1.1 brezak }
472 1.1 brezak return (fp->off);
473 1.1 brezak }
474 1.1 brezak
475 1.1 brezak int
476 1.1 brezak nfs_stat(f, sb)
477 1.1 brezak struct open_file *f;
478 1.1 brezak struct stat *sb;
479 1.1 brezak {
480 1.1 brezak register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
481 1.1 brezak mode_t mode = 0;
482 1.1 brezak u_long ftype = 0;
483 1.1 brezak
484 1.1 brezak #ifdef NFS_DEBUG
485 1.1 brezak if (debug)
486 1.6 mycroft printf("nfs_stat: called\n");
487 1.1 brezak #endif
488 1.6 mycroft
489 1.1 brezak if (getnfsinfo(fp, &mounttime, &sb->st_size, &ftype, &mode, &sb->st_uid, &sb->st_gid) < 0)
490 1.1 brezak return(-1);
491 1.1 brezak
492 1.1 brezak /* create a mode */
493 1.1 brezak switch (ftype) {
494 1.1 brezak case NFNON:
495 1.1 brezak sb->st_mode = 0;
496 1.1 brezak break;
497 1.1 brezak case NFREG:
498 1.1 brezak sb->st_mode = S_IFREG;
499 1.1 brezak break;
500 1.1 brezak case NFDIR:
501 1.1 brezak sb->st_mode = S_IFDIR;
502 1.1 brezak break;
503 1.1 brezak case NFBLK:
504 1.1 brezak sb->st_mode = S_IFBLK;
505 1.1 brezak break;
506 1.1 brezak case NFCHR:
507 1.1 brezak sb->st_mode = S_IFCHR;
508 1.1 brezak break;
509 1.1 brezak case NFLNK:
510 1.1 brezak sb->st_mode = S_IFLNK;
511 1.1 brezak break;
512 1.1 brezak }
513 1.1 brezak sb->st_mode |= mode;
514 1.1 brezak
515 1.1 brezak return (0);
516 1.1 brezak }
517