|
|
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_subs.c 7.29 (Berkeley) 7/26/90
24: */
25:
26: /*
27: * These functions support the macros and help fiddle mbuf chains for
28: * the nfs op functions. They do things like create the rpc header and
29: * copy data between mbuf chains and uio lists.
30: */
31: #include "param.h"
32: #include "user.h"
33: #include "proc.h"
34: #include "systm.h"
35: #include "kernel.h"
36: #include "mount.h"
37: #include "file.h"
38: #include "vnode.h"
39: #include "mbuf.h"
40: #include "errno.h"
41: #include "map.h"
42: #include "rpcv2.h"
43: #include "nfsv2.h"
44: #include "nfsnode.h"
45: #include "nfs.h"
46: #include "nfsiom.h"
47: #include "xdr_subs.h"
48: #include "nfsm_subs.h"
49:
50: #define TRUE 1
51: #define FALSE 0
52:
53: /*
54: * Data items converted to xdr at startup, since they are constant
55: * This is kinda hokey, but may save a little time doing byte swaps
56: */
57: u_long nfs_procids[NFS_NPROCS];
58: u_long nfs_xdrneg1;
59: u_long rpc_call, rpc_vers, rpc_reply, rpc_msgdenied,
60: rpc_mismatch, rpc_auth_unix, rpc_msgaccepted;
61: u_long nfs_vers, nfs_prog, nfs_true, nfs_false;
62: /* And other global data */
63: static u_long *rpc_uidp = (u_long *)0;
64: static u_long nfs_xid = 1;
65: static char *rpc_unixauth;
66: extern long hostid;
67: enum vtype ntov_type[7] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON };
68: extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
69: extern struct map nfsmap[NFS_MSIZ];
70: extern struct nfsreq nfsreqh;
71:
72: /* Function ret types */
73: static char *nfs_unixauth();
74:
75: /*
76: * Maximum number of groups passed through to NFS server.
77: * According to RFC1057 it should be 16.
78: * For release 3.X systems, the maximum value is 8.
79: * For some other servers, the maximum value is 10.
80: */
81: int numgrps = 8;
82:
83: /*
84: * Create the header for an rpc request packet
85: * The function nfs_unixauth() creates a unix style authorization string
86: * and returns a ptr to it.
87: * The hsiz is the size of the rest of the nfs request header.
88: * (just used to decide if a cluster is a good idea)
89: * nb: Note that the prog, vers and procid args are already in xdr byte order
90: */
91: struct mbuf *nfsm_reqh(prog, vers, procid, cred, hsiz, bpos, mb, retxid)
92: u_long prog;
93: u_long vers;
94: u_long procid;
95: struct ucred *cred;
96: int hsiz;
97: caddr_t *bpos;
98: struct mbuf **mb;
99: u_long *retxid;
100: {
101: register struct mbuf *mreq, *m;
102: register u_long *p;
103: struct mbuf *m1;
104: char *ap;
105: int asiz, siz;
106:
107: NFSMGETHDR(mreq);
108: asiz = ((((cred->cr_ngroups - 1) > numgrps) ? numgrps :
109: (cred->cr_ngroups - 1)) << 2);
110: #ifdef FILLINHOST
111: asiz += nfsm_rndup(hostnamelen)+(9*NFSX_UNSIGNED);
112: #else
113: asiz += 9*NFSX_UNSIGNED;
114: #endif
115:
116: /* If we need a lot, alloc a cluster ?? */
117: if ((asiz+hsiz+RPC_SIZ) > MHLEN)
118: MCLGET(mreq, M_WAIT);
119: mreq->m_len = NFSMSIZ(mreq);
120: siz = mreq->m_len;
121: m1 = mreq;
122: /*
123: * Alloc enough mbufs
124: * We do it now to avoid all sleeps after the call to nfs_unixauth()
125: */
126: while ((asiz+RPC_SIZ) > siz) {
127: MGET(m, M_WAIT, MT_DATA);
128: m1->m_next = m;
129: m->m_len = MLEN;
130: siz += MLEN;
131: m1 = m;
132: }
133: p = mtod(mreq, u_long *);
134: *p++ = *retxid = txdr_unsigned(++nfs_xid);
135: *p++ = rpc_call;
136: *p++ = rpc_vers;
137: *p++ = prog;
138: *p++ = vers;
139: *p++ = procid;
140:
141: /* Now we can call nfs_unixauth() and copy it in */
142: ap = nfs_unixauth(cred);
143: m = mreq;
144: siz = m->m_len-RPC_SIZ;
145: if (asiz <= siz) {
146: bcopy(ap, (caddr_t)p, asiz);
147: m->m_len = asiz+RPC_SIZ;
148: } else {
149: bcopy(ap, (caddr_t)p, siz);
150: ap += siz;
151: asiz -= siz;
152: while (asiz > 0) {
153: siz = (asiz > MLEN) ? MLEN : asiz;
154: m = m->m_next;
155: bcopy(ap, mtod(m, caddr_t), siz);
156: m->m_len = siz;
157: asiz -= siz;
158: ap += siz;
159: }
160: }
161:
162: /* Finally, return values */
163: *mb = m;
164: *bpos = mtod(m, caddr_t)+m->m_len;
165: return (mreq);
166: }
167:
168: /*
169: * copies mbuf chain to the uio scatter/gather list
170: */
171: nfsm_mbuftouio(mrep, uiop, siz, dpos)
172: struct mbuf **mrep;
173: register struct uio *uiop;
174: int siz;
175: caddr_t *dpos;
176: {
177: register char *mbufcp, *uiocp;
178: register int xfer, left, len;
179: register struct mbuf *mp;
180: long uiosiz, rem;
181: int error = 0;
182:
183: mp = *mrep;
184: mbufcp = *dpos;
185: len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
186: rem = nfsm_rndup(siz)-siz;
187: while (siz > 0) {
188: if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
189: return (EFBIG);
190: left = uiop->uio_iov->iov_len;
191: uiocp = uiop->uio_iov->iov_base;
192: if (left > siz)
193: left = siz;
194: uiosiz = left;
195: while (left > 0) {
196: while (len == 0) {
197: mp = mp->m_next;
198: if (mp == NULL)
199: return (EBADRPC);
200: mbufcp = mtod(mp, caddr_t);
201: len = mp->m_len;
202: }
203: xfer = (left > len) ? len : left;
204: #ifdef notdef
205: /* Not Yet.. */
206: if (uiop->uio_iov->iov_op != NULL)
207: (*(uiop->uio_iov->iov_op))
208: (mbufcp, uiocp, xfer);
209: else
210: #endif
211: if (uiop->uio_segflg == UIO_SYSSPACE)
212: bcopy(mbufcp, uiocp, xfer);
213: else
214: copyout(mbufcp, uiocp, xfer);
215: left -= xfer;
216: len -= xfer;
217: mbufcp += xfer;
218: uiocp += xfer;
219: uiop->uio_offset += xfer;
220: uiop->uio_resid -= xfer;
221: }
222: if (uiop->uio_iov->iov_len <= siz) {
223: uiop->uio_iovcnt--;
224: uiop->uio_iov++;
225: } else {
226: uiop->uio_iov->iov_base += uiosiz;
227: uiop->uio_iov->iov_len -= uiosiz;
228: }
229: siz -= uiosiz;
230: }
231: *dpos = mbufcp;
232: *mrep = mp;
233: if (rem > 0) {
234: if (len < rem)
235: error = nfs_adv(mrep, dpos, rem, len);
236: else
237: *dpos += rem;
238: }
239: return (error);
240: }
241:
242: /*
243: * copies a uio scatter/gather list to an mbuf chain...
244: */
245: nfsm_uiotombuf(uiop, mq, siz, bpos)
246: register struct uio *uiop;
247: struct mbuf **mq;
248: int siz;
249: caddr_t *bpos;
250: {
251: register char *uiocp;
252: register struct mbuf *mp, *mp2;
253: register int xfer, left, len;
254: int uiosiz, clflg, rem;
255: char *cp;
256:
257: if (siz > MLEN) /* or should it >= MCLBYTES ?? */
258: clflg = 1;
259: else
260: clflg = 0;
261: rem = nfsm_rndup(siz)-siz;
262: mp2 = *mq;
263: while (siz > 0) {
264: if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
265: return (EINVAL);
266: left = uiop->uio_iov->iov_len;
267: uiocp = uiop->uio_iov->iov_base;
268: if (left > siz)
269: left = siz;
270: uiosiz = left;
271: while (left > 0) {
272: MGET(mp, M_WAIT, MT_DATA);
273: if (clflg)
274: MCLGET(mp, M_WAIT);
275: mp->m_len = NFSMSIZ(mp);
276: mp2->m_next = mp;
277: mp2 = mp;
278: xfer = (left > mp->m_len) ? mp->m_len : left;
279: #ifdef notdef
280: /* Not Yet.. */
281: if (uiop->uio_iov->iov_op != NULL)
282: (*(uiop->uio_iov->iov_op))
283: (uiocp, mtod(mp, caddr_t), xfer);
284: else
285: #endif
286: if (uiop->uio_segflg == UIO_SYSSPACE)
287: bcopy(uiocp, mtod(mp, caddr_t), xfer);
288: else
289: copyin(uiocp, mtod(mp, caddr_t), xfer);
290: len = mp->m_len;
291: mp->m_len = xfer;
292: left -= xfer;
293: uiocp += xfer;
294: uiop->uio_offset += xfer;
295: uiop->uio_resid -= xfer;
296: }
297: if (uiop->uio_iov->iov_len <= siz) {
298: uiop->uio_iovcnt--;
299: uiop->uio_iov++;
300: } else {
301: uiop->uio_iov->iov_base += uiosiz;
302: uiop->uio_iov->iov_len -= uiosiz;
303: }
304: siz -= uiosiz;
305: }
306: if (rem > 0) {
307: if (rem > (len-mp->m_len)) {
308: MGET(mp, M_WAIT, MT_DATA);
309: mp->m_len = 0;
310: mp2->m_next = mp;
311: }
312: cp = mtod(mp, caddr_t)+mp->m_len;
313: for (left = 0; left < rem; left++)
314: *cp++ = '\0';
315: mp->m_len += rem;
316: *bpos = cp;
317: } else
318: *bpos = mtod(mp, caddr_t)+mp->m_len;
319: *mq = mp;
320: return (0);
321: }
322:
323: /*
324: * Help break down an mbuf chain by setting the first siz bytes contiguous
325: * pointed to by returned val.
326: * If Updateflg == True we can overwrite the first part of the mbuf data
327: * This is used by the macros nfsm_disect and nfsm_disecton for tough
328: * cases. (The macros use the vars. dpos and dpos2)
329: */
330: nfsm_disct(mdp, dposp, siz, left, updateflg, cp2)
331: struct mbuf **mdp;
332: caddr_t *dposp;
333: int siz;
334: int left;
335: int updateflg;
336: caddr_t *cp2;
337: {
338: register struct mbuf *mp, *mp2;
339: register int siz2, xfer;
340: register caddr_t p;
341:
342: mp = *mdp;
343: while (left == 0) {
344: *mdp = mp = mp->m_next;
345: if (mp == NULL)
346: return (EBADRPC);
347: left = mp->m_len;
348: *dposp = mtod(mp, caddr_t);
349: }
350: if (left >= siz) {
351: *cp2 = *dposp;
352: *dposp += siz;
353: } else if (mp->m_next == NULL) {
354: return (EBADRPC);
355: } else if (siz > MHLEN) {
356: panic("nfs S too big");
357: } else {
358: /* Iff update, you can overwrite, else must alloc new mbuf */
359: if (updateflg) {
360: NFSMINOFF(mp);
361: } else {
362: MGET(mp2, M_WAIT, MT_DATA);
363: mp2->m_next = mp->m_next;
364: mp->m_next = mp2;
365: mp->m_len -= left;
366: mp = mp2;
367: }
368: *cp2 = p = mtod(mp, caddr_t);
369: bcopy(*dposp, p, left); /* Copy what was left */
370: siz2 = siz-left;
371: p += left;
372: mp2 = mp->m_next;
373: /* Loop around copying up the siz2 bytes */
374: while (siz2 > 0) {
375: if (mp2 == NULL)
376: return (EBADRPC);
377: xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
378: if (xfer > 0) {
379: bcopy(mtod(mp2, caddr_t), p, xfer);
380: NFSMADV(mp2, xfer);
381: mp2->m_len -= xfer;
382: p += xfer;
383: siz2 -= xfer;
384: }
385: if (siz2 > 0)
386: mp2 = mp2->m_next;
387: }
388: mp->m_len = siz;
389: *mdp = mp2;
390: *dposp = mtod(mp2, caddr_t);
391: }
392: return (0);
393: }
394:
395: /*
396: * Advance the position in the mbuf chain.
397: */
398: nfs_adv(mdp, dposp, offs, left)
399: struct mbuf **mdp;
400: caddr_t *dposp;
401: int offs;
402: int left;
403: {
404: register struct mbuf *m;
405: register int s;
406:
407: m = *mdp;
408: s = left;
409: while (s < offs) {
410: offs -= s;
411: m = m->m_next;
412: if (m == NULL)
413: return (EBADRPC);
414: s = m->m_len;
415: }
416: *mdp = m;
417: *dposp = mtod(m, caddr_t)+offs;
418: return (0);
419: }
420:
421: /*
422: * Copy a string into mbufs for the hard cases...
423: */
424: nfsm_strtmbuf(mb, bpos, cp, siz)
425: struct mbuf **mb;
426: char **bpos;
427: char *cp;
428: long siz;
429: {
430: register struct mbuf *m1, *m2;
431: long left, xfer, len, tlen;
432: u_long *p;
433: int putsize;
434:
435: putsize = 1;
436: m2 = *mb;
437: left = NFSMSIZ(m2)-m2->m_len;
438: if (left > 0) {
439: p = ((u_long *)(*bpos));
440: *p++ = txdr_unsigned(siz);
441: putsize = 0;
442: left -= NFSX_UNSIGNED;
443: m2->m_len += NFSX_UNSIGNED;
444: if (left > 0) {
445: bcopy(cp, (caddr_t) p, left);
446: siz -= left;
447: cp += left;
448: m2->m_len += left;
449: left = 0;
450: }
451: }
452: /* Loop arround adding mbufs */
453: while (siz > 0) {
454: MGET(m1, M_WAIT, MT_DATA);
455: if (siz > MLEN)
456: MCLGET(m1, M_WAIT);
457: m1->m_len = NFSMSIZ(m1);
458: m2->m_next = m1;
459: m2 = m1;
460: p = mtod(m1, u_long *);
461: tlen = 0;
462: if (putsize) {
463: *p++ = txdr_unsigned(siz);
464: m1->m_len -= NFSX_UNSIGNED;
465: tlen = NFSX_UNSIGNED;
466: putsize = 0;
467: }
468: if (siz < m1->m_len) {
469: len = nfsm_rndup(siz);
470: xfer = siz;
471: if (xfer < len)
472: *(p+(xfer>>2)) = 0;
473: } else {
474: xfer = len = m1->m_len;
475: }
476: bcopy(cp, (caddr_t) p, xfer);
477: m1->m_len = len+tlen;
478: siz -= xfer;
479: cp += xfer;
480: }
481: *mb = m1;
482: *bpos = mtod(m1, caddr_t)+m1->m_len;
483: return (0);
484: }
485:
486: /*
487: * Called once to initialize data structures...
488: */
489: nfs_init()
490: {
491: register int i;
492:
493: rpc_vers = txdr_unsigned(RPC_VER2);
494: rpc_call = txdr_unsigned(RPC_CALL);
495: rpc_reply = txdr_unsigned(RPC_REPLY);
496: rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
497: rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
498: rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
499: rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
500: nfs_vers = txdr_unsigned(NFS_VER2);
501: nfs_prog = txdr_unsigned(NFS_PROG);
502: nfs_true = txdr_unsigned(TRUE);
503: nfs_false = txdr_unsigned(FALSE);
504: /* Loop thru nfs procids */
505: for (i = 0; i < NFS_NPROCS; i++)
506: nfs_procids[i] = txdr_unsigned(i);
507: /* Ensure async daemons disabled */
508: for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
509: nfs_iodwant[i] = (struct proc *)0;
510: nfs_xdrneg1 = txdr_unsigned(-1);
511: nfs_nhinit(); /* Init the nfsnode table */
512: nfsrv_initcache(); /* Init the server request cache */
513: rminit(nfsmap, (long)NFS_MAPREG, (long)1, "nfs mapreg", NFS_MSIZ);
514:
515: /*
516: * Initialize reply list and start timer
517: */
518: nfsreqh.r_prev = nfsreqh.r_next = &nfsreqh;
519: nfs_timer();
520: }
521:
522: /*
523: * Fill in the rest of the rpc_unixauth and return it
524: */
525: static char *nfs_unixauth(cr)
526: register struct ucred *cr;
527: {
528: register u_long *p;
529: register int i;
530: int ngr;
531:
532: /* Maybe someday there should be a cache of AUTH_SHORT's */
533: if ((p = rpc_uidp) == NULL) {
534: #ifdef FILLINHOST
535: i = nfsm_rndup(hostnamelen)+(25*NFSX_UNSIGNED);
536: #else
537: i = 25*NFSX_UNSIGNED;
538: #endif
539: MALLOC(p, u_long *, i, M_TEMP, M_WAITOK);
540: bzero((caddr_t)p, i);
541: rpc_unixauth = (caddr_t)p;
542: *p++ = txdr_unsigned(RPCAUTH_UNIX);
543: p++; /* Fill in size later */
544: *p++ = hostid;
545: #ifdef FILLINHOST
546: *p++ = txdr_unsigned(hostnamelen);
547: i = nfsm_rndup(hostnamelen);
548: bcopy(hostname, (caddr_t)p, hostnamelen);
549: p += (i>>2);
550: #else
551: *p++ = 0;
552: #endif
553: rpc_uidp = p;
554: }
555: *p++ = txdr_unsigned(cr->cr_uid);
556: *p++ = txdr_unsigned(cr->cr_groups[0]);
557: ngr = ((cr->cr_ngroups - 1) > numgrps) ? numgrps : (cr->cr_ngroups - 1);
558: *p++ = txdr_unsigned(ngr);
559: for (i = 1; i <= ngr; i++)
560: *p++ = txdr_unsigned(cr->cr_groups[i]);
561: /* And add the AUTH_NULL */
562: *p++ = 0;
563: *p = 0;
564: i = (((caddr_t)p)-rpc_unixauth)-12;
565: p = (u_long *)(rpc_unixauth+4);
566: *p = txdr_unsigned(i);
567: return (rpc_unixauth);
568: }
569:
570: /*
571: * Attribute cache routines.
572: * nfs_loadattrcache() - loads or updates the cache contents from attributes
573: * that are on the mbuf list
574: * nfs_getattrcache() - returns valid attributes if found in cache, returns
575: * error otherwise
576: */
577:
578: /*
579: * Load the attribute cache (that lives in the nfsnode entry) with
580: * the values on the mbuf list and
581: * Iff vap not NULL
582: * copy the attributes to *vaper
583: */
584: nfs_loadattrcache(vpp, mdp, dposp, vaper)
585: struct vnode **vpp;
586: struct mbuf **mdp;
587: caddr_t *dposp;
588: struct vattr *vaper;
589: {
590: register struct vnode *vp = *vpp;
591: register struct vattr *vap;
592: register struct nfsv2_fattr *fp;
593: extern struct vnodeops spec_nfsv2nodeops;
594: register struct nfsnode *np;
595: register long t1;
596: caddr_t dpos, cp2;
597: int error = 0;
598: struct mbuf *md;
599: enum vtype type;
600: long rdev;
601: struct timeval mtime;
602: struct vnode *nvp;
603:
604: md = *mdp;
605: dpos = *dposp;
606: t1 = (mtod(md, caddr_t)+md->m_len)-dpos;
607: if (error = nfsm_disct(&md, &dpos, NFSX_FATTR, t1, TRUE, &cp2))
608: return (error);
609: fp = (struct nfsv2_fattr *)cp2;
610: type = nfstov_type(fp->fa_type);
611: rdev = fxdr_unsigned(long, fp->fa_rdev);
612: fxdr_time(&fp->fa_mtime, &mtime);
613: /*
614: * If v_type == VNON it is a new node, so fill in the v_type,
615: * n_mtime fields. Check to see if it represents a special
616: * device, and if so, check for a possible alias. Once the
617: * correct vnode has been obtained, fill in the rest of the
618: * information.
619: */
620: np = VTONFS(vp);
621: if (vp->v_type == VNON) {
622: if (type == VCHR && rdev == 0xffffffff)
623: vp->v_type = type = VFIFO;
624: else
625: vp->v_type = type;
626: if (vp->v_type == VFIFO) {
627: #ifdef FIFO
628: extern struct vnodeops fifo_nfsv2nodeops;
629: vp->v_op = &fifo_nfsv2nodeops;
630: #else
631: return (EOPNOTSUPP);
632: #endif /* FIFO */
633: }
634: if (vp->v_type == VCHR || vp->v_type == VBLK) {
635: vp->v_op = &spec_nfsv2nodeops;
636: if (nvp = checkalias(vp, (dev_t)rdev, vp->v_mount)) {
637: /*
638: * Reinitialize aliased node.
639: */
640: np = VTONFS(nvp);
641: np->n_vnode = nvp;
642: np->n_flag = 0;
643: nfs_lock(nvp);
644: bcopy((caddr_t)&VTONFS(vp)->n_fh,
645: (caddr_t)&np->n_fh, NFSX_FH);
646: insque(np, nfs_hash(&np->n_fh));
647: np->n_attrstamp = 0;
648: np->n_sillyrename = (struct sillyrename *)0;
649: /*
650: * Discard unneeded vnode and update actual one
651: */
652: vput(vp);
653: *vpp = nvp;
654: }
655: }
656: np->n_mtime = mtime.tv_sec;
657: }
658: vap = &np->n_vattr;
659: vap->va_type = type;
660: vap->va_mode = nfstov_mode(fp->fa_mode);
661: vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
662: vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
663: vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
664: vap->va_size = fxdr_unsigned(u_long, fp->fa_size);
665: if ((np->n_flag & NMODIFIED) == 0 || vap->va_size > np->n_size)
666: np->n_size = vap->va_size;
667: vap->va_size_rsv = 0;
668: vap->va_blocksize = fxdr_unsigned(long, fp->fa_blocksize);
669: vap->va_rdev = (dev_t)rdev;
670: vap->va_bytes = fxdr_unsigned(long, fp->fa_blocks) * NFS_FABLKSIZE;
671: vap->va_bytes_rsv = 0;
672: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
673: vap->va_fileid = fxdr_unsigned(long, fp->fa_fileid);
674: vap->va_atime.tv_sec = fxdr_unsigned(long, fp->fa_atime.tv_sec);
675: vap->va_atime.tv_usec = 0;
676: vap->va_flags = fxdr_unsigned(u_long, fp->fa_atime.tv_usec);
677: vap->va_mtime = mtime;
678: vap->va_ctime.tv_sec = fxdr_unsigned(long, fp->fa_ctime.tv_sec);
679: vap->va_ctime.tv_usec = 0;
680: vap->va_gen = fxdr_unsigned(u_long, fp->fa_ctime.tv_usec);
681: np->n_attrstamp = time.tv_sec;
682: *dposp = dpos;
683: *mdp = md;
684: if (vaper != NULL) {
685: bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
686: if ((np->n_flag & NMODIFIED) && (np->n_size > vap->va_size))
687: vaper->va_size = np->n_size;
688: }
689: return (0);
690: }
691:
692: /*
693: * Check the time stamp
694: * If the cache is valid, copy contents to *vap and return 0
695: * otherwise return an error
696: */
697: nfs_getattrcache(vp, vap)
698: register struct vnode *vp;
699: struct vattr *vap;
700: {
701: register struct nfsnode *np;
702:
703: np = VTONFS(vp);
704: if ((time.tv_sec-np->n_attrstamp) < NFS_ATTRTIMEO) {
705: nfsstats.attrcache_hits++;
706: bcopy((caddr_t)&np->n_vattr,(caddr_t)vap,sizeof(struct vattr));
707: if ((np->n_flag & NMODIFIED) == 0)
708: np->n_size = vap->va_size;
709: else if (np->n_size > vap->va_size)
710: vap->va_size = np->n_size;
711: return (0);
712: } else {
713: nfsstats.attrcache_misses++;
714: return (ENOENT);
715: }
716: }
717:
718: /*
719: * Set up nameidata for a namei() call and do it
720: */
721: nfs_namei(ndp, fhp, len, mdp, dposp)
722: register struct nameidata *ndp;
723: fhandle_t *fhp;
724: int len;
725: struct mbuf **mdp;
726: caddr_t *dposp;
727: {
728: register int i, rem;
729: register struct mbuf *md;
730: register char *cp;
731: struct vnode *dp;
732: int flag;
733: int error;
734:
735: if ((ndp->ni_nameiop & HASBUF) == 0) {
736: flag = ndp->ni_nameiop & OPFLAG;
737: /*
738: * Copy the name from the mbuf list to the d_name field of ndp
739: * and set the various ndp fields appropriately.
740: */
741: cp = *dposp;
742: md = *mdp;
743: rem = mtod(md, caddr_t)+md->m_len-cp;
744: ndp->ni_hash = 0;
745: for (i = 0; i < len;) {
746: while (rem == 0) {
747: md = md->m_next;
748: if (md == NULL)
749: return (EBADRPC);
750: cp = mtod(md, caddr_t);
751: rem = md->m_len;
752: }
753: if (*cp == '\0' || *cp == '/')
754: return (EINVAL);
755: if (*cp & 0200)
756: if ((*cp&0377) == ('/'|0200) || flag != DELETE)
757: return (EINVAL);
758: ndp->ni_dent.d_name[i++] = *cp;
759: ndp->ni_hash += (unsigned char)*cp * i;
760: cp++;
761: rem--;
762: }
763: *mdp = md;
764: *dposp = cp;
765: len = nfsm_rndup(len)-len;
766: if (len > 0) {
767: if (rem < len) {
768: if (error = nfs_adv(mdp, dposp, len, rem))
769: return (error);
770: } else
771: *dposp += len;
772: }
773: } else
774: i = len;
775: ndp->ni_namelen = i;
776: ndp->ni_dent.d_namlen = i;
777: ndp->ni_dent.d_name[i] = '\0';
778: ndp->ni_segflg = UIO_SYSSPACE;
779: ndp->ni_pathlen = 1;
780: ndp->ni_pnbuf = ndp->ni_dirp = ndp->ni_ptr = &ndp->ni_dent.d_name[0];
781: ndp->ni_next = &ndp->ni_dent.d_name[i];
782: ndp->ni_nameiop |= (NOCROSSMOUNT | REMOTE | HASBUF);
783:
784: if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cred))
785: return (error);
786: if (dp->v_type != VDIR) {
787: vrele(dp);
788: return (ENOTDIR);
789: }
790: /*
791: * Must set current directory here to avoid confusion in namei()
792: * called from rename()
793: */
794: ndp->ni_cdir = dp;
795: ndp->ni_rdir = NULLVP;
796:
797: /*
798: * And call namei() to do the real work
799: */
800: error = namei(ndp);
801: vrele(dp);
802: return (error);
803: }
804:
805: /*
806: * A fiddled version of m_adj() that ensures null fill to a long
807: * boundary and only trims off the back end
808: */
809: nfsm_adj(mp, len, nul)
810: struct mbuf *mp;
811: register int len;
812: int nul;
813: {
814: register struct mbuf *m;
815: register int count, i;
816: register char *cp;
817:
818: /*
819: * Trim from tail. Scan the mbuf chain,
820: * calculating its length and finding the last mbuf.
821: * If the adjustment only affects this mbuf, then just
822: * adjust and return. Otherwise, rescan and truncate
823: * after the remaining size.
824: */
825: count = 0;
826: m = mp;
827: for (;;) {
828: count += m->m_len;
829: if (m->m_next == (struct mbuf *)0)
830: break;
831: m = m->m_next;
832: }
833: if (m->m_len > len) {
834: m->m_len -= len;
835: if (nul > 0) {
836: cp = mtod(m, caddr_t)+m->m_len-nul;
837: for (i = 0; i < nul; i++)
838: *cp++ = '\0';
839: }
840: return;
841: }
842: count -= len;
843: if (count < 0)
844: count = 0;
845: /*
846: * Correct length for chain is "count".
847: * Find the mbuf with last data, adjust its length,
848: * and toss data from remaining mbufs on chain.
849: */
850: for (m = mp; m; m = m->m_next) {
851: if (m->m_len >= count) {
852: m->m_len = count;
853: if (nul > 0) {
854: cp = mtod(m, caddr_t)+m->m_len-nul;
855: for (i = 0; i < nul; i++)
856: *cp++ = '\0';
857: }
858: break;
859: }
860: count -= m->m_len;
861: }
862: while (m = m->m_next)
863: m->m_len = 0;
864: }
865:
866: /*
867: * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
868: * - look up fsid in mount list (if not found ret error)
869: * - check that it is exported
870: * - get vp by calling VFS_FHTOVP() macro
871: * - if not lockflag unlock it with VOP_UNLOCK()
872: * - if cred->cr_uid == 0 set it to m_exroot
873: */
874: nfsrv_fhtovp(fhp, lockflag, vpp, cred)
875: fhandle_t *fhp;
876: int lockflag;
877: struct vnode **vpp;
878: struct ucred *cred;
879: {
880: register struct mount *mp;
881:
882: if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
883: return (ESTALE);
884: if ((mp->mnt_flag & MNT_EXPORTED) == 0)
885: return (EACCES);
886: if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
887: return (ESTALE);
888: if (cred->cr_uid == 0)
889: cred->cr_uid = mp->mnt_exroot;
890: if (!lockflag)
891: VOP_UNLOCK(*vpp);
892: return (0);
893: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.