[BACK]Return to compat_util.c CVS log [TXT][DIR] Up to [local] / sys / compat / common

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