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