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