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