linux_file.c revision 156842
19313Ssos/*- 29313Ssos * Copyright (c) 1994-1995 S�ren Schmidt 39313Ssos * All rights reserved. 49313Ssos * 59313Ssos * Redistribution and use in source and binary forms, with or without 69313Ssos * modification, are permitted provided that the following conditions 79313Ssos * are met: 89313Ssos * 1. Redistributions of source code must retain the above copyright 9111798Sdes * notice, this list of conditions and the following disclaimer 109313Ssos * in this position and unchanged. 119313Ssos * 2. Redistributions in binary form must reproduce the above copyright 129313Ssos * notice, this list of conditions and the following disclaimer in the 139313Ssos * documentation and/or other materials provided with the distribution. 149313Ssos * 3. The name of the author may not be used to endorse or promote products 1597748Sschweikh * derived from this software without specific prior written permission 169313Ssos * 179313Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 189313Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 199313Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 209313Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 219313Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 229313Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239313Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249313Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259313Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 269313Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279313Ssos */ 289313Ssos 29116173Sobrien#include <sys/cdefs.h> 30116173Sobrien__FBSDID("$FreeBSD: head/sys/compat/linux/linux_file.c 156842 2006-03-18 18:20:17Z netchild $"); 31116173Sobrien 3231784Seivind#include "opt_compat.h" 33101189Srwatson#include "opt_mac.h" 3431784Seivind 359313Ssos#include <sys/param.h> 369313Ssos#include <sys/systm.h> 3776166Smarkm#include <sys/conf.h> 3876166Smarkm#include <sys/dirent.h> 399313Ssos#include <sys/fcntl.h> 409313Ssos#include <sys/file.h> 419313Ssos#include <sys/filedesc.h> 4231561Sbde#include <sys/lock.h> 43101189Srwatson#include <sys/mac.h> 449313Ssos#include <sys/malloc.h> 4572538Sjlemon#include <sys/mount.h> 4676166Smarkm#include <sys/mutex.h> 4776166Smarkm#include <sys/proc.h> 48102814Siedowse#include <sys/syscallsubr.h> 4976166Smarkm#include <sys/sysproto.h> 5014331Speter#include <sys/tty.h> 5176166Smarkm#include <sys/vnode.h> 5212458Sbde 5372538Sjlemon#include <ufs/ufs/extattr.h> 5472538Sjlemon#include <ufs/ufs/quota.h> 5572538Sjlemon#include <ufs/ufs/ufsmount.h> 5672538Sjlemon 57140214Sobrien#ifdef COMPAT_LINUX32 58140214Sobrien#include <machine/../linux32/linux.h> 59140214Sobrien#include <machine/../linux32/linux32_proto.h> 60140214Sobrien#else 6164905Smarcel#include <machine/../linux/linux.h> 6268583Smarcel#include <machine/../linux/linux_proto.h> 63133816Stjr#endif 6464905Smarcel#include <compat/linux/linux_util.h> 659313Ssos 6668201Sobrien#ifndef __alpha__ 679313Ssosint 6883366Sjulianlinux_creat(struct thread *td, struct linux_creat_args *args) 699313Ssos{ 70102814Siedowse char *path; 71102814Siedowse int error; 729313Ssos 73102814Siedowse LCONVPATHEXIST(td, args->path, &path); 7414331Speter 759313Ssos#ifdef DEBUG 7672543Sjlemon if (ldebug(creat)) 77102814Siedowse printf(ARGS(creat, "%s, %d"), path, args->mode); 789313Ssos#endif 79102814Siedowse error = kern_open(td, path, UIO_SYSSPACE, O_WRONLY | O_CREAT | O_TRUNC, 80102814Siedowse args->mode); 81102814Siedowse LFREEPATH(path); 82102814Siedowse return (error); 839313Ssos} 8468201Sobrien#endif /*!__alpha__*/ 859313Ssos 869313Ssosint 8783366Sjulianlinux_open(struct thread *td, struct linux_open_args *args) 889313Ssos{ 8983382Sjhb struct proc *p = td->td_proc; 90102814Siedowse char *path; 91102814Siedowse int bsd_flags, error; 9214331Speter 9314331Speter if (args->flags & LINUX_O_CREAT) 94102814Siedowse LCONVPATHCREAT(td, args->path, &path); 9514331Speter else 96102814Siedowse LCONVPATHEXIST(td, args->path, &path); 9714331Speter 989313Ssos#ifdef DEBUG 9972543Sjlemon if (ldebug(open)) 10072543Sjlemon printf(ARGS(open, "%s, 0x%x, 0x%x"), 101102814Siedowse path, args->flags, args->mode); 1029313Ssos#endif 103102814Siedowse bsd_flags = 0; 1049313Ssos if (args->flags & LINUX_O_RDONLY) 105102814Siedowse bsd_flags |= O_RDONLY; 106111798Sdes if (args->flags & LINUX_O_WRONLY) 107102814Siedowse bsd_flags |= O_WRONLY; 1089313Ssos if (args->flags & LINUX_O_RDWR) 109102814Siedowse bsd_flags |= O_RDWR; 1109313Ssos if (args->flags & LINUX_O_NDELAY) 111102814Siedowse bsd_flags |= O_NONBLOCK; 1129313Ssos if (args->flags & LINUX_O_APPEND) 113102814Siedowse bsd_flags |= O_APPEND; 1149313Ssos if (args->flags & LINUX_O_SYNC) 115102814Siedowse bsd_flags |= O_FSYNC; 1169313Ssos if (args->flags & LINUX_O_NONBLOCK) 117102814Siedowse bsd_flags |= O_NONBLOCK; 1189313Ssos if (args->flags & LINUX_FASYNC) 119102814Siedowse bsd_flags |= O_ASYNC; 1209313Ssos if (args->flags & LINUX_O_CREAT) 121102814Siedowse bsd_flags |= O_CREAT; 1229313Ssos if (args->flags & LINUX_O_TRUNC) 123102814Siedowse bsd_flags |= O_TRUNC; 1249313Ssos if (args->flags & LINUX_O_EXCL) 125102814Siedowse bsd_flags |= O_EXCL; 1269313Ssos if (args->flags & LINUX_O_NOCTTY) 127102814Siedowse bsd_flags |= O_NOCTTY; 1289313Ssos 129102814Siedowse error = kern_open(td, path, UIO_SYSSPACE, bsd_flags, args->mode); 13070061Sjhb PROC_LOCK(p); 131102814Siedowse if (!error && !(bsd_flags & O_NOCTTY) && 1329313Ssos SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 13389306Salfred struct file *fp; 1349313Ssos 135113917Sjhb PROC_UNLOCK(p); 13689319Salfred error = fget(td, td->td_retval[0], &fp); 13789319Salfred if (!error) { 13889319Salfred if (fp->f_type == DTYPE_VNODE) 139102003Srwatson fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred, 140102003Srwatson td); 14189319Salfred fdrop(fp, td); 14289319Salfred } 14391140Stanimura } else { 14470061Sjhb PROC_UNLOCK(p); 14514331Speter#ifdef DEBUG 14672543Sjlemon if (ldebug(open)) 14772543Sjlemon printf(LMSG("open returns error %d"), error); 14814331Speter#endif 14991140Stanimura } 150102814Siedowse LFREEPATH(path); 1519313Ssos return error; 1529313Ssos} 1539313Ssos 1549313Ssosint 15583366Sjulianlinux_lseek(struct thread *td, struct linux_lseek_args *args) 1569313Ssos{ 1579313Ssos 15812858Speter struct lseek_args /* { 15912858Speter int fd; 1609313Ssos int pad; 16112858Speter off_t offset; 1629313Ssos int whence; 16312858Speter } */ tmp_args; 1649313Ssos int error; 1659313Ssos 1669313Ssos#ifdef DEBUG 16772543Sjlemon if (ldebug(lseek)) 16872543Sjlemon printf(ARGS(lseek, "%d, %ld, %d"), 16983221Smarcel args->fdes, (long)args->off, args->whence); 1709313Ssos#endif 17112858Speter tmp_args.fd = args->fdes; 17212858Speter tmp_args.offset = (off_t)args->off; 1739313Ssos tmp_args.whence = args->whence; 17483366Sjulian error = lseek(td, &tmp_args); 1759313Ssos return error; 1769313Ssos} 1779313Ssos 17868201Sobrien#ifndef __alpha__ 17914331Speterint 18083366Sjulianlinux_llseek(struct thread *td, struct linux_llseek_args *args) 18114331Speter{ 18214331Speter struct lseek_args bsd_args; 18314331Speter int error; 18414331Speter off_t off; 18514331Speter 18614331Speter#ifdef DEBUG 18772543Sjlemon if (ldebug(llseek)) 18872543Sjlemon printf(ARGS(llseek, "%d, %d:%d, %d"), 18972543Sjlemon args->fd, args->ohigh, args->olow, args->whence); 19014331Speter#endif 19114331Speter off = (args->olow) | (((off_t) args->ohigh) << 32); 19214331Speter 19314331Speter bsd_args.fd = args->fd; 19414331Speter bsd_args.offset = off; 19514331Speter bsd_args.whence = args->whence; 19614331Speter 19783366Sjulian if ((error = lseek(td, &bsd_args))) 19814331Speter return error; 19914331Speter 200111797Sdes if ((error = copyout(td->td_retval, args->res, sizeof (off_t)))) 20114331Speter return error; 20214331Speter 20383366Sjulian td->td_retval[0] = 0; 20414331Speter return 0; 20514331Speter} 20668201Sobrien#endif /*!__alpha__*/ 20714331Speter 20868201Sobrien#ifndef __alpha__ 2099313Ssosint 21083366Sjulianlinux_readdir(struct thread *td, struct linux_readdir_args *args) 2119313Ssos{ 21214331Speter struct linux_getdents_args lda; 21314331Speter 21414331Speter lda.fd = args->fd; 21514331Speter lda.dent = args->dent; 21614331Speter lda.count = 1; 21783366Sjulian return linux_getdents(td, &lda); 21814331Speter} 21968201Sobrien#endif /*!__alpha__*/ 22014331Speter 22183221Smarcel/* 22283221Smarcel * Note that linux_getdents(2) and linux_getdents64(2) have the same 22383221Smarcel * arguments. They only differ in the definition of struct dirent they 22483221Smarcel * operate on. We use this to common the code, with the exception of 22583221Smarcel * accessing struct dirent. Note that linux_readdir(2) is implemented 22683221Smarcel * by means of linux_getdents(2). In this case we never operate on 22783221Smarcel * struct dirent64 and thus don't need to handle it... 22883221Smarcel */ 22983221Smarcel 23083221Smarcelstruct l_dirent { 23183221Smarcel l_long d_ino; 23283221Smarcel l_off_t d_off; 23383221Smarcel l_ushort d_reclen; 23483221Smarcel char d_name[LINUX_NAME_MAX + 1]; 23583221Smarcel}; 23683221Smarcel 23783221Smarcelstruct l_dirent64 { 23883221Smarcel uint64_t d_ino; 23983221Smarcel int64_t d_off; 24083221Smarcel l_ushort d_reclen; 24183221Smarcel u_char d_type; 24283221Smarcel char d_name[LINUX_NAME_MAX + 1]; 24383221Smarcel}; 24483221Smarcel 24583221Smarcel#define LINUX_RECLEN(de,namlen) \ 24683221Smarcel ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1)) 24783221Smarcel 24883221Smarcel#define LINUX_DIRBLKSIZ 512 24983221Smarcel 25083221Smarcelstatic int 25183366Sjuliangetdents_common(struct thread *td, struct linux_getdents64_args *args, 25283221Smarcel int is64bit) 25314331Speter{ 254111798Sdes struct dirent *bdp; 25583221Smarcel struct vnode *vp; 25683221Smarcel caddr_t inp, buf; /* BSD-format */ 25783221Smarcel int len, reclen; /* BSD-format */ 25883221Smarcel caddr_t outp; /* Linux-format */ 25983221Smarcel int resid, linuxreclen=0; /* Linux-format */ 26083221Smarcel struct file *fp; 26183221Smarcel struct uio auio; 26283221Smarcel struct iovec aiov; 26383221Smarcel off_t off; 26483221Smarcel struct l_dirent linux_dirent; 26583221Smarcel struct l_dirent64 linux_dirent64; 26683221Smarcel int buflen, error, eofflag, nbytes, justone; 26783221Smarcel u_long *cookies = NULL, *cookiep; 26883221Smarcel int ncookies; 2699313Ssos 27083366Sjulian if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0) 27183221Smarcel return (error); 2729313Ssos 27389306Salfred if ((fp->f_flag & FREAD) == 0) { 27489306Salfred fdrop(fp, td); 27583221Smarcel return (EBADF); 27689306Salfred } 2779313Ssos 278116678Sphk vp = fp->f_vnode; 27989306Salfred if (vp->v_type != VDIR) { 28089306Salfred fdrop(fp, td); 28183221Smarcel return (EINVAL); 28289306Salfred } 2839313Ssos 28483221Smarcel nbytes = args->count; 28583221Smarcel if (nbytes == 1) { 28683221Smarcel /* readdir(2) case. Always struct dirent. */ 28789306Salfred if (is64bit) { 28889306Salfred fdrop(fp, td); 28983221Smarcel return (EINVAL); 29089306Salfred } 29183221Smarcel nbytes = sizeof(linux_dirent); 29283221Smarcel justone = 1; 29383221Smarcel } else 29483221Smarcel justone = 0; 2959313Ssos 29683221Smarcel off = fp->f_offset; 2979313Ssos 29883221Smarcel buflen = max(LINUX_DIRBLKSIZ, nbytes); 29983221Smarcel buflen = min(buflen, MAXBSIZE); 300111119Simp buf = malloc(buflen, M_TEMP, M_WAITOK); 30183366Sjulian vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 30283221Smarcel 3039313Ssosagain: 30483221Smarcel aiov.iov_base = buf; 30583221Smarcel aiov.iov_len = buflen; 30683221Smarcel auio.uio_iov = &aiov; 30783221Smarcel auio.uio_iovcnt = 1; 30883221Smarcel auio.uio_rw = UIO_READ; 30983221Smarcel auio.uio_segflg = UIO_SYSSPACE; 31083366Sjulian auio.uio_td = td; 31183221Smarcel auio.uio_resid = buflen; 31283221Smarcel auio.uio_offset = off; 3139313Ssos 31483221Smarcel if (cookies) { 31583221Smarcel free(cookies, M_TEMP); 31683221Smarcel cookies = NULL; 31783221Smarcel } 31824654Sdfr 319101189Srwatson#ifdef MAC 320101189Srwatson /* 321101189Srwatson * Do directory search MAC check using non-cached credentials. 322101189Srwatson */ 323112451Sjhb if ((error = mac_check_vnode_readdir(td->td_ucred, vp))) 324101189Srwatson goto out; 325101189Srwatson#endif /* MAC */ 32683221Smarcel if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, 32783221Smarcel &cookies))) 32883221Smarcel goto out; 3299313Ssos 33083221Smarcel inp = buf; 33183221Smarcel outp = (caddr_t)args->dirent; 33283221Smarcel resid = nbytes; 33383221Smarcel if ((len = buflen - auio.uio_resid) <= 0) 33483221Smarcel goto eof; 3359313Ssos 33683221Smarcel cookiep = cookies; 33724654Sdfr 33883221Smarcel if (cookies) { 33983221Smarcel /* 34083221Smarcel * When using cookies, the vfs has the option of reading from 34183221Smarcel * a different offset than that supplied (UFS truncates the 34283221Smarcel * offset to a block boundary to make sure that it never reads 34383221Smarcel * partway through a directory entry, even if the directory 34483221Smarcel * has been compacted). 34583221Smarcel */ 34683221Smarcel while (len > 0 && ncookies > 0 && *cookiep <= off) { 34783221Smarcel bdp = (struct dirent *) inp; 34883221Smarcel len -= bdp->d_reclen; 34983221Smarcel inp += bdp->d_reclen; 35083221Smarcel cookiep++; 35183221Smarcel ncookies--; 35283221Smarcel } 35324654Sdfr } 35424654Sdfr 35583221Smarcel while (len > 0) { 35683221Smarcel if (cookiep && ncookies == 0) 35783221Smarcel break; 35883221Smarcel bdp = (struct dirent *) inp; 35983221Smarcel reclen = bdp->d_reclen; 36083221Smarcel if (reclen & 3) { 36183221Smarcel error = EFAULT; 36283221Smarcel goto out; 36383221Smarcel } 36483221Smarcel 36583221Smarcel if (bdp->d_fileno == 0) { 36683221Smarcel inp += reclen; 36783221Smarcel if (cookiep) { 36883221Smarcel off = *cookiep++; 36983221Smarcel ncookies--; 37083221Smarcel } else 37183221Smarcel off += reclen; 37283221Smarcel 37383221Smarcel len -= reclen; 37483221Smarcel continue; 37583221Smarcel } 37683221Smarcel 37783221Smarcel linuxreclen = (is64bit) 37883221Smarcel ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen) 37983221Smarcel : LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 38083221Smarcel 38183221Smarcel if (reclen > len || resid < linuxreclen) { 38283221Smarcel outp++; 38383221Smarcel break; 38483221Smarcel } 38583221Smarcel 38683221Smarcel if (justone) { 38783221Smarcel /* readdir(2) case. */ 38883221Smarcel linux_dirent.d_ino = (l_long)bdp->d_fileno; 38983221Smarcel linux_dirent.d_off = (l_off_t)linuxreclen; 39083221Smarcel linux_dirent.d_reclen = (l_ushort)bdp->d_namlen; 39183221Smarcel strcpy(linux_dirent.d_name, bdp->d_name); 39283221Smarcel error = copyout(&linux_dirent, outp, linuxreclen); 39383221Smarcel } else { 39483221Smarcel if (is64bit) { 39583221Smarcel linux_dirent64.d_ino = bdp->d_fileno; 39683221Smarcel linux_dirent64.d_off = (cookiep) 39783221Smarcel ? (l_off_t)*cookiep 39883221Smarcel : (l_off_t)(off + reclen); 39983221Smarcel linux_dirent64.d_reclen = 40083221Smarcel (l_ushort)linuxreclen; 40183221Smarcel linux_dirent64.d_type = bdp->d_type; 40283221Smarcel strcpy(linux_dirent64.d_name, bdp->d_name); 40383221Smarcel error = copyout(&linux_dirent64, outp, 40483221Smarcel linuxreclen); 40583221Smarcel } else { 40683221Smarcel linux_dirent.d_ino = bdp->d_fileno; 40783221Smarcel linux_dirent.d_off = (cookiep) 40883221Smarcel ? (l_off_t)*cookiep 40983221Smarcel : (l_off_t)(off + reclen); 41083221Smarcel linux_dirent.d_reclen = (l_ushort)linuxreclen; 41183221Smarcel strcpy(linux_dirent.d_name, bdp->d_name); 41283221Smarcel error = copyout(&linux_dirent, outp, 41383221Smarcel linuxreclen); 41483221Smarcel } 41583221Smarcel } 41683221Smarcel if (error) 41783221Smarcel goto out; 41883221Smarcel 41983221Smarcel inp += reclen; 42083221Smarcel if (cookiep) { 42183221Smarcel off = *cookiep++; 42283221Smarcel ncookies--; 42383221Smarcel } else 42483221Smarcel off += reclen; 42583221Smarcel 42683221Smarcel outp += linuxreclen; 42783221Smarcel resid -= linuxreclen; 42883221Smarcel len -= reclen; 42983221Smarcel if (justone) 43083221Smarcel break; 43110355Sswallace } 4329313Ssos 43383221Smarcel if (outp == (caddr_t)args->dirent) 43483221Smarcel goto again; 4359313Ssos 43683221Smarcel fp->f_offset = off; 43783221Smarcel if (justone) 43883221Smarcel nbytes = resid + linuxreclen; 43910355Sswallace 4409313Ssoseof: 44183366Sjulian td->td_retval[0] = nbytes - resid; 44283221Smarcel 4439313Ssosout: 44483221Smarcel if (cookies) 44583221Smarcel free(cookies, M_TEMP); 44683221Smarcel 44783366Sjulian VOP_UNLOCK(vp, 0, td); 44889306Salfred fdrop(fp, td); 44983221Smarcel free(buf, M_TEMP); 45083221Smarcel return (error); 4519313Ssos} 45214331Speter 45383221Smarcelint 45483366Sjulianlinux_getdents(struct thread *td, struct linux_getdents_args *args) 45583221Smarcel{ 45683221Smarcel 45783221Smarcel#ifdef DEBUG 45883221Smarcel if (ldebug(getdents)) 45983221Smarcel printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count); 46083221Smarcel#endif 46183221Smarcel 46283366Sjulian return (getdents_common(td, (struct linux_getdents64_args*)args, 0)); 46383221Smarcel} 46483221Smarcel 46583221Smarcelint 46683366Sjulianlinux_getdents64(struct thread *td, struct linux_getdents64_args *args) 46783221Smarcel{ 46883221Smarcel 46983221Smarcel#ifdef DEBUG 47083221Smarcel if (ldebug(getdents64)) 47183221Smarcel printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count); 47283221Smarcel#endif 47383221Smarcel 47483366Sjulian return (getdents_common(td, args, 1)); 47583221Smarcel} 47683221Smarcel 47714331Speter/* 47814331Speter * These exist mainly for hooks for doing /compat/linux translation. 47914331Speter */ 48014331Speter 48114331Speterint 48283366Sjulianlinux_access(struct thread *td, struct linux_access_args *args) 48314331Speter{ 484102814Siedowse char *path; 485102814Siedowse int error; 48614331Speter 487102814Siedowse LCONVPATHEXIST(td, args->path, &path); 48814331Speter 48914331Speter#ifdef DEBUG 49072543Sjlemon if (ldebug(access)) 491102814Siedowse printf(ARGS(access, "%s, %d"), path, args->flags); 49214331Speter#endif 493102814Siedowse error = kern_access(td, path, UIO_SYSSPACE, args->flags); 494102814Siedowse LFREEPATH(path); 495102814Siedowse return (error); 49614331Speter} 49714331Speter 49814331Speterint 49983366Sjulianlinux_unlink(struct thread *td, struct linux_unlink_args *args) 50014331Speter{ 501102814Siedowse char *path; 502102814Siedowse int error; 50314331Speter 504102814Siedowse LCONVPATHEXIST(td, args->path, &path); 50514331Speter 50614331Speter#ifdef DEBUG 50772543Sjlemon if (ldebug(unlink)) 508102814Siedowse printf(ARGS(unlink, "%s"), path); 50914331Speter#endif 51014331Speter 511102814Siedowse error = kern_unlink(td, path, UIO_SYSSPACE); 512102814Siedowse LFREEPATH(path); 513102814Siedowse return (error); 51414331Speter} 51514331Speter 51614331Speterint 51783366Sjulianlinux_chdir(struct thread *td, struct linux_chdir_args *args) 51814331Speter{ 519102814Siedowse char *path; 520102814Siedowse int error; 52114331Speter 522102814Siedowse LCONVPATHEXIST(td, args->path, &path); 52314331Speter 52414331Speter#ifdef DEBUG 52572543Sjlemon if (ldebug(chdir)) 526102814Siedowse printf(ARGS(chdir, "%s"), path); 52714331Speter#endif 528102814Siedowse error = kern_chdir(td, path, UIO_SYSSPACE); 529102814Siedowse LFREEPATH(path); 530102814Siedowse return (error); 53114331Speter} 53214331Speter 53314331Speterint 53483366Sjulianlinux_chmod(struct thread *td, struct linux_chmod_args *args) 53514331Speter{ 536102814Siedowse char *path; 537102814Siedowse int error; 53814331Speter 539102814Siedowse LCONVPATHEXIST(td, args->path, &path); 54014331Speter 54114331Speter#ifdef DEBUG 54272543Sjlemon if (ldebug(chmod)) 543102814Siedowse printf(ARGS(chmod, "%s, %d"), path, args->mode); 54414331Speter#endif 545102814Siedowse error = kern_chmod(td, path, UIO_SYSSPACE, args->mode); 546102814Siedowse LFREEPATH(path); 547102814Siedowse return (error); 54814331Speter} 54914331Speter 55014331Speterint 55183366Sjulianlinux_mkdir(struct thread *td, struct linux_mkdir_args *args) 55214331Speter{ 553102814Siedowse char *path; 554102814Siedowse int error; 55514331Speter 556102814Siedowse LCONVPATHCREAT(td, args->path, &path); 55714331Speter 55814331Speter#ifdef DEBUG 55972543Sjlemon if (ldebug(mkdir)) 560102814Siedowse printf(ARGS(mkdir, "%s, %d"), path, args->mode); 56114331Speter#endif 562102814Siedowse error = kern_mkdir(td, path, UIO_SYSSPACE, args->mode); 563102814Siedowse LFREEPATH(path); 564102814Siedowse return (error); 56514331Speter} 56614331Speter 56714331Speterint 56883366Sjulianlinux_rmdir(struct thread *td, struct linux_rmdir_args *args) 56914331Speter{ 570102814Siedowse char *path; 571102814Siedowse int error; 57214331Speter 573102814Siedowse LCONVPATHEXIST(td, args->path, &path); 57414331Speter 57514331Speter#ifdef DEBUG 57672543Sjlemon if (ldebug(rmdir)) 577102814Siedowse printf(ARGS(rmdir, "%s"), path); 57814331Speter#endif 579102814Siedowse error = kern_rmdir(td, path, UIO_SYSSPACE); 580102814Siedowse LFREEPATH(path); 581102814Siedowse return (error); 58214331Speter} 58314331Speter 58414331Speterint 58583366Sjulianlinux_rename(struct thread *td, struct linux_rename_args *args) 58614331Speter{ 587102814Siedowse char *from, *to; 588102814Siedowse int error; 58914331Speter 590102814Siedowse LCONVPATHEXIST(td, args->from, &from); 591102814Siedowse /* Expand LCONVPATHCREATE so that `from' can be freed on errors */ 592102814Siedowse error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); 593102814Siedowse if (to == NULL) { 594102814Siedowse LFREEPATH(from); 595102814Siedowse return (error); 596102814Siedowse } 59714331Speter 59814331Speter#ifdef DEBUG 59972543Sjlemon if (ldebug(rename)) 600102814Siedowse printf(ARGS(rename, "%s, %s"), from, to); 60114331Speter#endif 602102814Siedowse error = kern_rename(td, from, to, UIO_SYSSPACE); 603102814Siedowse LFREEPATH(from); 604102814Siedowse LFREEPATH(to); 605102814Siedowse return (error); 60614331Speter} 60714331Speter 60814331Speterint 60983366Sjulianlinux_symlink(struct thread *td, struct linux_symlink_args *args) 61014331Speter{ 611102814Siedowse char *path, *to; 612102814Siedowse int error; 61314331Speter 614102814Siedowse LCONVPATHEXIST(td, args->path, &path); 615102814Siedowse /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 616102814Siedowse error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); 617102814Siedowse if (to == NULL) { 618102814Siedowse LFREEPATH(path); 619102814Siedowse return (error); 620102814Siedowse } 62114331Speter 62214331Speter#ifdef DEBUG 62372543Sjlemon if (ldebug(symlink)) 624102814Siedowse printf(ARGS(symlink, "%s, %s"), path, to); 62514331Speter#endif 626102814Siedowse error = kern_symlink(td, path, to, UIO_SYSSPACE); 627102814Siedowse LFREEPATH(path); 628102814Siedowse LFREEPATH(to); 629102814Siedowse return (error); 63014331Speter} 63114331Speter 63214331Speterint 63383366Sjulianlinux_readlink(struct thread *td, struct linux_readlink_args *args) 63414331Speter{ 635102814Siedowse char *name; 636102814Siedowse int error; 63714331Speter 638102814Siedowse LCONVPATHEXIST(td, args->name, &name); 63914331Speter 64014331Speter#ifdef DEBUG 64172543Sjlemon if (ldebug(readlink)) 642102814Siedowse printf(ARGS(readlink, "%s, %p, %d"), name, (void *)args->buf, 643102814Siedowse args->count); 64414331Speter#endif 645102814Siedowse error = kern_readlink(td, name, UIO_SYSSPACE, args->buf, UIO_USERSPACE, 646102814Siedowse args->count); 647102814Siedowse LFREEPATH(name); 648102814Siedowse return (error); 64914331Speter} 65014331Speter 65114331Speterint 65283366Sjulianlinux_truncate(struct thread *td, struct linux_truncate_args *args) 65314331Speter{ 654102814Siedowse char *path; 655102814Siedowse int error; 65614331Speter 657102814Siedowse LCONVPATHEXIST(td, args->path, &path); 65814331Speter 65914331Speter#ifdef DEBUG 66072543Sjlemon if (ldebug(truncate)) 661102814Siedowse printf(ARGS(truncate, "%s, %ld"), path, (long)args->length); 66214331Speter#endif 66314331Speter 664102814Siedowse error = kern_truncate(td, path, UIO_SYSSPACE, args->length); 665102814Siedowse LFREEPATH(path); 666102814Siedowse return (error); 66714331Speter} 66814331Speter 66949662Smarcelint 670156842Snetchildlinux_ftruncate(struct thread *td, struct linux_ftruncate_args *args) 671156842Snetchild{ 672156842Snetchild struct ftruncate_args /* { 673156842Snetchild int fd; 674156842Snetchild int pad; 675156842Snetchild off_t length; 676156842Snetchild } */ nuap; 677156842Snetchild 678156842Snetchild nuap.fd = args->fd; 679156842Snetchild nuap.pad = 0; 680156842Snetchild nuap.length = args->length; 681156842Snetchild return (ftruncate(td, &nuap)); 682156842Snetchild} 683156842Snetchild 684156842Snetchildint 68583366Sjulianlinux_link(struct thread *td, struct linux_link_args *args) 68649662Smarcel{ 687102814Siedowse char *path, *to; 688102814Siedowse int error; 68949662Smarcel 690102814Siedowse LCONVPATHEXIST(td, args->path, &path); 691102814Siedowse /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 692102814Siedowse error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); 693102814Siedowse if (to == NULL) { 694102814Siedowse LFREEPATH(path); 695102814Siedowse return (error); 696102814Siedowse } 69749662Smarcel 69849662Smarcel#ifdef DEBUG 69972543Sjlemon if (ldebug(link)) 700102814Siedowse printf(ARGS(link, "%s, %s"), path, to); 70149662Smarcel#endif 702102814Siedowse error = kern_link(td, path, to, UIO_SYSSPACE); 703102814Siedowse LFREEPATH(path); 704102814Siedowse LFREEPATH(to); 705102814Siedowse return (error); 70649662Smarcel} 70749788Smarcel 70868201Sobrien#ifndef __alpha__ 70953713Smarcelint 71083366Sjulianlinux_fdatasync(td, uap) 71183366Sjulian struct thread *td; 71253713Smarcel struct linux_fdatasync_args *uap; 71353713Smarcel{ 71453713Smarcel struct fsync_args bsd; 71553713Smarcel 71653713Smarcel bsd.fd = uap->fd; 71783366Sjulian return fsync(td, &bsd); 71853713Smarcel} 71968201Sobrien#endif /*!__alpha__*/ 72063285Smarcel 72163285Smarcelint 72283366Sjulianlinux_pread(td, uap) 72383366Sjulian struct thread *td; 72463285Smarcel struct linux_pread_args *uap; 72563285Smarcel{ 72663285Smarcel struct pread_args bsd; 72763285Smarcel 72863285Smarcel bsd.fd = uap->fd; 72963285Smarcel bsd.buf = uap->buf; 73063285Smarcel bsd.nbyte = uap->nbyte; 73163285Smarcel bsd.offset = uap->offset; 73283366Sjulian return pread(td, &bsd); 73363285Smarcel} 73463285Smarcel 73563285Smarcelint 73683366Sjulianlinux_pwrite(td, uap) 73783366Sjulian struct thread *td; 73863285Smarcel struct linux_pwrite_args *uap; 73963285Smarcel{ 74063285Smarcel struct pwrite_args bsd; 74163285Smarcel 74263285Smarcel bsd.fd = uap->fd; 74363285Smarcel bsd.buf = uap->buf; 74463285Smarcel bsd.nbyte = uap->nbyte; 74563285Smarcel bsd.offset = uap->offset; 74683366Sjulian return pwrite(td, &bsd); 74763285Smarcel} 74872538Sjlemon 74972538Sjlemonint 75083366Sjulianlinux_mount(struct thread *td, struct linux_mount_args *args) 75172538Sjlemon{ 75272538Sjlemon struct ufs_args ufs; 753111798Sdes char fstypename[MFSNAMELEN]; 754111798Sdes char mntonname[MNAMELEN], mntfromname[MNAMELEN]; 75573286Sadrian int error; 75673286Sadrian int fsflags; 75773286Sadrian void *fsdata; 75872538Sjlemon 759111798Sdes error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1, 76073286Sadrian NULL); 76172538Sjlemon if (error) 762111798Sdes return (error); 763127057Stjr error = copyinstr(args->specialfile, mntfromname, MNAMELEN - 1, NULL); 76472538Sjlemon if (error) 765111798Sdes return (error); 766127057Stjr error = copyinstr(args->dir, mntonname, MNAMELEN - 1, NULL); 76772538Sjlemon if (error) 768111798Sdes return (error); 76972538Sjlemon 77072538Sjlemon#ifdef DEBUG 77172538Sjlemon if (ldebug(mount)) 77272538Sjlemon printf(ARGS(mount, "%s, %s, %s"), 77372538Sjlemon fstypename, mntfromname, mntonname); 77472538Sjlemon#endif 77572538Sjlemon 77672538Sjlemon if (strcmp(fstypename, "ext2") == 0) { 777127059Stjr strcpy(fstypename, "ext2fs"); 77873286Sadrian fsdata = &ufs; 77972538Sjlemon ufs.fspec = mntfromname; 78072538Sjlemon#define DEFAULT_ROOTID -2 78172538Sjlemon ufs.export.ex_root = DEFAULT_ROOTID; 78272538Sjlemon ufs.export.ex_flags = 78372538Sjlemon args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0; 78472538Sjlemon } else if (strcmp(fstypename, "proc") == 0) { 785127059Stjr strcpy(fstypename, "linprocfs"); 78673286Sadrian fsdata = NULL; 78772538Sjlemon } else { 78872538Sjlemon return (ENODEV); 78972538Sjlemon } 79072538Sjlemon 79173286Sadrian fsflags = 0; 79272538Sjlemon 79372538Sjlemon if ((args->rwflag & 0xffff0000) == 0xc0ed0000) { 79472538Sjlemon /* 79572538Sjlemon * Linux SYNC flag is not included; the closest equivalent 79672538Sjlemon * FreeBSD has is !ASYNC, which is our default. 79772538Sjlemon */ 79872538Sjlemon if (args->rwflag & LINUX_MS_RDONLY) 799111798Sdes fsflags |= MNT_RDONLY; 80072538Sjlemon if (args->rwflag & LINUX_MS_NOSUID) 801111798Sdes fsflags |= MNT_NOSUID; 80272538Sjlemon if (args->rwflag & LINUX_MS_NOEXEC) 803111798Sdes fsflags |= MNT_NOEXEC; 80472538Sjlemon if (args->rwflag & LINUX_MS_REMOUNT) 805111798Sdes fsflags |= MNT_UPDATE; 80672538Sjlemon } 80772538Sjlemon 808127059Stjr if (strcmp(fstypename, "linprocfs") == 0) { 809132708Sphk error = kernel_vmount(fsflags, 810132708Sphk "fstype", fstypename, 811132708Sphk "fspath", mntonname, 812132708Sphk NULL); 813127059Stjr } else 814138353Sphk error = EOPNOTSUPP; 815127059Stjr return (error); 81672538Sjlemon} 81772538Sjlemon 81872538Sjlemonint 81983366Sjulianlinux_oldumount(struct thread *td, struct linux_oldumount_args *args) 82072538Sjlemon{ 82183221Smarcel struct linux_umount_args args2; 82272538Sjlemon 82372538Sjlemon args2.path = args->path; 82472538Sjlemon args2.flags = 0; 82583366Sjulian return (linux_umount(td, &args2)); 82672538Sjlemon} 82772538Sjlemon 82872538Sjlemonint 82983366Sjulianlinux_umount(struct thread *td, struct linux_umount_args *args) 83072538Sjlemon{ 83172538Sjlemon struct unmount_args bsd; 83272538Sjlemon 83372538Sjlemon bsd.path = args->path; 83472538Sjlemon bsd.flags = args->flags; /* XXX correct? */ 83583366Sjulian return (unmount(td, &bsd)); 83672538Sjlemon} 83783221Smarcel 83883221Smarcel/* 83983221Smarcel * fcntl family of syscalls 84083221Smarcel */ 84183221Smarcel 84283221Smarcelstruct l_flock { 84383221Smarcel l_short l_type; 84483221Smarcel l_short l_whence; 84583221Smarcel l_off_t l_start; 84683221Smarcel l_off_t l_len; 84783221Smarcel l_pid_t l_pid; 848133816Stjr} 849140214Sobrien#if defined(__amd64__) && defined(COMPAT_LINUX32) 850133816Stjr__packed 851133816Stjr#endif 852133816Stjr; 85383221Smarcel 85483221Smarcelstatic void 85583221Smarcellinux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock) 85683221Smarcel{ 85783221Smarcel switch (linux_flock->l_type) { 85883221Smarcel case LINUX_F_RDLCK: 85983221Smarcel bsd_flock->l_type = F_RDLCK; 86083221Smarcel break; 86183221Smarcel case LINUX_F_WRLCK: 86283221Smarcel bsd_flock->l_type = F_WRLCK; 86383221Smarcel break; 86483221Smarcel case LINUX_F_UNLCK: 86583221Smarcel bsd_flock->l_type = F_UNLCK; 86683221Smarcel break; 86783221Smarcel default: 86883221Smarcel bsd_flock->l_type = -1; 86983221Smarcel break; 87083221Smarcel } 87183221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 87283221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 87383221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 87483221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 87583221Smarcel} 87683221Smarcel 87783221Smarcelstatic void 87883221Smarcelbsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock) 87983221Smarcel{ 88083221Smarcel switch (bsd_flock->l_type) { 88183221Smarcel case F_RDLCK: 88283221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 88383221Smarcel break; 88483221Smarcel case F_WRLCK: 88583221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 88683221Smarcel break; 88783221Smarcel case F_UNLCK: 88883221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 88983221Smarcel break; 89083221Smarcel } 89183221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 89283221Smarcel linux_flock->l_start = (l_off_t)bsd_flock->l_start; 89383221Smarcel linux_flock->l_len = (l_off_t)bsd_flock->l_len; 89483221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 89583221Smarcel} 89683221Smarcel 897140214Sobrien#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 89883221Smarcelstruct l_flock64 { 89983221Smarcel l_short l_type; 90083221Smarcel l_short l_whence; 90183221Smarcel l_loff_t l_start; 90283221Smarcel l_loff_t l_len; 90383221Smarcel l_pid_t l_pid; 904133816Stjr} 905140214Sobrien#if defined(__amd64__) && defined(COMPAT_LINUX32) 906133816Stjr__packed 907133816Stjr#endif 908133816Stjr; 90983221Smarcel 91083221Smarcelstatic void 91183221Smarcellinux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock) 91283221Smarcel{ 91383221Smarcel switch (linux_flock->l_type) { 91483221Smarcel case LINUX_F_RDLCK: 91583221Smarcel bsd_flock->l_type = F_RDLCK; 91683221Smarcel break; 91783221Smarcel case LINUX_F_WRLCK: 91883221Smarcel bsd_flock->l_type = F_WRLCK; 91983221Smarcel break; 92083221Smarcel case LINUX_F_UNLCK: 92183221Smarcel bsd_flock->l_type = F_UNLCK; 92283221Smarcel break; 92383221Smarcel default: 92483221Smarcel bsd_flock->l_type = -1; 92583221Smarcel break; 92683221Smarcel } 92783221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 92883221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 92983221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 93083221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 93183221Smarcel} 93283221Smarcel 93383221Smarcelstatic void 93483221Smarcelbsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) 93583221Smarcel{ 93683221Smarcel switch (bsd_flock->l_type) { 93783221Smarcel case F_RDLCK: 93883221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 93983221Smarcel break; 94083221Smarcel case F_WRLCK: 94183221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 94283221Smarcel break; 94383221Smarcel case F_UNLCK: 94483221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 94583221Smarcel break; 94683221Smarcel } 94783221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 94883221Smarcel linux_flock->l_start = (l_loff_t)bsd_flock->l_start; 94983221Smarcel linux_flock->l_len = (l_loff_t)bsd_flock->l_len; 95083221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 95183221Smarcel} 952133816Stjr#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 95383221Smarcel 95483221Smarcel#if defined(__alpha__) 95583221Smarcel#define linux_fcntl64_args linux_fcntl_args 95683221Smarcel#endif 95783221Smarcel 95883221Smarcelstatic int 95983366Sjulianfcntl_common(struct thread *td, struct linux_fcntl64_args *args) 96083221Smarcel{ 961107680Siedowse struct l_flock linux_flock; 962107680Siedowse struct flock bsd_flock; 96383221Smarcel struct file *fp; 964102872Siedowse long arg; 96583221Smarcel int error, result; 96683221Smarcel 96783221Smarcel switch (args->cmd) { 96883221Smarcel case LINUX_F_DUPFD: 969102872Siedowse return (kern_fcntl(td, args->fd, F_DUPFD, args->arg)); 97083221Smarcel 97183221Smarcel case LINUX_F_GETFD: 972102872Siedowse return (kern_fcntl(td, args->fd, F_GETFD, 0)); 97383221Smarcel 97483221Smarcel case LINUX_F_SETFD: 975102872Siedowse return (kern_fcntl(td, args->fd, F_SETFD, args->arg)); 97683221Smarcel 97783221Smarcel case LINUX_F_GETFL: 978102872Siedowse error = kern_fcntl(td, args->fd, F_GETFL, 0); 97983366Sjulian result = td->td_retval[0]; 98083366Sjulian td->td_retval[0] = 0; 98183221Smarcel if (result & O_RDONLY) 98283366Sjulian td->td_retval[0] |= LINUX_O_RDONLY; 98383221Smarcel if (result & O_WRONLY) 98483366Sjulian td->td_retval[0] |= LINUX_O_WRONLY; 98583221Smarcel if (result & O_RDWR) 98683366Sjulian td->td_retval[0] |= LINUX_O_RDWR; 98783221Smarcel if (result & O_NDELAY) 98883366Sjulian td->td_retval[0] |= LINUX_O_NONBLOCK; 98983221Smarcel if (result & O_APPEND) 99083366Sjulian td->td_retval[0] |= LINUX_O_APPEND; 99183221Smarcel if (result & O_FSYNC) 99283366Sjulian td->td_retval[0] |= LINUX_O_SYNC; 99383221Smarcel if (result & O_ASYNC) 99483366Sjulian td->td_retval[0] |= LINUX_FASYNC; 995144987Smdodd#ifdef LINUX_O_NOFOLLOW 996144987Smdodd if (result & O_NOFOLLOW) 997144987Smdodd td->td_retval[0] |= LINUX_O_NOFOLLOW; 998144987Smdodd#endif 999144987Smdodd#ifdef LINUX_O_DIRECT 1000144987Smdodd if (result & O_DIRECT) 1001144987Smdodd td->td_retval[0] |= LINUX_O_DIRECT; 1002144987Smdodd#endif 100383221Smarcel return (error); 100483221Smarcel 100583221Smarcel case LINUX_F_SETFL: 1006102872Siedowse arg = 0; 100783221Smarcel if (args->arg & LINUX_O_NDELAY) 1008102872Siedowse arg |= O_NONBLOCK; 100983221Smarcel if (args->arg & LINUX_O_APPEND) 1010102872Siedowse arg |= O_APPEND; 101183221Smarcel if (args->arg & LINUX_O_SYNC) 1012102872Siedowse arg |= O_FSYNC; 101383221Smarcel if (args->arg & LINUX_FASYNC) 1014102872Siedowse arg |= O_ASYNC; 1015144987Smdodd#ifdef LINUX_O_NOFOLLOW 1016144987Smdodd if (args->arg & LINUX_O_NOFOLLOW) 1017144987Smdodd arg |= O_NOFOLLOW; 1018144987Smdodd#endif 1019144987Smdodd#ifdef LINUX_O_DIRECT 1020144987Smdodd if (args->arg & LINUX_O_DIRECT) 1021144987Smdodd arg |= O_DIRECT; 1022144987Smdodd#endif 1023102872Siedowse return (kern_fcntl(td, args->fd, F_SETFL, arg)); 102483221Smarcel 1025107680Siedowse case LINUX_F_GETLK: 1026111797Sdes error = copyin((void *)args->arg, &linux_flock, 1027107680Siedowse sizeof(linux_flock)); 1028107680Siedowse if (error) 1029107680Siedowse return (error); 1030107680Siedowse linux_to_bsd_flock(&linux_flock, &bsd_flock); 1031107680Siedowse error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); 1032107680Siedowse if (error) 1033107680Siedowse return (error); 1034107680Siedowse bsd_to_linux_flock(&bsd_flock, &linux_flock); 1035111797Sdes return (copyout(&linux_flock, (void *)args->arg, 1036107680Siedowse sizeof(linux_flock))); 1037107680Siedowse 1038107680Siedowse case LINUX_F_SETLK: 1039111797Sdes error = copyin((void *)args->arg, &linux_flock, 1040107680Siedowse sizeof(linux_flock)); 1041107680Siedowse if (error) 1042107680Siedowse return (error); 1043107680Siedowse linux_to_bsd_flock(&linux_flock, &bsd_flock); 1044107680Siedowse return (kern_fcntl(td, args->fd, F_SETLK, 1045107680Siedowse (intptr_t)&bsd_flock)); 1046107680Siedowse 1047107680Siedowse case LINUX_F_SETLKW: 1048111797Sdes error = copyin((void *)args->arg, &linux_flock, 1049107680Siedowse sizeof(linux_flock)); 1050107680Siedowse if (error) 1051107680Siedowse return (error); 1052107680Siedowse linux_to_bsd_flock(&linux_flock, &bsd_flock); 1053107680Siedowse return (kern_fcntl(td, args->fd, F_SETLKW, 1054107680Siedowse (intptr_t)&bsd_flock)); 1055107680Siedowse 105683221Smarcel case LINUX_F_GETOWN: 1057102872Siedowse return (kern_fcntl(td, args->fd, F_GETOWN, 0)); 105883221Smarcel 105983221Smarcel case LINUX_F_SETOWN: 106083221Smarcel /* 106183221Smarcel * XXX some Linux applications depend on F_SETOWN having no 106283221Smarcel * significant effect for pipes (SIGIO is not delivered for 106383221Smarcel * pipes under Linux-2.2.35 at least). 106483221Smarcel */ 106589319Salfred error = fget(td, args->fd, &fp); 106689319Salfred if (error) 106789319Salfred return (error); 106889306Salfred if (fp->f_type == DTYPE_PIPE) { 106989306Salfred fdrop(fp, td); 107083221Smarcel return (EINVAL); 107189306Salfred } 107289306Salfred fdrop(fp, td); 107383221Smarcel 1074102872Siedowse return (kern_fcntl(td, args->fd, F_SETOWN, args->arg)); 107583221Smarcel } 107683221Smarcel 107783221Smarcel return (EINVAL); 107883221Smarcel} 107983221Smarcel 108083221Smarcelint 108183366Sjulianlinux_fcntl(struct thread *td, struct linux_fcntl_args *args) 108283221Smarcel{ 108383221Smarcel struct linux_fcntl64_args args64; 108483221Smarcel 108583221Smarcel#ifdef DEBUG 108683221Smarcel if (ldebug(fcntl)) 108783221Smarcel printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); 108883221Smarcel#endif 108983221Smarcel 109083221Smarcel args64.fd = args->fd; 109183221Smarcel args64.cmd = args->cmd; 109283221Smarcel args64.arg = args->arg; 109383366Sjulian return (fcntl_common(td, &args64)); 109483221Smarcel} 109583221Smarcel 1096140214Sobrien#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 109783221Smarcelint 109883366Sjulianlinux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) 109983221Smarcel{ 110083221Smarcel struct l_flock64 linux_flock; 1101102872Siedowse struct flock bsd_flock; 110283221Smarcel int error; 110383221Smarcel 110483221Smarcel#ifdef DEBUG 110583221Smarcel if (ldebug(fcntl64)) 110683221Smarcel printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd); 110783221Smarcel#endif 110883221Smarcel 110983221Smarcel switch (args->cmd) { 111099687Srobert case LINUX_F_GETLK64: 1111111797Sdes error = copyin((void *)args->arg, &linux_flock, 111283221Smarcel sizeof(linux_flock)); 111383221Smarcel if (error) 111483221Smarcel return (error); 1115102872Siedowse linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1116102872Siedowse error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); 111783221Smarcel if (error) 111883221Smarcel return (error); 1119102872Siedowse bsd_to_linux_flock64(&bsd_flock, &linux_flock); 1120111797Sdes return (copyout(&linux_flock, (void *)args->arg, 1121111797Sdes sizeof(linux_flock))); 112283221Smarcel 112399687Srobert case LINUX_F_SETLK64: 1124111797Sdes error = copyin((void *)args->arg, &linux_flock, 112583221Smarcel sizeof(linux_flock)); 112683221Smarcel if (error) 112783221Smarcel return (error); 1128102872Siedowse linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1129102872Siedowse return (kern_fcntl(td, args->fd, F_SETLK, 1130102872Siedowse (intptr_t)&bsd_flock)); 113183221Smarcel 113299687Srobert case LINUX_F_SETLKW64: 1133111797Sdes error = copyin((void *)args->arg, &linux_flock, 113483221Smarcel sizeof(linux_flock)); 113583221Smarcel if (error) 113683221Smarcel return (error); 1137102872Siedowse linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1138102872Siedowse return (kern_fcntl(td, args->fd, F_SETLKW, 1139102872Siedowse (intptr_t)&bsd_flock)); 114083221Smarcel } 114183221Smarcel 114283366Sjulian return (fcntl_common(td, args)); 114383221Smarcel} 1144133816Stjr#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 114585022Smarcel 114685022Smarcelint 114785022Smarcellinux_chown(struct thread *td, struct linux_chown_args *args) 114885022Smarcel{ 1149102814Siedowse char *path; 1150102814Siedowse int error; 115185022Smarcel 1152102814Siedowse LCONVPATHEXIST(td, args->path, &path); 115385022Smarcel 115485022Smarcel#ifdef DEBUG 115585022Smarcel if (ldebug(chown)) 1156102814Siedowse printf(ARGS(chown, "%s, %d, %d"), path, args->uid, args->gid); 115785022Smarcel#endif 1158102814Siedowse error = kern_chown(td, path, UIO_SYSSPACE, args->uid, args->gid); 1159102814Siedowse LFREEPATH(path); 1160102814Siedowse return (error); 116185022Smarcel} 116285022Smarcel 116385022Smarcelint 116485022Smarcellinux_lchown(struct thread *td, struct linux_lchown_args *args) 116585022Smarcel{ 1166102814Siedowse char *path; 1167102814Siedowse int error; 116885022Smarcel 1169102814Siedowse LCONVPATHEXIST(td, args->path, &path); 117085022Smarcel 117185022Smarcel#ifdef DEBUG 117285022Smarcel if (ldebug(lchown)) 1173102814Siedowse printf(ARGS(lchown, "%s, %d, %d"), path, args->uid, args->gid); 117485022Smarcel#endif 1175102814Siedowse error = kern_lchown(td, path, UIO_SYSSPACE, args->uid, args->gid); 1176102814Siedowse LFREEPATH(path); 1177102814Siedowse return (error); 117885022Smarcel} 1179