linux_util.c revision 130959
114331Speter/* 214331Speter * Copyright (c) 1994 Christos Zoulas 314331Speter * Copyright (c) 1995 Frank van der Linden 414331Speter * Copyright (c) 1995 Scott Bartram 514331Speter * All rights reserved. 614331Speter * 714331Speter * Redistribution and use in source and binary forms, with or without 814331Speter * modification, are permitted provided that the following conditions 914331Speter * are met: 1014331Speter * 1. Redistributions of source code must retain the above copyright 1114331Speter * notice, this list of conditions and the following disclaimer. 1214331Speter * 2. Redistributions in binary form must reproduce the above copyright 1314331Speter * notice, this list of conditions and the following disclaimer in the 1414331Speter * documentation and/or other materials provided with the distribution. 1514331Speter * 3. The name of the author may not be used to endorse or promote products 1614331Speter * derived from this software without specific prior written permission 1714331Speter * 1814331Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1914331Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2014331Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2114331Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2214331Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2314331Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2414331Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2514331Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2614331Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2714331Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2814331Speter * 2914331Speter * from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp 3014331Speter */ 3114331Speter 32116173Sobrien#include <sys/cdefs.h> 33116173Sobrien__FBSDID("$FreeBSD: head/sys/compat/linux/linux_util.c 130959 2004-06-23 06:35:43Z bde $"); 34116173Sobrien 3514331Speter#include <sys/param.h> 36130959Sbde#include <sys/lock.h> 37130959Sbde#include <sys/malloc.h> 38130959Sbde#include <sys/mutex.h> 3914331Speter#include <sys/namei.h> 4014331Speter#include <sys/proc.h> 41130959Sbde#include <sys/systm.h> 4214331Speter#include <sys/vnode.h> 4314331Speter 44108541Salfred#include <machine/stdarg.h> 45108541Salfred 4664913Smarcel#include <compat/linux/linux_util.h> 4714331Speter 4814331Speterconst char linux_emul_path[] = "/compat/linux"; 4914331Speter 5014331Speter/* 5114331Speter * Search an alternate path before passing pathname arguments on 5272091Sasmodai * to system calls. Useful for keeping a separate 'emulation tree'. 5314331Speter * 5414331Speter * If cflag is set, we check if an attempt can be made to create 5514331Speter * the named file, i.e. we check if the directory it should 5614331Speter * be in exists. 5714331Speter */ 5814331Speterint 5985599Sdeslinux_emul_find(td, sgp, path, pbuf, cflag) 6083366Sjulian struct thread *td; 6114331Speter caddr_t *sgp; /* Pointer to stackgap memory */ 6214331Speter char *path; 6314331Speter char **pbuf; 6414331Speter int cflag; 6514331Speter{ 66102803Siedowse char *newpath; 67102803Siedowse size_t sz; 68102803Siedowse int error; 69102803Siedowse 70102803Siedowse error = linux_emul_convpath(td, path, (sgp == NULL) ? UIO_SYSSPACE : 71102803Siedowse UIO_USERSPACE, &newpath, cflag); 72102803Siedowse if (newpath == NULL) 73102803Siedowse return (error); 74102803Siedowse 75102803Siedowse if (sgp == NULL) { 76102803Siedowse *pbuf = newpath; 77102803Siedowse return (error); 78102803Siedowse } 79102803Siedowse 80102803Siedowse sz = strlen(newpath); 81102803Siedowse *pbuf = stackgap_alloc(sgp, sz + 1); 82102803Siedowse if (*pbuf != NULL) 83102803Siedowse error = copyout(newpath, *pbuf, sz + 1); 84102803Siedowse else 85102803Siedowse error = ENAMETOOLONG; 86102803Siedowse free(newpath, M_TEMP); 87102803Siedowse 88102803Siedowse return (error); 89102803Siedowse} 90102803Siedowse 91102803Siedowseint 92102803Siedowselinux_emul_convpath(td, path, pathseg, pbuf, cflag) 93102803Siedowse struct thread *td; 94102803Siedowse char *path; 95102803Siedowse enum uio_seg pathseg; 96102803Siedowse char **pbuf; 97102803Siedowse int cflag; 98102803Siedowse{ 9914331Speter struct nameidata nd; 10014331Speter struct nameidata ndroot; 10114331Speter int error; 10285599Sdes const char *prefix; 10314331Speter char *ptr, *buf, *cp; 104102803Siedowse size_t len, sz; 10514331Speter 106130902Srwatson GIANT_REQUIRED; 107130902Srwatson 108111119Simp buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 109102803Siedowse *pbuf = buf; 11014331Speter 11185599Sdes prefix = linux_emul_path; 11214331Speter for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) 11314331Speter continue; 11414331Speter sz = MAXPATHLEN - (ptr - buf); 11514331Speter 116102803Siedowse if (pathseg == UIO_SYSSPACE) 11714331Speter error = copystr(path, ptr, sz, &len); 11814331Speter else 11914331Speter error = copyinstr(path, ptr, sz, &len); 12014331Speter 12114331Speter if (error) { 122102803Siedowse *pbuf = NULL; 12314331Speter free(buf, M_TEMP); 12414331Speter return error; 12514331Speter } 12614331Speter 12714331Speter if (*ptr != '/') { 128102803Siedowse error = EINVAL; 129102803Siedowse goto keeporig; 13014331Speter } 13114331Speter 13214331Speter /* 13314331Speter * We know that there is a / somewhere in this pathname. 13414331Speter * Search backwards for it, to find the file's parent dir 13514331Speter * to see if it exists in the alternate tree. If it does, 13614331Speter * and we want to create a file (cflag is set). We don't 13714331Speter * need to worry about the root comparison in this case. 13814331Speter */ 13914331Speter 14014331Speter if (cflag) { 14114331Speter for (cp = &ptr[len] - 1; *cp != '/'; cp--); 14214331Speter *cp = '\0'; 14314331Speter 14483366Sjulian NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 145102803Siedowse error = namei(&nd); 14614331Speter *cp = '/'; 147102803Siedowse if (error != 0) 148102803Siedowse goto keeporig; 14914331Speter } 15014331Speter else { 15183366Sjulian NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 15214331Speter 153102803Siedowse if ((error = namei(&nd)) != 0) 154102803Siedowse goto keeporig; 15514331Speter 15614331Speter /* 15714331Speter * We now compare the vnode of the linux_root to the one 15814331Speter * vnode asked. If they resolve to be the same, then we 15914331Speter * ignore the match so that the real root gets used. 16014331Speter * This avoids the problem of traversing "../.." to find the 16114331Speter * root directory and never finding it, because "/" resolves 16214331Speter * to the emulation root directory. This is expensive :-( 16314331Speter */ 16418027Sbde NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, 16583366Sjulian td); 16614331Speter 16714331Speter if ((error = namei(&ndroot)) != 0) { 16814331Speter /* Cannot happen! */ 16954655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 17014331Speter vrele(nd.ni_vp); 171102803Siedowse goto keeporig; 17214331Speter } 17314331Speter 174124537Struckman if (nd.ni_vp == ndroot.ni_vp) { 17514331Speter error = ENOENT; 17617450Snate goto bad; 17714331Speter } 17814331Speter 17914331Speter } 18014331Speter 18154655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 18214331Speter vrele(nd.ni_vp); 18354655Seivind if (!cflag) { 18454655Seivind NDFREE(&ndroot, NDF_ONLY_PNBUF); 18514331Speter vrele(ndroot.ni_vp); 18654655Seivind } 18714331Speter return error; 18817450Snate 18917450Snatebad: 19054655Seivind NDFREE(&ndroot, NDF_ONLY_PNBUF); 19117450Snate vrele(ndroot.ni_vp); 19254655Seivind NDFREE(&nd, NDF_ONLY_PNBUF); 19317450Snate vrele(nd.ni_vp); 194102803Siedowsekeeporig: 195102803Siedowse /* Keep the original path; copy it back to the start of the buffer. */ 196102803Siedowse bcopy(ptr, buf, len); 19717450Snate return error; 19814331Speter} 199108541Salfred 200108541Salfredvoid 201108541Salfredlinux_msg(const struct thread *td, const char *fmt, ...) 202108541Salfred{ 203108541Salfred va_list ap; 204108541Salfred struct proc *p; 205108541Salfred 206108541Salfred p = td->td_proc; 207108541Salfred printf("linux: pid %d (%s): ", (int)p->p_pid, p->p_comm); 208108541Salfred va_start(ap, fmt); 209108541Salfred vprintf(fmt, ap); 210108541Salfred va_end(ap); 211108541Salfred printf("\n"); 212108541Salfred} 213