|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* $NetBSD: umap_vnops.c,v 1.3 1994/08/19 11:25:42 mycroft Exp $ */
23:
24: /*
25: * Copyright (c) 1992, 1993
26: * The Regents of the University of California. All rights reserved.
27: *
28: * This code is derived from software donated to Berkeley by
29: * the UCLA Ficus project.
30: *
31: * Redistribution and use in source and binary forms, with or without
32: * modification, are permitted provided that the following conditions
33: * are met:
34: * 1. Redistributions of source code must retain the above copyright
35: * notice, this list of conditions and the following disclaimer.
36: * 2. Redistributions in binary form must reproduce the above copyright
37: * notice, this list of conditions and the following disclaimer in the
38: * documentation and/or other materials provided with the distribution.
39: * 3. All advertising materials mentioning features or use of this software
40: * must display the following acknowledgement:
41: * This product includes software developed by the University of
42: * California, Berkeley and its contributors.
43: * 4. Neither the name of the University nor the names of its contributors
44: * may be used to endorse or promote products derived from this software
45: * without specific prior written permission.
46: *
47: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57: * SUCH DAMAGE.
58: *
59: * @(#)umap_vnops.c 8.3 (Berkeley) 1/5/94
60: */
61:
62: /*
63: * Umap Layer
64: */
65:
66: #include <sys/param.h>
67: #include <sys/systm.h>
68: #include <sys/time.h>
69: #include <sys/types.h>
70: #include <sys/vnode.h>
71: #include <sys/mount.h>
72: #include <sys/namei.h>
73: #include <sys/malloc.h>
74: #include <sys/buf.h>
75: #include <miscfs/umapfs/umap.h>
76:
77:
78: int umap_bug_bypass = 0; /* for debugging: enables bypass printf'ing */
79:
80: /*
81: * This is the 10-Apr-92 bypass routine.
82: * See null_vnops.c:null_bypass for more details.
83: */
84: int
85: umap_bypass(ap)
86: struct vop_generic_args /* {
87: struct vnodeop_desc *a_desc;
88: <other random data follows, presumably>
89: } */ *ap;
90: {
91: extern int (**umap_vnodeop_p)(); /* not extern, really "forward" */
92: struct ucred **credpp = 0, *credp = 0;
93: struct ucred *savecredp, *savecompcredp = 0;
94: struct ucred *compcredp = 0;
95: struct vnode **this_vp_p;
96: int error;
97: struct vnode *old_vps[VDESC_MAX_VPS];
98: struct vnode *vp1 = 0;
99: struct vnode **vps_p[VDESC_MAX_VPS];
100: struct vnode ***vppp;
101: struct vnodeop_desc *descp = ap->a_desc;
102: int reles, i;
103: struct componentname **compnamepp = 0;
104:
105: if (umap_bug_bypass)
106: printf ("umap_bypass: %s\n", descp->vdesc_name);
107:
108: #ifdef SAFETY
109: /*
110: * We require at least one vp.
111: */
112: if (descp->vdesc_vp_offsets == NULL ||
113: descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET)
114: panic ("umap_bypass: no vp's in map.\n");
115: #endif
116:
117: /*
118: * Map the vnodes going in.
119: * Later, we'll invoke the operation based on
120: * the first mapped vnode's operation vector.
121: */
122: reles = descp->vdesc_flags;
123: for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
124: if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
125: break; /* bail out at end of list */
126: vps_p[i] = this_vp_p =
127: VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[i], ap);
128:
129: if (i == 0) {
130: vp1 = *vps_p[0];
131: }
132:
133: /*
134: * We're not guaranteed that any but the first vnode
135: * are of our type. Check for and don't map any
136: * that aren't. (Must map first vp or vclean fails.)
137: */
138:
139: if (i && (*this_vp_p)->v_op != umap_vnodeop_p) {
140: old_vps[i] = NULL;
141: } else {
142: old_vps[i] = *this_vp_p;
143: *(vps_p[i]) = UMAPVPTOLOWERVP(*this_vp_p);
144: if (reles & 1)
145: VREF(*this_vp_p);
146: }
147:
148: }
149:
150: /*
151: * Fix the credentials. (That's the purpose of this layer.)
152: */
153:
154: if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {
155:
156: credpp = VOPARG_OFFSETTO(struct ucred**,
157: descp->vdesc_cred_offset, ap);
158:
159: /* Save old values */
160:
161: savecredp = *credpp;
162: if (savecredp != NOCRED)
163: *credpp = crdup(savecredp);
164: credp = *credpp;
165:
166: if (umap_bug_bypass && credp->cr_uid != 0)
167: printf("umap_bypass: user was %d, group %d\n",
168: credp->cr_uid, credp->cr_gid);
169:
170: /* Map all ids in the credential structure. */
171:
172: umap_mapids(vp1->v_mount, credp);
173:
174: if (umap_bug_bypass && credp->cr_uid != 0)
175: printf("umap_bypass: user now %d, group %d\n",
176: credp->cr_uid, credp->cr_gid);
177: }
178:
179: /* BSD often keeps a credential in the componentname structure
180: * for speed. If there is one, it better get mapped, too.
181: */
182:
183: if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) {
184:
185: compnamepp = VOPARG_OFFSETTO(struct componentname**,
186: descp->vdesc_componentname_offset, ap);
187:
188: savecompcredp = (*compnamepp)->cn_cred;
189: if (savecompcredp != NOCRED)
190: (*compnamepp)->cn_cred = crdup(savecompcredp);
191: compcredp = (*compnamepp)->cn_cred;
192:
193: if (umap_bug_bypass && compcredp->cr_uid != 0)
194: printf("umap_bypass: component credit user was %d, group %d\n",
195: compcredp->cr_uid, compcredp->cr_gid);
196:
197: /* Map all ids in the credential structure. */
198:
199: umap_mapids(vp1->v_mount, compcredp);
200:
201: if (umap_bug_bypass && compcredp->cr_uid != 0)
202: printf("umap_bypass: component credit user now %d, group %d\n",
203: compcredp->cr_uid, compcredp->cr_gid);
204: }
205:
206: /*
207: * Call the operation on the lower layer
208: * with the modified argument structure.
209: */
210: error = VCALL(*(vps_p[0]), descp->vdesc_offset, ap);
211:
212: /*
213: * Maintain the illusion of call-by-value
214: * by restoring vnodes in the argument structure
215: * to their original value.
216: */
217: reles = descp->vdesc_flags;
218: for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
219: if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
220: break; /* bail out at end of list */
221: if (old_vps[i]) {
222: *(vps_p[i]) = old_vps[i];
223: if (reles & 1)
224: vrele(*(vps_p[i]));
225: };
226: };
227:
228: /*
229: * Map the possible out-going vpp
230: * (Assumes that the lower layer always returns
231: * a VREF'ed vpp unless it gets an error.)
232: */
233: if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET &&
234: !(descp->vdesc_flags & VDESC_NOMAP_VPP) &&
235: !error) {
236: if (descp->vdesc_flags & VDESC_VPP_WILLRELE)
237: goto out;
238: vppp = VOPARG_OFFSETTO(struct vnode***,
239: descp->vdesc_vpp_offset, ap);
240: error = umap_node_create(old_vps[0]->v_mount, **vppp, *vppp);
241: };
242:
243: out:
244: /*
245: * Free duplicate cred structure and restore old one.
246: */
247: if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {
248: if (umap_bug_bypass && credp && credp->cr_uid != 0)
249: printf("umap_bypass: returning-user was %d\n",
250: credp->cr_uid);
251:
252: if (savecredp != NOCRED) {
253: if (credp != NOCRED)
254: crfree(credp);
255: *credpp = savecredp;
256: if (umap_bug_bypass && credpp && (*credpp)->cr_uid != 0)
257: printf("umap_bypass: returning-user now %d\n\n",
258: savecredp->cr_uid);
259: }
260: }
261:
262: if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) {
263: if (umap_bug_bypass && compcredp && compcredp->cr_uid != 0)
264: printf("umap_bypass: returning-component-user was %d\n",
265: compcredp->cr_uid);
266:
267: if (savecompcredp != NOCRED) {
268: if (compcredp != NOCRED)
269: crfree(compcredp);
270: (*compnamepp)->cn_cred = savecompcredp;
271: if (umap_bug_bypass && credpp && (*credpp)->cr_uid != 0)
272: printf("umap_bypass: returning-component-user now %d\n",
273: savecompcredp->cr_uid);
274: }
275: }
276:
277: return (error);
278: }
279:
280:
281: /*
282: * We handle getattr to change the fsid.
283: */
284: int
285: umap_getattr(ap)
286: struct vop_getattr_args /* {
287: struct vnode *a_vp;
288: struct vattr *a_vap;
289: struct ucred *a_cred;
290: struct proc *a_p;
291: } */ *ap;
292: {
293: uid_t uid;
294: gid_t gid;
295: int error, tmpid, nentries, gnentries;
296: uid_t (*mapdata)[2];
297: gid_t (*gmapdata)[2];
298: struct vnode **vp1p;
299: struct vnodeop_desc *descp = ap->a_desc;
300:
301: if (error = umap_bypass(ap))
302: return (error);
303: /* Requires that arguments be restored. */
304: ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
305:
306: /*
307: * Umap needs to map the uid and gid returned by a stat
308: * into the proper values for this site. This involves
309: * finding the returned uid in the mapping information,
310: * translating it into the uid on the other end,
311: * and filling in the proper field in the vattr
312: * structure pointed to by ap->a_vap. The group
313: * is easier, since currently all groups will be
314: * translate to the NULLGROUP.
315: */
316:
317: /* Find entry in map */
318:
319: uid = ap->a_vap->va_uid;
320: gid = ap->a_vap->va_gid;
321: if (umap_bug_bypass)
322: printf("umap_getattr: mapped uid = %d, mapped gid = %d\n", uid,
323: gid);
324:
325: vp1p = VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[0], ap);
326: nentries = MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_nentries;
327: mapdata = (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_mapdata);
328: gnentries = MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gnentries;
329: gmapdata = (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gmapdata);
330:
331: /* Reverse map the uid for the vnode. Since it's a reverse
332: map, we can't use umap_mapids() to do it. */
333:
334: tmpid = umap_reverse_findid(uid, mapdata, nentries);
335:
336: if (tmpid != -1) {
337: ap->a_vap->va_uid = (uid_t) tmpid;
338: if (umap_bug_bypass)
339: printf("umap_getattr: original uid = %d\n", uid);
340: } else
341: ap->a_vap->va_uid = (uid_t) NOBODY;
342:
343: /* Reverse map the gid for the vnode. */
344:
345: tmpid = umap_reverse_findid(gid, gmapdata, gnentries);
346:
347: if (tmpid != -1) {
348: ap->a_vap->va_gid = (gid_t) tmpid;
349: if (umap_bug_bypass)
350: printf("umap_getattr: original gid = %d\n", gid);
351: } else
352: ap->a_vap->va_gid = (gid_t) NULLGROUP;
353:
354: return (0);
355: }
356:
357: int
358: umap_inactive(ap)
359: struct vop_inactive_args /* {
360: struct vnode *a_vp;
361: } */ *ap;
362: {
363: /*
364: * Do nothing (and _don't_ bypass).
365: * Wait to vrele lowervp until reclaim,
366: * so that until then our umap_node is in the
367: * cache and reusable.
368: *
369: */
370: return (0);
371: }
372:
373: int
374: umap_reclaim(ap)
375: struct vop_reclaim_args /* {
376: struct vnode *a_vp;
377: } */ *ap;
378: {
379: struct vnode *vp = ap->a_vp;
380: struct umap_node *xp = VTOUMAP(vp);
381: struct vnode *lowervp = xp->umap_lowervp;
382:
383: /* After this assignment, this node will not be re-used. */
384: xp->umap_lowervp = NULL;
385: LIST_REMOVE(xp, umap_hash);
386: FREE(vp->v_data, M_TEMP);
387: vp->v_data = NULL;
388: vrele(lowervp);
389: return (0);
390: }
391:
392: int
393: umap_strategy(ap)
394: struct vop_strategy_args /* {
395: struct buf *a_bp;
396: } */ *ap;
397: {
398: struct buf *bp = ap->a_bp;
399: int error;
400: struct vnode *savedvp;
401:
402: savedvp = bp->b_vp;
403: bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp);
404:
405: error = VOP_STRATEGY(ap->a_bp);
406:
407: bp->b_vp = savedvp;
408:
409: return (error);
410: }
411:
412: int
413: umap_bwrite(ap)
414: struct vop_bwrite_args /* {
415: struct buf *a_bp;
416: } */ *ap;
417: {
418: struct buf *bp = ap->a_bp;
419: int error;
420: struct vnode *savedvp;
421:
422: savedvp = bp->b_vp;
423: bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp);
424:
425: error = VOP_BWRITE(ap->a_bp);
426:
427: bp->b_vp = savedvp;
428:
429: return (error);
430: }
431:
432:
433: int
434: umap_print(ap)
435: struct vop_print_args /* {
436: struct vnode *a_vp;
437: } */ *ap;
438: {
439: struct vnode *vp = ap->a_vp;
440: printf("\ttag VT_UMAPFS, vp=%x, lowervp=%x\n", vp, UMAPVPTOLOWERVP(vp));
441: return (0);
442: }
443:
444: int
445: umap_rename(ap)
446: struct vop_rename_args /* {
447: struct vnode *a_fdvp;
448: struct vnode *a_fvp;
449: struct componentname *a_fcnp;
450: struct vnode *a_tdvp;
451: struct vnode *a_tvp;
452: struct componentname *a_tcnp;
453: } */ *ap;
454: {
455: int error;
456: struct componentname *compnamep;
457: struct ucred *compcredp, *savecompcredp;
458: struct vnode *vp;
459:
460: /*
461: * Rename is irregular, having two componentname structures.
462: * We need to map the cre in the second structure,
463: * and then bypass takes care of the rest.
464: */
465:
466: vp = ap->a_fdvp;
467: compnamep = ap->a_tcnp;
468: compcredp = compnamep->cn_cred;
469:
470: savecompcredp = compcredp;
471: compcredp = compnamep->cn_cred = crdup(savecompcredp);
472:
473: if (umap_bug_bypass && compcredp->cr_uid != 0)
474: printf("umap_rename: rename component credit user was %d, group %d\n",
475: compcredp->cr_uid, compcredp->cr_gid);
476:
477: /* Map all ids in the credential structure. */
478:
479: umap_mapids(vp->v_mount, compcredp);
480:
481: if (umap_bug_bypass && compcredp->cr_uid != 0)
482: printf("umap_rename: rename component credit user now %d, group %d\n",
483: compcredp->cr_uid, compcredp->cr_gid);
484:
485: error = umap_bypass(ap);
486:
487: /* Restore the additional mapped componentname cred structure. */
488:
489: crfree(compcredp);
490: compnamep->cn_cred = savecompcredp;
491:
492: return error;
493: }
494:
495: /*
496: * Global vfs data structures
497: */
498: /*
499: * XXX - strategy, bwrite are hand coded currently. They should
500: * go away with a merged buffer/block cache.
501: *
502: */
503: int (**umap_vnodeop_p)();
504: struct vnodeopv_entry_desc umap_vnodeop_entries[] = {
505: { &vop_default_desc, umap_bypass },
506:
507: { &vop_getattr_desc, umap_getattr },
508: { &vop_inactive_desc, umap_inactive },
509: { &vop_reclaim_desc, umap_reclaim },
510: { &vop_print_desc, umap_print },
511: { &vop_rename_desc, umap_rename },
512:
513: { &vop_strategy_desc, umap_strategy },
514: { &vop_bwrite_desc, umap_bwrite },
515:
516: { (struct vnodeop_desc*) NULL, (int(*)()) NULL }
517: };
518: struct vnodeopv_desc umap_vnodeop_opv_desc =
519: { &umap_vnodeop_p, umap_vnodeop_entries };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.