nfs_serv.c revision 1.8.2.3 1 /*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: @(#)nfs_serv.c 7.40 (Berkeley) 5/15/91
37 * nfs_serv.c,v 1.7 1993/09/03 23:57:25 jtc Exp
38 */
39
40 /*
41 * nfs version 2 server calls to vnode ops
42 * - these routines generally have 3 phases
43 * 1 - break down and validate rpc request in mbuf list
44 * 2 - do the vnode ops for the request
45 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
46 * 3 - build the rpc reply in an mbuf list
47 * nb:
48 * - do not mix the phases, since the nfsm_?? macros can return failures
49 * on a bad rpc or similar and do not do any vrele() or vput()'s
50 *
51 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs
52 * error number iff error != 0 whereas
53 * returning an error from the server function implies a fatal error
54 * such as a badly constructed rpc request that should be dropped without
55 * a reply.
56 */
57
58 #include <sys/param.h>
59 #include <sys/systm.h>
60 #include <sys/proc.h>
61 #include <sys/file.h>
62 #include <sys/namei.h>
63 #include <sys/vnode.h>
64 #include <sys/mount.h>
65 #include <sys/mbuf.h>
66
67 #include <ufs/quota.h>
68 #include <ufs/inode.h>
69 #include <ufs/dir.h>
70
71 #include <machine/cpu.h>
72
73 #include <nfs/nfsv2.h>
74 #include <nfs/nfs.h>
75 #include <nfs/xdr_subs.h>
76 #include <nfs/nfsm_subs.h>
77
78 /* Defs */
79 #define TRUE 1
80 #define FALSE 0
81
82 /* Global vars */
83 extern u_long nfs_procids[NFS_NPROCS];
84 extern u_long nfs_xdrneg1;
85 extern u_long nfs_false, nfs_true;
86 nfstype nfs_type[9]={ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
87 NFCHR, NFNON };
88
89 int nfsrv_null(),
90 nfsrv_getattr(),
91 nfsrv_setattr(),
92 nfsrv_lookup(),
93 nfsrv_readlink(),
94 nfsrv_read(),
95 nfsrv_write(),
96 nfsrv_create(),
97 nfsrv_remove(),
98 nfsrv_rename(),
99 nfsrv_link(),
100 nfsrv_symlink(),
101 nfsrv_mkdir(),
102 nfsrv_rmdir(),
103 nfsrv_readdir(),
104 nfsrv_statfs(),
105 nfsrv_noop();
106
107 int (*nfsrv_procs[NFS_NPROCS])() = {
108 nfsrv_null,
109 nfsrv_getattr,
110 nfsrv_setattr,
111 nfsrv_noop,
112 nfsrv_lookup,
113 nfsrv_readlink,
114 nfsrv_read,
115 nfsrv_noop,
116 nfsrv_write,
117 nfsrv_create,
118 nfsrv_remove,
119 nfsrv_rename,
120 nfsrv_link,
121 nfsrv_symlink,
122 nfsrv_mkdir,
123 nfsrv_rmdir,
124 nfsrv_readdir,
125 nfsrv_statfs,
126 };
127 /*
128 * nfs getattr service
129 */
130 nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat, p)
131 struct mbuf **mrq;
132 struct mbuf *mrep, *md;
133 caddr_t dpos;
134 struct ucred *cred;
135 u_long xid;
136 int *repstat;
137 struct proc *p;
138 {
139 register struct nfsv2_fattr *fp;
140 struct vattr va;
141 register struct vattr *vap = &va;
142 struct vnode *vp;
143 nfsv2fh_t nfh;
144 fhandle_t *fhp;
145 register u_long *tl;
146 register long t1;
147 caddr_t bpos;
148 int error = 0;
149 char *cp2;
150 struct mbuf *mb, *mb2, *mreq;
151
152 fhp = &nfh.fh_generic;
153 nfsm_srvmtofh(fhp);
154 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
155 nfsm_reply(0);
156 error = VOP_GETATTR(vp, vap, cred, p);
157 vput(vp);
158 nfsm_reply(NFSX_FATTR);
159 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
160 nfsm_srvfillattr;
161 nfsm_srvdone;
162 }
163
164 /*
165 * nfs setattr service
166 */
167 nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat, p)
168 struct mbuf **mrq;
169 struct mbuf *mrep, *md;
170 caddr_t dpos;
171 struct ucred *cred;
172 u_long xid;
173 int *repstat;
174 struct proc *p;
175 {
176 struct vattr va;
177 register struct vattr *vap = &va;
178 register struct nfsv2_sattr *sp;
179 register struct nfsv2_fattr *fp;
180 struct vnode *vp;
181 nfsv2fh_t nfh;
182 fhandle_t *fhp;
183 register u_long *tl;
184 register long t1;
185 caddr_t bpos;
186 int error = 0;
187 char *cp2;
188 struct mbuf *mb, *mb2, *mreq;
189
190 fhp = &nfh.fh_generic;
191 nfsm_srvmtofh(fhp);
192 nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR);
193 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
194 nfsm_reply(0);
195 if (error = nfsrv_access(vp, VWRITE, cred, p))
196 goto out;
197 VATTR_NULL(vap);
198 /*
199 * Nah nah nah nah na nah
200 * There is a bug in the Sun client that puts 0xffff in the mode
201 * field of sattr when it should put in 0xffffffff. The u_short
202 * doesn't sign extend.
203 * --> check the low order 2 bytes for 0xffff
204 */
205 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
206 vap->va_mode = nfstov_mode(sp->sa_mode);
207 if (sp->sa_uid != nfs_xdrneg1)
208 vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
209 if (sp->sa_gid != nfs_xdrneg1)
210 vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
211 if (sp->sa_size != nfs_xdrneg1)
212 vap->va_size = fxdr_unsigned(u_long, sp->sa_size);
213 /*
214 * The usec field of sa_atime is overloaded with the va_flags field
215 * for 4.4BSD clients. Hopefully other clients always set both the
216 * sec and usec fields to -1 when not setting the atime.
217 *
218 * jfw (at) ksr.com (6/2/93): Suns certainly don't set the usec field to
219 * -1 when *setting* the atime, resulting in
220 * va_flags acquiring random contents.
221 */
222 #if 0 /* bad assumption, NFS is too fragile to extend. */
223 if (sp->sa_atime.tv_sec != nfs_xdrneg1) {
224 vap->va_atime.tv_sec = fxdr_unsigned(long, sp->sa_atime.tv_sec);
225 vap->va_atime.tv_usec = 0;
226 }
227 if (sp->sa_atime.tv_usec != nfs_xdrneg1)
228 vap->va_flags = fxdr_unsigned(u_long, sp->sa_atime.tv_usec);
229 #else
230 if (sp->sa_atime.tv_sec != nfs_xdrneg1)
231 fxdr_time(&sp->sa_atime, &vap->va_atime);
232 #endif
233 if (sp->sa_mtime.tv_sec != nfs_xdrneg1)
234 fxdr_time(&sp->sa_mtime, &vap->va_mtime);
235 if (error = VOP_SETATTR(vp, vap, cred, p)) {
236 vput(vp);
237 nfsm_reply(0);
238 }
239 error = VOP_GETATTR(vp, vap, cred, p);
240 out:
241 vput(vp);
242 nfsm_reply(NFSX_FATTR);
243 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
244 nfsm_srvfillattr;
245 nfsm_srvdone;
246 }
247
248 /*
249 * nfs lookup rpc
250 */
251 nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat, p)
252 struct mbuf **mrq;
253 struct mbuf *mrep, *md;
254 caddr_t dpos;
255 struct ucred *cred;
256 u_long xid;
257 int *repstat;
258 struct proc *p;
259 {
260 register struct nfsv2_fattr *fp;
261 struct nameidata nd;
262 struct vnode *vp;
263 nfsv2fh_t nfh;
264 fhandle_t *fhp;
265 register caddr_t cp;
266 register u_long *tl;
267 register long t1;
268 caddr_t bpos;
269 int error = 0;
270 char *cp2;
271 struct mbuf *mb, *mb2, *mreq;
272 long len;
273 struct vattr va, *vap = &va;
274
275 fhp = &nfh.fh_generic;
276 nfsm_srvmtofh(fhp);
277 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
278 nd.ni_cred = cred;
279 nd.ni_nameiop = LOOKUP | LOCKLEAF;
280 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
281 nfsm_reply(0);
282 vp = nd.ni_vp;
283 bzero((caddr_t)fhp, sizeof(nfh));
284 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
285 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
286 vput(vp);
287 nfsm_reply(0);
288 }
289 error = VOP_GETATTR(vp, vap, cred, p);
290 vput(vp);
291 nfsm_reply(NFSX_FH+NFSX_FATTR);
292 nfsm_srvfhtom(fhp);
293 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
294 nfsm_srvfillattr;
295 nfsm_srvdone;
296 }
297
298 /*
299 * nfs readlink service
300 */
301 nfsrv_readlink(mrep, md, dpos, cred, xid, mrq, repstat, p)
302 struct mbuf **mrq;
303 struct mbuf *mrep, *md;
304 caddr_t dpos;
305 struct ucred *cred;
306 u_long xid;
307 int *repstat;
308 struct proc *p;
309 {
310 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
311 register struct iovec *ivp = iv;
312 register struct mbuf *mp;
313 register u_long *tl;
314 register long t1;
315 caddr_t bpos;
316 int error = 0;
317 char *cp2;
318 struct mbuf *mb, *mb2, *mp2, *mp3, *mreq;
319 struct vnode *vp;
320 nfsv2fh_t nfh;
321 fhandle_t *fhp;
322 struct uio io, *uiop = &io;
323 int i, tlen, len;
324
325 fhp = &nfh.fh_generic;
326 nfsm_srvmtofh(fhp);
327 len = 0;
328 i = 0;
329 while (len < NFS_MAXPATHLEN) {
330 MGET(mp, M_WAIT, MT_DATA);
331 MCLGET(mp, M_WAIT);
332 mp->m_len = NFSMSIZ(mp);
333 if (len == 0)
334 mp3 = mp2 = mp;
335 else {
336 mp2->m_next = mp;
337 mp2 = mp;
338 }
339 if ((len+mp->m_len) > NFS_MAXPATHLEN) {
340 mp->m_len = NFS_MAXPATHLEN-len;
341 len = NFS_MAXPATHLEN;
342 } else
343 len += mp->m_len;
344 ivp->iov_base = mtod(mp, caddr_t);
345 ivp->iov_len = mp->m_len;
346 i++;
347 ivp++;
348 }
349 uiop->uio_iov = iv;
350 uiop->uio_iovcnt = i;
351 uiop->uio_offset = 0;
352 uiop->uio_resid = len;
353 uiop->uio_rw = UIO_READ;
354 uiop->uio_segflg = UIO_SYSSPACE;
355 uiop->uio_procp = (struct proc *)0;
356 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) {
357 m_freem(mp3);
358 nfsm_reply(0);
359 }
360 if (vp->v_type != VLNK) {
361 error = EINVAL;
362 goto out;
363 }
364 error = VOP_READLINK(vp, uiop, cred);
365 out:
366 vput(vp);
367 if (error)
368 m_freem(mp3);
369 nfsm_reply(NFSX_UNSIGNED);
370 if (uiop->uio_resid > 0) {
371 len -= uiop->uio_resid;
372 tlen = nfsm_rndup(len);
373 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
374 }
375 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
376 *tl = txdr_unsigned(len);
377 mb->m_next = mp3;
378 nfsm_srvdone;
379 }
380
381 /*
382 * nfs read service
383 */
384 nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat, p)
385 struct mbuf **mrq;
386 struct mbuf *mrep, *md;
387 caddr_t dpos;
388 struct ucred *cred;
389 u_long xid;
390 int *repstat;
391 struct proc *p;
392 {
393 register struct iovec *iv;
394 struct iovec *iv2;
395 register struct mbuf *m;
396 register struct nfsv2_fattr *fp;
397 register u_long *tl;
398 register long t1;
399 caddr_t bpos;
400 int error = 0;
401 char *cp2;
402 struct mbuf *mb, *mb2, *mreq;
403 struct mbuf *m2, *m3;
404 struct vnode *vp;
405 nfsv2fh_t nfh;
406 fhandle_t *fhp;
407 struct uio io, *uiop = &io;
408 struct vattr va, *vap = &va;
409 int i, cnt, len, left, siz, tlen;
410 off_t off;
411
412 fhp = &nfh.fh_generic;
413 nfsm_srvmtofh(fhp);
414 nfsm_disect(tl, u_long *, NFSX_UNSIGNED);
415 off = fxdr_unsigned(off_t, *tl);
416 nfsm_srvstrsiz(cnt, NFS_MAXDATA);
417 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
418 nfsm_reply(0);
419 if ((error = nfsrv_access(vp, VREAD, cred, p)) &&
420 (error = nfsrv_access(vp, VEXEC, cred, p))) {
421 vput(vp);
422 nfsm_reply(0);
423 }
424 len = left = cnt;
425 /*
426 * Generate the mbuf list with the uio_iov ref. to it.
427 */
428 i = 0;
429 m3 = (struct mbuf *)0;
430 #ifdef lint
431 m2 = (struct mbuf *)0;
432 #endif /* lint */
433 MALLOC(iv, struct iovec *,
434 ((NFS_MAXDATA+MLEN-1)/MLEN) * sizeof (struct iovec), M_TEMP,
435 M_WAITOK);
436 iv2 = iv;
437 while (left > 0) {
438 MGET(m, M_WAIT, MT_DATA);
439 if (left > MINCLSIZE)
440 MCLGET(m, M_WAIT);
441 m->m_len = 0;
442 siz = min(M_TRAILINGSPACE(m), left);
443 m->m_len = siz;
444 iv->iov_base = mtod(m, caddr_t);
445 iv->iov_len = siz;
446 iv++;
447 i++;
448 left -= siz;
449 if (m3) {
450 m2->m_next = m;
451 m2 = m;
452 } else
453 m3 = m2 = m;
454 }
455 uiop->uio_iov = iv2;
456 uiop->uio_iovcnt = i;
457 uiop->uio_offset = off;
458 uiop->uio_resid = cnt;
459 uiop->uio_rw = UIO_READ;
460 uiop->uio_segflg = UIO_SYSSPACE;
461 uiop->uio_procp = (struct proc *)0;
462 error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
463 off = uiop->uio_offset;
464 FREE((caddr_t)iv2, M_TEMP);
465 if (error) {
466 m_freem(m3);
467 vput(vp);
468 nfsm_reply(0);
469 }
470 if (error = VOP_GETATTR(vp, vap, cred, p))
471 m_freem(m3);
472 vput(vp);
473 nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED);
474 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
475 nfsm_srvfillattr;
476 len -= uiop->uio_resid;
477 if (len > 0) {
478 tlen = nfsm_rndup(len);
479 if (cnt != tlen || tlen != len)
480 nfsm_adj(m3, cnt-tlen, tlen-len);
481 } else {
482 m_freem(m3);
483 m3 = (struct mbuf *)0;
484 }
485 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
486 *tl = txdr_unsigned(len);
487 mb->m_next = m3;
488 nfsm_srvdone;
489 }
490
491 /*
492 * nfs write service
493 */
494 nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat, p)
495 struct mbuf *mrep, *md, **mrq;
496 caddr_t dpos;
497 struct ucred *cred;
498 u_long xid;
499 int *repstat;
500 struct proc *p;
501 {
502 register struct iovec *ivp;
503 register struct mbuf *mp;
504 register struct nfsv2_fattr *fp;
505 struct iovec iv[NFS_MAXIOVEC];
506 struct vattr va;
507 register struct vattr *vap = &va;
508 register u_long *tl;
509 register long t1;
510 caddr_t bpos;
511 int error = 0;
512 char *cp2;
513 struct mbuf *mb, *mb2, *mreq;
514 struct vnode *vp;
515 nfsv2fh_t nfh;
516 fhandle_t *fhp;
517 struct uio io, *uiop = &io;
518 off_t off;
519 long siz, len, xfer;
520
521 fhp = &nfh.fh_generic;
522 nfsm_srvmtofh(fhp);
523 nfsm_disect(tl, u_long *, 4*NFSX_UNSIGNED);
524 off = fxdr_unsigned(off_t, *++tl);
525 tl += 2;
526 len = fxdr_unsigned(long, *tl);
527 if (len > NFS_MAXDATA || len <= 0) {
528 error = EBADRPC;
529 nfsm_reply(0);
530 }
531 if (dpos == (mtod(md, caddr_t)+md->m_len)) {
532 mp = md->m_next;
533 if (mp == NULL) {
534 error = EBADRPC;
535 nfsm_reply(0);
536 }
537 } else {
538 mp = md;
539 siz = dpos-mtod(mp, caddr_t);
540 mp->m_len -= siz;
541 NFSMADV(mp, siz);
542 }
543 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
544 nfsm_reply(0);
545 if (error = nfsrv_access(vp, VWRITE, cred, p)) {
546 vput(vp);
547 nfsm_reply(0);
548 }
549 uiop->uio_resid = 0;
550 uiop->uio_rw = UIO_WRITE;
551 uiop->uio_segflg = UIO_SYSSPACE;
552 uiop->uio_procp = (struct proc *)0;
553 /*
554 * Do up to NFS_MAXIOVEC mbufs of write each iteration of the
555 * loop until done.
556 */
557 while (len > 0 && uiop->uio_resid == 0) {
558 ivp = iv;
559 siz = 0;
560 uiop->uio_iov = ivp;
561 uiop->uio_iovcnt = 0;
562 uiop->uio_offset = off;
563 while (len > 0 && uiop->uio_iovcnt < NFS_MAXIOVEC && mp != NULL) {
564 ivp->iov_base = mtod(mp, caddr_t);
565 if (len < mp->m_len)
566 ivp->iov_len = xfer = len;
567 else
568 ivp->iov_len = xfer = mp->m_len;
569 #ifdef notdef
570 /* Not Yet .. */
571 if (M_HASCL(mp) && (((u_long)ivp->iov_base) & CLOFSET) == 0)
572 ivp->iov_op = NULL; /* what should it be ?? */
573 else
574 ivp->iov_op = NULL;
575 #endif
576 uiop->uio_iovcnt++;
577 ivp++;
578 len -= xfer;
579 siz += xfer;
580 mp = mp->m_next;
581 }
582 if (len > 0 && mp == NULL) {
583 error = EBADRPC;
584 vput(vp);
585 nfsm_reply(0);
586 }
587 uiop->uio_resid = siz;
588 if (error = VOP_WRITE(vp, uiop, IO_SYNC | IO_NODELOCKED,
589 cred)) {
590 vput(vp);
591 nfsm_reply(0);
592 }
593 off = uiop->uio_offset;
594 }
595 error = VOP_GETATTR(vp, vap, cred, p);
596 vput(vp);
597 nfsm_reply(NFSX_FATTR);
598 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
599 nfsm_srvfillattr;
600 nfsm_srvdone;
601 }
602
603 /*
604 * nfs create service
605 * if it already exists, just set length * 28 Aug 92*
606 * do NOT truncate unconditionally !
607 */
608 nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat, p)
609 struct mbuf *mrep, *md, **mrq;
610 caddr_t dpos;
611 struct ucred *cred;
612 u_long xid;
613 int *repstat;
614 struct proc *p;
615 {
616 register struct nfsv2_fattr *fp;
617 struct vattr va;
618 register struct vattr *vap = &va;
619 struct nameidata nd;
620 register caddr_t cp;
621 register u_long *tl;
622 register long t1;
623 caddr_t bpos;
624 long rdev;
625 int error = 0;
626 char *cp2;
627 struct mbuf *mb, *mb2, *mreq;
628 struct vnode *vp;
629 nfsv2fh_t nfh;
630 fhandle_t *fhp;
631 long len;
632
633 nd.ni_nameiop = 0;
634 fhp = &nfh.fh_generic;
635 nfsm_srvmtofh(fhp);
636 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
637 nd.ni_cred = cred;
638 nd.ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF | SAVESTART;
639 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
640 nfsm_reply(0);
641 VATTR_NULL(vap);
642 nfsm_disect(tl, u_long *, NFSX_SATTR);
643 /*
644 * If it doesn't exist, create it * 28 Aug 92*
645 * otherwise just set length from attributes
646 * should I set the mode too ??
647 */
648 if (nd.ni_vp == NULL) {
649 vap->va_type = IFTOVT(fxdr_unsigned(u_long, *tl));
650 if (vap->va_type == VNON)
651 vap->va_type = VREG;
652 vap->va_mode = nfstov_mode(*tl);
653 rdev = fxdr_unsigned(long, *(tl+3));
654 if (vap->va_type == VREG || vap->va_type == VSOCK) {
655 vrele(nd.ni_startdir);
656 if (error = VOP_CREATE(&nd, vap, p))
657 nfsm_reply(0);
658 FREE(nd.ni_pnbuf, M_NAMEI);
659 } else if (vap->va_type == VCHR || vap->va_type == VBLK ||
660 vap->va_type == VFIFO) {
661 if (vap->va_type == VCHR && rdev == 0xffffffff)
662 vap->va_type = VFIFO;
663 if (vap->va_type == VFIFO) {
664 #ifndef FIFO
665 VOP_ABORTOP(&nd);
666 vput(nd.ni_dvp);
667 error = ENXIO;
668 goto out;
669 #endif /* FIFO */
670 } else if (error = suser(cred, (u_short *)0)) {
671 VOP_ABORTOP(&nd);
672 vput(nd.ni_dvp);
673 goto out;
674 } else
675 vap->va_rdev = (dev_t)rdev;
676 if (error = VOP_MKNOD(&nd, vap, cred, p)) {
677 vrele(nd.ni_startdir);
678 nfsm_reply(0);
679 }
680 nd.ni_nameiop &= ~(OPMASK | LOCKPARENT | SAVESTART);
681 nd.ni_nameiop |= LOOKUP;
682 if (error = lookup(&nd, p)) {
683 free(nd.ni_pnbuf, M_NAMEI);
684 nfsm_reply(0);
685 }
686 FREE(nd.ni_pnbuf, M_NAMEI);
687 if (nd.ni_more) {
688 vrele(nd.ni_dvp);
689 vput(nd.ni_vp);
690 VOP_ABORTOP(&nd);
691 error = EINVAL;
692 nfsm_reply(0);
693 }
694 } else {
695 VOP_ABORTOP(&nd);
696 vput(nd.ni_dvp);
697 error = ENXIO;
698 goto out;
699 }
700 vp = nd.ni_vp;
701 } else {
702 vrele(nd.ni_startdir);
703 free(nd.ni_pnbuf, M_NAMEI);
704 vp = nd.ni_vp;
705 if (nd.ni_dvp == vp)
706 vrele(nd.ni_dvp);
707 else
708 vput(nd.ni_dvp);
709 VOP_ABORTOP(&nd);
710 vap->va_size = fxdr_unsigned(long, *(tl+3)); /* 28 Aug 92*/
711 /* 08 Sep 92*/ if (vap->va_size != -1 && (error = VOP_SETATTR(vp, vap, cred, p))) {
712 vput(vp);
713 nfsm_reply(0);
714 }
715 }
716 bzero((caddr_t)fhp, sizeof(nfh));
717 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
718 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
719 vput(vp);
720 nfsm_reply(0);
721 }
722 error = VOP_GETATTR(vp, vap, cred, p);
723 vput(vp);
724 nfsm_reply(NFSX_FH+NFSX_FATTR);
725 nfsm_srvfhtom(fhp);
726 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
727 nfsm_srvfillattr;
728 return (error);
729 nfsmout:
730 if (nd.ni_nameiop)
731 vrele(nd.ni_startdir);
732 VOP_ABORTOP(&nd);
733 if (nd.ni_dvp == nd.ni_vp)
734 vrele(nd.ni_dvp);
735 else
736 vput(nd.ni_dvp);
737 if (nd.ni_vp)
738 vput(nd.ni_vp);
739 return (error);
740
741 out:
742 vrele(nd.ni_startdir);
743 free(nd.ni_pnbuf, M_NAMEI);
744 nfsm_reply(0);
745 }
746
747 /*
748 * nfs remove service
749 */
750 nfsrv_remove(mrep, md, dpos, cred, xid, mrq, repstat, p)
751 struct mbuf *mrep, *md, **mrq;
752 caddr_t dpos;
753 struct ucred *cred;
754 u_long xid;
755 int *repstat;
756 struct proc *p;
757 {
758 struct nameidata nd;
759 register u_long *tl;
760 register long t1;
761 caddr_t bpos;
762 int error = 0;
763 char *cp2;
764 struct mbuf *mb, *mreq;
765 struct vnode *vp;
766 nfsv2fh_t nfh;
767 fhandle_t *fhp;
768 long len;
769
770 fhp = &nfh.fh_generic;
771 nfsm_srvmtofh(fhp);
772 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
773 nd.ni_cred = cred;
774 nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
775 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
776 nfsm_reply(0);
777 vp = nd.ni_vp;
778 if (vp->v_type == VDIR &&
779 (error = suser(cred, (u_short *)0)))
780 goto out;
781 /*
782 * The root of a mounted filesystem cannot be deleted.
783 */
784 if (vp->v_flag & VROOT) {
785 error = EBUSY;
786 goto out;
787 }
788 if (vp->v_flag & VTEXT)
789 (void) vnode_pager_uncache(vp);
790 out:
791 if (!error) {
792 error = VOP_REMOVE(&nd, p);
793 } else {
794 VOP_ABORTOP(&nd);
795 if (nd.ni_dvp == vp)
796 vrele(nd.ni_dvp);
797 else
798 vput(nd.ni_dvp);
799 vput(vp);
800 }
801 nfsm_reply(0);
802 nfsm_srvdone;
803 }
804
805 /*
806 * nfs rename service
807 */
808 nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat, p)
809 struct mbuf *mrep, *md, **mrq;
810 caddr_t dpos;
811 struct ucred *cred;
812 u_long xid;
813 int *repstat;
814 struct proc *p;
815 {
816 register u_long *tl;
817 register long t1;
818 caddr_t bpos;
819 int error = 0;
820 char *cp2;
821 struct mbuf *mb, *mreq;
822 struct nameidata fromnd, tond;
823 struct vnode *fvp, *tvp, *tdvp;
824 nfsv2fh_t fnfh, tnfh;
825 fhandle_t *ffhp, *tfhp;
826 long len, len2;
827 int rootflg = 0;
828
829 ffhp = &fnfh.fh_generic;
830 tfhp = &tnfh.fh_generic;
831 fromnd.ni_nameiop = 0;
832 tond.ni_nameiop = 0;
833 nfsm_srvmtofh(ffhp);
834 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
835 /*
836 * Remember if we are root so that we can reset cr_uid before
837 * the second nfs_namei() call
838 */
839 if (cred->cr_uid == 0)
840 rootflg++;
841 fromnd.ni_cred = cred;
842 fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART;
843 if (error = nfs_namei(&fromnd, ffhp, len, &md, &dpos, p))
844 nfsm_reply(0);
845 fvp = fromnd.ni_vp;
846 nfsm_srvmtofh(tfhp);
847 nfsm_strsiz(len2, NFS_MAXNAMLEN);
848 if (rootflg)
849 cred->cr_uid = 0;
850 tond.ni_cred = cred;
851 tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE
852 | SAVESTART;
853 if (error = nfs_namei(&tond, tfhp, len2, &md, &dpos, p)) {
854 VOP_ABORTOP(&fromnd);
855 vrele(fromnd.ni_dvp);
856 vrele(fvp);
857 goto out1;
858 }
859 tdvp = tond.ni_dvp;
860 tvp = tond.ni_vp;
861 if (tvp != NULL) {
862 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
863 error = EISDIR;
864 goto out;
865 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
866 error = ENOTDIR;
867 goto out;
868 }
869 }
870 if (fvp->v_mount != tdvp->v_mount) {
871 error = EXDEV;
872 goto out;
873 }
874 if (fvp == tdvp)
875 error = EINVAL;
876 /*
877 * If source is the same as the destination (that is the
878 * same vnode with the same name in the same directory),
879 * then there is nothing to do.
880 */
881 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
882 fromnd.ni_namelen == tond.ni_namelen &&
883 !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen))
884 error = -1;
885 out:
886 if (!error) {
887 error = VOP_RENAME(&fromnd, &tond, p);
888 } else {
889 VOP_ABORTOP(&tond);
890 if (tdvp == tvp)
891 vrele(tdvp);
892 else
893 vput(tdvp);
894 if (tvp)
895 vput(tvp);
896 VOP_ABORTOP(&fromnd);
897 vrele(fromnd.ni_dvp);
898 vrele(fvp);
899 }
900 vrele(tond.ni_startdir);
901 FREE(tond.ni_pnbuf, M_NAMEI);
902 out1:
903 vrele(fromnd.ni_startdir);
904 FREE(fromnd.ni_pnbuf, M_NAMEI);
905 nfsm_reply(0);
906 return (error);
907
908 nfsmout:
909 if (tond.ni_nameiop) {
910 vrele(tond.ni_startdir);
911 FREE(tond.ni_pnbuf, M_NAMEI);
912 }
913 if (fromnd.ni_nameiop) {
914 vrele(fromnd.ni_startdir);
915 FREE(fromnd.ni_pnbuf, M_NAMEI);
916 VOP_ABORTOP(&fromnd);
917 vrele(fromnd.ni_dvp);
918 vrele(fvp);
919 }
920 return (error);
921 }
922
923 /*
924 * nfs link service
925 */
926 nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat, p)
927 struct mbuf *mrep, *md, **mrq;
928 caddr_t dpos;
929 struct ucred *cred;
930 u_long xid;
931 int *repstat;
932 struct proc *p;
933 {
934 struct nameidata nd;
935 register u_long *tl;
936 register long t1;
937 caddr_t bpos;
938 int error = 0;
939 char *cp2;
940 struct mbuf *mb, *mreq;
941 struct vnode *vp, *xp;
942 nfsv2fh_t nfh, dnfh;
943 fhandle_t *fhp, *dfhp;
944 long len;
945
946 fhp = &nfh.fh_generic;
947 dfhp = &dnfh.fh_generic;
948 nfsm_srvmtofh(fhp);
949 nfsm_srvmtofh(dfhp);
950 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
951 if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred))
952 nfsm_reply(0);
953 if (vp->v_type == VDIR && (error = suser(cred, NULL)))
954 goto out1;
955 nd.ni_cred = cred;
956 nd.ni_nameiop = CREATE | LOCKPARENT;
957 if (error = nfs_namei(&nd, dfhp, len, &md, &dpos, p))
958 goto out1;
959 xp = nd.ni_vp;
960 if (xp != NULL) {
961 error = EEXIST;
962 goto out;
963 }
964 xp = nd.ni_dvp;
965 if (vp->v_mount != xp->v_mount)
966 error = EXDEV;
967 out:
968 if (!error) {
969 error = VOP_LINK(vp, &nd, p);
970 } else {
971 VOP_ABORTOP(&nd);
972 if (nd.ni_dvp == nd.ni_vp)
973 vrele(nd.ni_dvp);
974 else
975 vput(nd.ni_dvp);
976 if (nd.ni_vp)
977 vrele(nd.ni_vp);
978 }
979 out1:
980 vrele(vp);
981 nfsm_reply(0);
982 nfsm_srvdone;
983 }
984
985 /*
986 * nfs symbolic link service
987 */
988 nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat, p)
989 struct mbuf *mrep, *md, **mrq;
990 caddr_t dpos;
991 struct ucred *cred;
992 u_long xid;
993 int *repstat;
994 struct proc *p;
995 {
996 struct vattr va;
997 struct nameidata nd;
998 register struct vattr *vap = &va;
999 register u_long *tl;
1000 register long t1;
1001 struct nfsv2_sattr *sp;
1002 caddr_t bpos;
1003 struct uio io;
1004 struct iovec iv;
1005 int error = 0;
1006 char *pathcp, *cp2;
1007 struct mbuf *mb, *mreq;
1008 nfsv2fh_t nfh;
1009 fhandle_t *fhp;
1010 long len, len2;
1011
1012 pathcp = (char *)0;
1013 fhp = &nfh.fh_generic;
1014 nfsm_srvmtofh(fhp);
1015 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
1016 nd.ni_cred = cred;
1017 nd.ni_nameiop = CREATE | LOCKPARENT;
1018 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
1019 goto out;
1020 nfsm_strsiz(len2, NFS_MAXPATHLEN);
1021 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
1022 iv.iov_base = pathcp;
1023 iv.iov_len = len2;
1024 io.uio_resid = len2;
1025 io.uio_offset = 0;
1026 io.uio_iov = &iv;
1027 io.uio_iovcnt = 1;
1028 io.uio_segflg = UIO_SYSSPACE;
1029 io.uio_rw = UIO_READ;
1030 io.uio_procp = (struct proc *)0;
1031 nfsm_mtouio(&io, len2);
1032 nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR);
1033 *(pathcp + len2) = '\0';
1034 if (nd.ni_vp) {
1035 VOP_ABORTOP(&nd);
1036 if (nd.ni_dvp == nd.ni_vp)
1037 vrele(nd.ni_dvp);
1038 else
1039 vput(nd.ni_dvp);
1040 vrele(nd.ni_vp);
1041 error = EEXIST;
1042 goto out;
1043 }
1044 VATTR_NULL(vap);
1045 vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode);
1046 error = VOP_SYMLINK(&nd, vap, pathcp, p);
1047 out:
1048 if (pathcp)
1049 FREE(pathcp, M_TEMP);
1050 nfsm_reply(0);
1051 return (error);
1052 nfsmout:
1053 VOP_ABORTOP(&nd);
1054 if (nd.ni_dvp == nd.ni_vp)
1055 vrele(nd.ni_dvp);
1056 else
1057 vput(nd.ni_dvp);
1058 if (nd.ni_vp)
1059 vrele(nd.ni_vp);
1060 if (pathcp)
1061 FREE(pathcp, M_TEMP);
1062 return (error);
1063 }
1064
1065 /*
1066 * nfs mkdir service
1067 */
1068 nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat, p)
1069 struct mbuf *mrep, *md, **mrq;
1070 caddr_t dpos;
1071 struct ucred *cred;
1072 u_long xid;
1073 int *repstat;
1074 struct proc *p;
1075 {
1076 struct vattr va;
1077 register struct vattr *vap = &va;
1078 register struct nfsv2_fattr *fp;
1079 struct nameidata nd;
1080 register caddr_t cp;
1081 register u_long *tl;
1082 register long t1;
1083 caddr_t bpos;
1084 int error = 0;
1085 char *cp2;
1086 struct mbuf *mb, *mb2, *mreq;
1087 struct vnode *vp;
1088 nfsv2fh_t nfh;
1089 fhandle_t *fhp;
1090 long len;
1091
1092 fhp = &nfh.fh_generic;
1093 nfsm_srvmtofh(fhp);
1094 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
1095 nd.ni_cred = cred;
1096 nd.ni_nameiop = CREATE | LOCKPARENT;
1097 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
1098 nfsm_reply(0);
1099 nfsm_disect(tl, u_long *, NFSX_UNSIGNED);
1100 VATTR_NULL(vap);
1101 vap->va_type = VDIR;
1102 vap->va_mode = nfstov_mode(*tl++);
1103 vp = nd.ni_vp;
1104 if (vp != NULL) {
1105 VOP_ABORTOP(&nd);
1106 if (nd.ni_dvp == vp)
1107 vrele(nd.ni_dvp);
1108 else
1109 vput(nd.ni_dvp);
1110 vrele(vp);
1111 error = EEXIST;
1112 nfsm_reply(0);
1113 }
1114 if (error = VOP_MKDIR(&nd, vap, p))
1115 nfsm_reply(0);
1116 vp = nd.ni_vp;
1117 bzero((caddr_t)fhp, sizeof(nfh));
1118 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1119 if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
1120 vput(vp);
1121 nfsm_reply(0);
1122 }
1123 error = VOP_GETATTR(vp, vap, cred, p);
1124 vput(vp);
1125 nfsm_reply(NFSX_FH+NFSX_FATTR);
1126 nfsm_srvfhtom(fhp);
1127 nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
1128 nfsm_srvfillattr;
1129 return (error);
1130 nfsmout:
1131 VOP_ABORTOP(&nd);
1132 if (nd.ni_dvp == nd.ni_vp)
1133 vrele(nd.ni_dvp);
1134 else
1135 vput(nd.ni_dvp);
1136 if (nd.ni_vp)
1137 vrele(nd.ni_vp);
1138 return (error);
1139 }
1140
1141 /*
1142 * nfs rmdir service
1143 */
1144 nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat, p)
1145 struct mbuf *mrep, *md, **mrq;
1146 caddr_t dpos;
1147 struct ucred *cred;
1148 u_long xid;
1149 int *repstat;
1150 struct proc *p;
1151 {
1152 register u_long *tl;
1153 register long t1;
1154 caddr_t bpos;
1155 int error = 0;
1156 char *cp2;
1157 struct mbuf *mb, *mreq;
1158 struct vnode *vp;
1159 nfsv2fh_t nfh;
1160 fhandle_t *fhp;
1161 long len;
1162 struct nameidata nd;
1163
1164 fhp = &nfh.fh_generic;
1165 nfsm_srvmtofh(fhp);
1166 nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
1167 nd.ni_cred = cred;
1168 nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
1169 if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
1170 nfsm_reply(0);
1171 vp = nd.ni_vp;
1172 if (vp->v_type != VDIR) {
1173 error = ENOTDIR;
1174 goto out;
1175 }
1176 /*
1177 * No rmdir "." please.
1178 */
1179 if (nd.ni_dvp == vp) {
1180 error = EINVAL;
1181 goto out;
1182 }
1183 /*
1184 * The root of a mounted filesystem cannot be deleted.
1185 */
1186 if (vp->v_flag & VROOT)
1187 error = EBUSY;
1188 out:
1189 if (!error) {
1190 error = VOP_RMDIR(&nd, p);
1191 } else {
1192 VOP_ABORTOP(&nd);
1193 if (nd.ni_dvp == nd.ni_vp)
1194 vrele(nd.ni_dvp);
1195 else
1196 vput(nd.ni_dvp);
1197 vput(vp);
1198 }
1199 nfsm_reply(0);
1200 nfsm_srvdone;
1201 }
1202
1203 /*
1204 * nfs readdir service
1205 * - mallocs what it thinks is enough to read
1206 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
1207 * - calls VOP_READDIR()
1208 * - loops around building the reply
1209 * if the output generated exceeds count break out of loop
1210 * The nfsm_clget macro is used here so that the reply will be packed
1211 * tightly in mbuf clusters.
1212 * - it only knows that it has encountered eof when the VOP_READDIR()
1213 * reads nothing
1214 * - as such one readdir rpc will return eof false although you are there
1215 * and then the next will return eof
1216 * - it trims out records with d_ino == 0
1217 * this doesn't matter for Unix clients, but they might confuse clients
1218 * for other os'.
1219 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
1220 * than requested, but this may not apply to all filesystems. For
1221 * example, client NFS does not { although it is never remote mounted
1222 * anyhow }
1223 * PS: The NFS protocol spec. does not clarify what the "count" byte
1224 * argument is a count of.. just name strings and file id's or the
1225 * entire reply rpc or ...
1226 * I tried just file name and id sizes and it confused the Sun client,
1227 * so I am using the full rpc size now. The "paranoia.." comment refers
1228 * to including the status longwords that are not a part of the dir.
1229 * "entry" structures, but are in the rpc.
1230 */
1231 nfsrv_readdir(mrep, md, dpos, cred, xid, mrq, repstat, p)
1232 struct mbuf **mrq;
1233 struct mbuf *mrep, *md;
1234 caddr_t dpos;
1235 struct ucred *cred;
1236 u_long xid;
1237 int *repstat;
1238 struct proc *p;
1239 {
1240 register char *bp, *be;
1241 register struct mbuf *mp;
1242 register struct direct *dp;
1243 register caddr_t cp;
1244 register u_long *tl;
1245 register long t1;
1246 caddr_t bpos;
1247 int error = 0;
1248 char *cp2;
1249 struct mbuf *mb, *mb2, *mreq;
1250 char *cpos, *cend;
1251 int len, nlen, rem, xfer, tsiz, i;
1252 struct vnode *vp;
1253 struct mbuf *mp2, *mp3;
1254 nfsv2fh_t nfh;
1255 fhandle_t *fhp;
1256 struct uio io;
1257 struct iovec iv;
1258 int siz, cnt, fullsiz, eofflag;
1259 char *rbuf;
1260 off_t off;
1261 u_int *cookiebuf, *cookie;
1262 int ncookies;
1263
1264 fhp = &nfh.fh_generic;
1265 nfsm_srvmtofh(fhp);
1266 nfsm_disect(tl, u_long *, 2*NFSX_UNSIGNED);
1267 off = fxdr_unsigned(off_t, *tl++);
1268 cnt = fxdr_unsigned(int, *tl);
1269 siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));
1270 if (cnt > NFS_MAXREADDIR)
1271 siz = NFS_MAXREADDIR;
1272 fullsiz = siz;
1273 ncookies = siz / 16; /* guess on the number of cookies needed */
1274 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
1275 nfsm_reply(0);
1276 if (error = nfsrv_access(vp, VEXEC, cred, p)) {
1277 vput(vp);
1278 nfsm_reply(0);
1279 }
1280 VOP_UNLOCK(vp);
1281 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
1282 MALLOC(cookiebuf, u_int *, ncookies * sizeof(u_int), M_TEMP, M_WAITOK);
1283 again:
1284 iv.iov_base = rbuf;
1285 iv.iov_len = fullsiz;
1286 io.uio_iov = &iv;
1287 io.uio_iovcnt = 1;
1288 io.uio_offset = off;
1289 io.uio_resid = fullsiz;
1290 io.uio_segflg = UIO_SYSSPACE;
1291 io.uio_rw = UIO_READ;
1292 io.uio_procp = (struct proc *)0;
1293
1294 error = VOP_READDIR(vp, &io, cred, &eofflag, cookiebuf, ncookies);
1295 cookie = cookiebuf;
1296 off = io.uio_offset;
1297 if (error) {
1298 vrele(vp);
1299 free((caddr_t)rbuf, M_TEMP);
1300 free(cookiebuf,M_TEMP);
1301 nfsm_reply(0);
1302 }
1303 if (io.uio_resid) {
1304 siz -= io.uio_resid;
1305
1306 /*
1307 * If nothing read, return eof
1308 * rpc reply
1309 */
1310 if (siz == 0) {
1311 vrele(vp);
1312 nfsm_reply(2*NFSX_UNSIGNED);
1313 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
1314 *tl++ = nfs_false;
1315 *tl = nfs_true;
1316 FREE((caddr_t)cookiebuf, M_TEMP);
1317 FREE((caddr_t)rbuf, M_TEMP);
1318 return (0);
1319 }
1320 }
1321
1322 /*
1323 * Check for degenerate cases of nothing useful read.
1324 * If so go try again
1325 */
1326 cpos = rbuf;
1327 cend = rbuf + siz;
1328 while (cpos < cend) {
1329 dp = (struct direct *)cpos;
1330 if (cpos < rbuf || dp->d_ino == 0) {
1331 cpos += dp->d_reclen;
1332 cookie++;
1333 } else
1334 break;
1335 }
1336 if (cpos >= cend) {
1337 siz = fullsiz;
1338 goto again;
1339 }
1340
1341 vrele(vp);
1342 len = 3*NFSX_UNSIGNED; /* paranoia, probably can be 0 */
1343 bp = be = (caddr_t)0;
1344 mp3 = (struct mbuf *)0;
1345 nfsm_reply(siz);
1346
1347 /* Loop through the records and build reply */
1348 while (cpos < cend) {
1349 if (dp->d_ino != 0) {
1350 nlen = dp->d_namlen;
1351 rem = nfsm_rndup(nlen)-nlen;
1352
1353 /*
1354 * As noted above, the NFS spec. is not clear about what
1355 * should be included in "count" as totalled up here in
1356 * "len".
1357 */
1358 len += (4*NFSX_UNSIGNED+nlen+rem);
1359 if (len > cnt) {
1360 eofflag = 0;
1361 break;
1362 }
1363
1364 /* Build the directory record xdr from the direct entry */
1365 nfsm_clget;
1366 *tl = nfs_true;
1367 bp += NFSX_UNSIGNED;
1368 nfsm_clget;
1369 *tl = txdr_unsigned(dp->d_ino);
1370 bp += NFSX_UNSIGNED;
1371 nfsm_clget;
1372 *tl = txdr_unsigned(nlen);
1373 bp += NFSX_UNSIGNED;
1374
1375 /* And loop arround copying the name */
1376 xfer = nlen;
1377 cp = dp->d_name;
1378 while (xfer > 0) {
1379 nfsm_clget;
1380 if ((bp+xfer) > be)
1381 tsiz = be-bp;
1382 else
1383 tsiz = xfer;
1384 bcopy(cp, bp, tsiz);
1385 bp += tsiz;
1386 xfer -= tsiz;
1387 if (xfer > 0)
1388 cp += tsiz;
1389 }
1390 /* And null pad to a long boundary */
1391 for (i = 0; i < rem; i++)
1392 *bp++ = '\0';
1393 nfsm_clget;
1394
1395 /* Finish off the record */
1396 *tl = txdr_unsigned(*cookie);
1397 bp += NFSX_UNSIGNED;
1398 }
1399 cpos += dp->d_reclen;
1400 dp = (struct direct *)cpos;
1401 cookie++;
1402 }
1403 nfsm_clget;
1404 *tl = nfs_false;
1405 bp += NFSX_UNSIGNED;
1406 nfsm_clget;
1407 if (eofflag)
1408 *tl = nfs_true;
1409 else
1410 *tl = nfs_false;
1411 bp += NFSX_UNSIGNED;
1412 if (bp < be)
1413 mp->m_len = bp-mtod(mp, caddr_t);
1414 mb->m_next = mp3;
1415 FREE(cookiebuf, M_TEMP);
1416 FREE(rbuf, M_TEMP);
1417 nfsm_srvdone;
1418 }
1419
1420 /*
1421 * nfs statfs service
1422 */
1423 nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat, p)
1424 struct mbuf **mrq;
1425 struct mbuf *mrep, *md;
1426 caddr_t dpos;
1427 struct ucred *cred;
1428 u_long xid;
1429 int *repstat;
1430 struct proc *p;
1431 {
1432 register struct statfs *sf;
1433 register struct nfsv2_statfs *sfp;
1434 register u_long *tl;
1435 register long t1;
1436 caddr_t bpos;
1437 int error = 0;
1438 char *cp2;
1439 struct mbuf *mb, *mb2, *mreq;
1440 struct vnode *vp;
1441 nfsv2fh_t nfh;
1442 fhandle_t *fhp;
1443 struct statfs statfs;
1444
1445 fhp = &nfh.fh_generic;
1446 nfsm_srvmtofh(fhp);
1447 if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
1448 nfsm_reply(0);
1449 sf = &statfs;
1450 error = VFS_STATFS(vp->v_mount, sf, p);
1451 vput(vp);
1452 nfsm_reply(NFSX_STATFS);
1453 nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS);
1454 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
1455 sfp->sf_bsize = txdr_unsigned(sf->f_fsize);
1456 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
1457 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
1458 sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
1459 nfsm_srvdone;
1460 }
1461
1462 /*
1463 * Null operation, used by clients to ping server
1464 */
1465 /* ARGSUSED */
1466 nfsrv_null(mrep, md, dpos, cred, xid, mrq, repstat, p)
1467 struct mbuf **mrq;
1468 struct mbuf *mrep, *md;
1469 caddr_t dpos;
1470 struct ucred *cred;
1471 u_long xid;
1472 int *repstat;
1473 struct proc *p;
1474 {
1475 caddr_t bpos;
1476 int error = 0;
1477 struct mbuf *mb, *mreq;
1478
1479 error = VNOVAL;
1480 nfsm_reply(0);
1481 return (error);
1482 }
1483
1484 /*
1485 * No operation, used for obsolete procedures
1486 */
1487 /* ARGSUSED */
1488 nfsrv_noop(mrep, md, dpos, cred, xid, mrq, repstat, p)
1489 struct mbuf **mrq;
1490 struct mbuf *mrep, *md;
1491 caddr_t dpos;
1492 struct ucred *cred;
1493 u_long xid;
1494 int *repstat;
1495 struct proc *p;
1496 {
1497 caddr_t bpos;
1498 int error; /* 08 Sep 92*/
1499 struct mbuf *mb, *mreq;
1500
1501 if (*repstat) /* 08 Sep 92*/
1502 error = *repstat;
1503 else
1504 error = EPROCUNAVAIL;
1505 nfsm_reply(0);
1506 return (error);
1507 }
1508
1509 /*
1510 * Perform access checking for vnodes obtained from file handles that would
1511 * refer to files already opened by a Unix client. You cannot just use
1512 * vn_writechk() and VOP_ACCESS() for two reasons.
1513 * 1 - You must check for MNT_EXRDONLY as well as MNT_RDONLY for the write case
1514 * 2 - The owner is to be given access irrespective of mode bits so that
1515 * processes that chmod after opening a file don't break. I don't like
1516 * this because it opens a security hole, but since the nfs server opens
1517 * a security hole the size of a barn door anyhow, what the heck.
1518 */
1519 nfsrv_access(vp, flags, cred, p)
1520 register struct vnode *vp;
1521 int flags;
1522 register struct ucred *cred;
1523 struct proc *p;
1524 {
1525 struct vattr vattr;
1526 int error;
1527 if (flags & VWRITE) {
1528 /* Just vn_writechk() changed to check MNT_EXRDONLY */
1529 /*
1530 * Disallow write attempts on read-only file systems;
1531 * unless the file is a socket or a block or character
1532 * device resident on the file system.
1533 */
1534 if (vp->v_mount->mnt_flag & (MNT_RDONLY | MNT_EXRDONLY)) {
1535 switch (vp->v_type) {
1536 case VREG: case VDIR: case VLNK:
1537 return (EROFS);
1538 }
1539 }
1540 /*
1541 * If there's shared text associated with
1542 * the inode, try to free it up once. If
1543 * we fail, we can't allow writing.
1544 */
1545 if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp))
1546 return (ETXTBSY);
1547 }
1548 if (error = VOP_GETATTR(vp, &vattr, cred, p))
1549 return (error);
1550 if ((error = VOP_ACCESS(vp, flags, cred, p)) &&
1551 cred->cr_uid != vattr.va_uid)
1552 return (error);
1553 return (0);
1554 }
1555