Annotation of sys/compat/common/compat_util.c, Revision 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