ibcs2_util.c revision 11397
111394Sswallace/* 211394Sswallace * Copyright (c) 1994 Christos Zoulas 311394Sswallace * Copyright (c) 1995 Frank van der Linden 411394Sswallace * Copyright (c) 1995 Scott Bartram 511394Sswallace * All rights reserved. 611394Sswallace * 711394Sswallace * Redistribution and use in source and binary forms, with or without 811394Sswallace * modification, are permitted provided that the following conditions 911394Sswallace * are met: 1011394Sswallace * 1. Redistributions of source code must retain the above copyright 1111394Sswallace * notice, this list of conditions and the following disclaimer. 1211394Sswallace * 2. Redistributions in binary form must reproduce the above copyright 1311394Sswallace * notice, this list of conditions and the following disclaimer in the 1411394Sswallace * documentation and/or other materials provided with the distribution. 1511394Sswallace * 3. The name of the author may not be used to endorse or promote products 1611394Sswallace * derived from this software without specific prior written permission 1711394Sswallace * 1811394Sswallace * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1911394Sswallace * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2011394Sswallace * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2111394Sswallace * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2211394Sswallace * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2311394Sswallace * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2411394Sswallace * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2511394Sswallace * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2611394Sswallace * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2711394Sswallace * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2811394Sswallace * 2911394Sswallace * from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp 3011394Sswallace */ 3111394Sswallace 3211394Sswallace#include <sys/param.h> 3311394Sswallace#include <sys/systm.h> 3411394Sswallace#include <sys/namei.h> 3511394Sswallace#include <sys/proc.h> 3611394Sswallace#include <sys/file.h> 3711394Sswallace#include <sys/stat.h> 3811394Sswallace#include <sys/filedesc.h> 3911394Sswallace#include <sys/ioctl.h> 4011394Sswallace#include <sys/kernel.h> 4111394Sswallace#include <sys/malloc.h> 4211394Sswallace#include <sys/vnode.h> 4311394Sswallace 4411397Sswallace#include <i386/ibcs2/ibcs2_util.h> 4511394Sswallace 4611394Sswallaceconst char ibcs2_emul_path[] = "/emul/ibcs2"; 4711394Sswallace 4811394Sswallace/* 4911394Sswallace * Search an alternate path before passing pathname arguments on 5011394Sswallace * to system calls. Useful for keeping a seperate 'emulation tree'. 5111394Sswallace * 5211394Sswallace * If cflag is set, we check if an attempt can be made to create 5311394Sswallace * the named file, i.e. we check if the directory it should 5411394Sswallace * be in exists. 5511394Sswallace */ 5611394Sswallaceint 5711394Sswallaceibcs2_emul_find(p, sgp, prefix, path, pbuf, cflag) 5811394Sswallace struct proc *p; 5911394Sswallace caddr_t *sgp; /* Pointer to stackgap memory */ 6011394Sswallace const char *prefix; 6111394Sswallace char *path; 6211394Sswallace char **pbuf; 6311394Sswallace int cflag; 6411394Sswallace{ 6511394Sswallace struct nameidata nd; 6611394Sswallace struct nameidata ndroot; 6711394Sswallace struct vattr vat; 6811394Sswallace struct vattr vatroot; 6911394Sswallace int error; 7011394Sswallace char *ptr, *buf, *cp; 7111394Sswallace size_t sz, len; 7211394Sswallace 7311394Sswallace buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 7411394Sswallace *pbuf = path; 7511394Sswallace 7611394Sswallace for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) 7711394Sswallace continue; 7811394Sswallace 7911394Sswallace sz = MAXPATHLEN - (ptr - buf); 8011394Sswallace 8111394Sswallace /* 8211394Sswallace * If sgp is not given then the path is already in kernel space 8311394Sswallace */ 8411394Sswallace if (sgp == NULL) 8511394Sswallace error = copystr(path, ptr, sz, &len); 8611394Sswallace else 8711394Sswallace error = copyinstr(path, ptr, sz, &len); 8811394Sswallace 8911394Sswallace if (error) { 9011394Sswallace free(buf, M_TEMP); 9111394Sswallace return error; 9211394Sswallace } 9311394Sswallace 9411394Sswallace if (*ptr != '/') { 9511394Sswallace free(buf, M_TEMP); 9611394Sswallace return EINVAL; 9711394Sswallace } 9811394Sswallace 9911394Sswallace /* 10011394Sswallace * We know that there is a / somewhere in this pathname. 10111394Sswallace * Search backwards for it, to find the file's parent dir 10211394Sswallace * to see if it exists in the alternate tree. If it does, 10311394Sswallace * and we want to create a file (cflag is set). We don't 10411394Sswallace * need to worry about the root comparison in this case. 10511394Sswallace */ 10611394Sswallace 10711394Sswallace if (cflag) { 10811394Sswallace for (cp = &ptr[len] - 1; *cp != '/'; cp--); 10911394Sswallace *cp = '\0'; 11011394Sswallace 11111394Sswallace NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p); 11211394Sswallace 11311394Sswallace if ((error = namei(&nd)) != 0) { 11411394Sswallace free(buf, M_TEMP); 11511394Sswallace return error; 11611394Sswallace } 11711394Sswallace 11811394Sswallace *cp = '/'; 11911394Sswallace } 12011394Sswallace else { 12111394Sswallace NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p); 12211394Sswallace 12311394Sswallace if ((error = namei(&nd)) != 0) { 12411394Sswallace free(buf, M_TEMP); 12511394Sswallace return error; 12611394Sswallace } 12711394Sswallace 12811394Sswallace /* 12911394Sswallace * We now compare the vnode of the ibcs2_root to the one 13011394Sswallace * vnode asked. If they resolve to be the same, then we 13111394Sswallace * ignore the match so that the real root gets used. 13211394Sswallace * This avoids the problem of traversing "../.." to find the 13311394Sswallace * root directory and never finding it, because "/" resolves 13411394Sswallace * to the emulation root directory. This is expensive :-( 13511394Sswallace */ 13611394Sswallace /* XXX: prototype should have const here for NDINIT */ 13711394Sswallace NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, 13811394Sswallace (char *) ibcs2_emul_path, p); 13911394Sswallace 14011394Sswallace if ((error = namei(&ndroot)) != 0) { 14111394Sswallace /* Cannot happen! */ 14211394Sswallace free(buf, M_TEMP); 14311394Sswallace vrele(nd.ni_vp); 14411394Sswallace return error; 14511394Sswallace } 14611394Sswallace 14711394Sswallace if ((error = VOP_GETATTR(nd.ni_vp, &vat, p->p_ucred, p)) != 0) { 14811394Sswallace goto done; 14911394Sswallace } 15011394Sswallace 15111394Sswallace if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, p->p_ucred, p)) 15211394Sswallace != 0) { 15311394Sswallace goto done; 15411394Sswallace } 15511394Sswallace 15611394Sswallace if (vat.va_fsid == vatroot.va_fsid && 15711394Sswallace vat.va_fileid == vatroot.va_fileid) { 15811394Sswallace error = ENOENT; 15911394Sswallace goto done; 16011394Sswallace } 16111394Sswallace 16211394Sswallace } 16311394Sswallace if (sgp == NULL) 16411394Sswallace *pbuf = buf; 16511394Sswallace else { 16611394Sswallace sz = &ptr[len] - buf; 16711394Sswallace *pbuf = stackgap_alloc(sgp, sz + 1); 16811394Sswallace error = copyout(buf, *pbuf, sz); 16911394Sswallace free(buf, M_TEMP); 17011394Sswallace } 17111394Sswallace 17211394Sswallace 17311394Sswallacedone: 17411394Sswallace vrele(nd.ni_vp); 17511394Sswallace if (!cflag) 17611394Sswallace vrele(ndroot.ni_vp); 17711394Sswallace return error; 17811394Sswallace} 179