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