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