root/compat/common/compat_util.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. emul_find
  2. emul_flags_translate
  3. stackgap_init
  4. stackgap_alloc

    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 }

/* [<][>][^][v][top][bottom][index][help] */