Annotation of sys/compat/common/compat_util.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: compat_util.c,v 1.10 2004/08/01 06:22:28 mickey Exp $ */
2: /* $NetBSD: compat_util.c,v 1.4 1996/03/14 19:31:45 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1994 Christos Zoulas
6: * Copyright (c) 1995 Frank van der Linden
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. The name of the author may not be used to endorse or promote products
18: * derived from this software without specific prior written permission
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30: *
31: */
32:
33: #include <sys/param.h>
34: #include <sys/systm.h>
35: #include <sys/namei.h>
36: #include <sys/proc.h>
37: #include <sys/file.h>
38: #include <sys/stat.h>
39: #include <sys/filedesc.h>
40: #include <sys/ioctl.h>
41: #include <sys/kernel.h>
42: #include <sys/malloc.h>
43: #include <sys/vnode.h>
44:
45: #include <compat/common/compat_util.h>
46:
47: /*
48: * Search an alternate path before passing pathname arguments on
49: * to system calls. Useful for keeping a separate 'emulation tree'.
50: *
51: * If cflag is set, we check if an attempt can be made to create
52: * the named file, i.e. we check if the directory it should
53: * be in exists.
54: */
55: int
56: emul_find(p, sgp, prefix, path, pbuf, cflag)
57: struct proc *p;
58: caddr_t *sgp; /* Pointer to stackgap memory */
59: const char *prefix;
60: char *path;
61: char **pbuf;
62: int cflag;
63: {
64: struct nameidata nd;
65: struct nameidata ndroot;
66: struct vattr vat;
67: struct vattr vatroot;
68: int error;
69: char *ptr, *buf, *cp;
70: const char *pr;
71: size_t sz, len;
72:
73: buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
74: *pbuf = path;
75:
76: for (ptr = buf, pr = prefix; (*ptr = *pr) != '\0'; ptr++, pr++)
77: continue;
78:
79: sz = MAXPATHLEN - (ptr - buf);
80:
81: /*
82: * If sgp is not given then the path is already in kernel space
83: */
84: if (sgp == NULL)
85: error = copystr(path, ptr, sz, &len);
86: else
87: error = copyinstr(path, ptr, sz, &len);
88:
89: if (error)
90: goto bad;
91:
92: if (*ptr != '/') {
93: error = EINVAL;
94: goto bad;
95: }
96:
97: /*
98: * We know that there is a / somewhere in this pathname.
99: * Search backwards for it, to find the file's parent dir
100: * to see if it exists in the alternate tree. If it does,
101: * and we want to create a file (cflag is set). We don't
102: * need to worry about the root comparison in this case.
103: */
104:
105: if (cflag) {
106: for (cp = &ptr[len] - 1; *cp != '/'; cp--)
107: ;
108: *cp = '\0';
109:
110: NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p);
111:
112: if ((error = namei(&nd)) != 0)
113: goto bad;
114:
115: *cp = '/';
116: }
117: else {
118: NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p);
119:
120: if ((error = namei(&nd)) != 0)
121: goto bad;
122:
123: /*
124: * We now compare the vnode of the emulation root to the one
125: * vnode asked. If they resolve to be the same, then we
126: * ignore the match so that the real root gets used.
127: * This avoids the problem of traversing "../.." to find the
128: * root directory and never finding it, because "/" resolves
129: * to the emulation root directory. This is expensive :-(
130: */
131: /* XXX: prototype should have const here for NDINIT */
132: NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, prefix, p);
133:
134: if ((error = namei(&ndroot)) != 0)
135: goto bad2;
136:
137: if ((error = VOP_GETATTR(nd.ni_vp, &vat, p->p_ucred, p)) != 0)
138: goto bad3;
139:
140: if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, p->p_ucred, p))
141: != 0)
142: goto bad3;
143:
144: if (vat.va_fsid == vatroot.va_fsid &&
145: vat.va_fileid == vatroot.va_fileid) {
146: error = ENOENT;
147: goto bad3;
148: }
149: }
150: if (sgp == NULL)
151: *pbuf = buf;
152: else {
153: sz = &ptr[len] - buf;
154: *pbuf = stackgap_alloc(sgp, sz + 1);
155: if (*pbuf == NULL) {
156: error = ENAMETOOLONG;
157: goto bad;
158: }
159: if ((error = copyout(buf, *pbuf, sz)) != 0) {
160: *pbuf = path;
161: goto bad;
162: }
163: free(buf, M_TEMP);
164: }
165:
166: vrele(nd.ni_vp);
167: if (!cflag)
168: vrele(ndroot.ni_vp);
169: return error;
170:
171: bad3:
172: vrele(ndroot.ni_vp);
173: bad2:
174: vrele(nd.ni_vp);
175: bad:
176: free(buf, M_TEMP);
177: return error;
178: }
179:
180: /*
181: * Translate one set of flags to another, based on the entries in
182: * the given table. If 'leftover' is specified, it is filled in
183: * with any flags which could not be translated.
184: */
185: unsigned long
186: emul_flags_translate(tab, in, leftover)
187: const struct emul_flags_xtab *tab;
188: unsigned long in;
189: unsigned long *leftover;
190: {
191: unsigned long out;
192:
193: for (out = 0; tab->omask != 0; tab++) {
194: if ((in & tab->omask) == tab->oval) {
195: in &= ~tab->omask;
196: out |= tab->nval;
197: }
198: }
199: if (leftover != NULL)
200: *leftover = in;
201: return (out);
202: }
203:
204: caddr_t
205: stackgap_init(e)
206: struct emul *e;
207: {
208: return STACKGAPBASE;
209: }
210:
211: void *
212: stackgap_alloc(sgp, sz)
213: caddr_t *sgp;
214: size_t sz;
215: {
216: void *n = (void *) *sgp;
217: caddr_t nsgp;
218:
219: sz = ALIGN(sz);
220: nsgp = *sgp + sz;
221: #ifdef MACHINE_STACK_GROWS_UP
222: if (nsgp > ((caddr_t)PS_STRINGS) + STACKGAPLEN)
223: return NULL;
224: #else
225: if (nsgp > ((caddr_t)PS_STRINGS))
226: return NULL;
227: #endif
228: *sgp = nsgp;
229: return n;
230: }
CVSweb