linux_file.c revision 160276
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 160276 2006-07-11 20:52:08Z jhb $"); 31116173Sobrien 32156874Sru#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 669313Ssosint 6783366Sjulianlinux_creat(struct thread *td, struct linux_creat_args *args) 689313Ssos{ 69102814Siedowse char *path; 70102814Siedowse int error; 719313Ssos 72102814Siedowse LCONVPATHEXIST(td, args->path, &path); 7314331Speter 749313Ssos#ifdef DEBUG 7572543Sjlemon if (ldebug(creat)) 76102814Siedowse printf(ARGS(creat, "%s, %d"), path, args->mode); 779313Ssos#endif 78102814Siedowse error = kern_open(td, path, UIO_SYSSPACE, O_WRONLY | O_CREAT | O_TRUNC, 79102814Siedowse args->mode); 80102814Siedowse LFREEPATH(path); 81102814Siedowse return (error); 829313Ssos} 839313Ssos 849313Ssosint 8583366Sjulianlinux_open(struct thread *td, struct linux_open_args *args) 869313Ssos{ 8783382Sjhb struct proc *p = td->td_proc; 88102814Siedowse char *path; 89102814Siedowse int bsd_flags, error; 9014331Speter 9114331Speter if (args->flags & LINUX_O_CREAT) 92102814Siedowse LCONVPATHCREAT(td, args->path, &path); 9314331Speter else 94102814Siedowse LCONVPATHEXIST(td, args->path, &path); 9514331Speter 969313Ssos#ifdef DEBUG 9772543Sjlemon if (ldebug(open)) 9872543Sjlemon printf(ARGS(open, "%s, 0x%x, 0x%x"), 99102814Siedowse path, args->flags, args->mode); 1009313Ssos#endif 101102814Siedowse bsd_flags = 0; 1029313Ssos if (args->flags & LINUX_O_RDONLY) 103102814Siedowse bsd_flags |= O_RDONLY; 104111798Sdes if (args->flags & LINUX_O_WRONLY) 105102814Siedowse bsd_flags |= O_WRONLY; 1069313Ssos if (args->flags & LINUX_O_RDWR) 107102814Siedowse bsd_flags |= O_RDWR; 1089313Ssos if (args->flags & LINUX_O_NDELAY) 109102814Siedowse bsd_flags |= O_NONBLOCK; 1109313Ssos if (args->flags & LINUX_O_APPEND) 111102814Siedowse bsd_flags |= O_APPEND; 1129313Ssos if (args->flags & LINUX_O_SYNC) 113102814Siedowse bsd_flags |= O_FSYNC; 1149313Ssos if (args->flags & LINUX_O_NONBLOCK) 115102814Siedowse bsd_flags |= O_NONBLOCK; 1169313Ssos if (args->flags & LINUX_FASYNC) 117102814Siedowse bsd_flags |= O_ASYNC; 1189313Ssos if (args->flags & LINUX_O_CREAT) 119102814Siedowse bsd_flags |= O_CREAT; 1209313Ssos if (args->flags & LINUX_O_TRUNC) 121102814Siedowse bsd_flags |= O_TRUNC; 1229313Ssos if (args->flags & LINUX_O_EXCL) 123102814Siedowse bsd_flags |= O_EXCL; 1249313Ssos if (args->flags & LINUX_O_NOCTTY) 125102814Siedowse bsd_flags |= O_NOCTTY; 1269313Ssos 127102814Siedowse error = kern_open(td, path, UIO_SYSSPACE, bsd_flags, args->mode); 12870061Sjhb PROC_LOCK(p); 129102814Siedowse if (!error && !(bsd_flags & O_NOCTTY) && 1309313Ssos SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 13189306Salfred struct file *fp; 1329313Ssos 133113917Sjhb PROC_UNLOCK(p); 13489319Salfred error = fget(td, td->td_retval[0], &fp); 13589319Salfred if (!error) { 13689319Salfred if (fp->f_type == DTYPE_VNODE) 137102003Srwatson fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred, 138102003Srwatson td); 13989319Salfred fdrop(fp, td); 14089319Salfred } 14191140Stanimura } else { 14270061Sjhb PROC_UNLOCK(p); 14314331Speter#ifdef DEBUG 14472543Sjlemon if (ldebug(open)) 14572543Sjlemon printf(LMSG("open returns error %d"), error); 14614331Speter#endif 14791140Stanimura } 148102814Siedowse LFREEPATH(path); 1499313Ssos return error; 1509313Ssos} 1519313Ssos 1529313Ssosint 15383366Sjulianlinux_lseek(struct thread *td, struct linux_lseek_args *args) 1549313Ssos{ 1559313Ssos 15612858Speter struct lseek_args /* { 15712858Speter int fd; 1589313Ssos int pad; 15912858Speter off_t offset; 1609313Ssos int whence; 16112858Speter } */ tmp_args; 1629313Ssos int error; 1639313Ssos 1649313Ssos#ifdef DEBUG 16572543Sjlemon if (ldebug(lseek)) 16672543Sjlemon printf(ARGS(lseek, "%d, %ld, %d"), 16783221Smarcel args->fdes, (long)args->off, args->whence); 1689313Ssos#endif 16912858Speter tmp_args.fd = args->fdes; 17012858Speter tmp_args.offset = (off_t)args->off; 1719313Ssos tmp_args.whence = args->whence; 17283366Sjulian error = lseek(td, &tmp_args); 1739313Ssos return error; 1749313Ssos} 1759313Ssos 17614331Speterint 17783366Sjulianlinux_llseek(struct thread *td, struct linux_llseek_args *args) 17814331Speter{ 17914331Speter struct lseek_args bsd_args; 18014331Speter int error; 18114331Speter off_t off; 18214331Speter 18314331Speter#ifdef DEBUG 18472543Sjlemon if (ldebug(llseek)) 18572543Sjlemon printf(ARGS(llseek, "%d, %d:%d, %d"), 18672543Sjlemon args->fd, args->ohigh, args->olow, args->whence); 18714331Speter#endif 18814331Speter off = (args->olow) | (((off_t) args->ohigh) << 32); 18914331Speter 19014331Speter bsd_args.fd = args->fd; 19114331Speter bsd_args.offset = off; 19214331Speter bsd_args.whence = args->whence; 19314331Speter 19483366Sjulian if ((error = lseek(td, &bsd_args))) 19514331Speter return error; 19614331Speter 197111797Sdes if ((error = copyout(td->td_retval, args->res, sizeof (off_t)))) 19814331Speter return error; 19914331Speter 20083366Sjulian td->td_retval[0] = 0; 20114331Speter return 0; 20214331Speter} 20314331Speter 2049313Ssosint 20583366Sjulianlinux_readdir(struct thread *td, struct linux_readdir_args *args) 2069313Ssos{ 20714331Speter struct linux_getdents_args lda; 20814331Speter 20914331Speter lda.fd = args->fd; 21014331Speter lda.dent = args->dent; 21114331Speter lda.count = 1; 21283366Sjulian return linux_getdents(td, &lda); 21314331Speter} 21414331Speter 21583221Smarcel/* 21683221Smarcel * Note that linux_getdents(2) and linux_getdents64(2) have the same 21783221Smarcel * arguments. They only differ in the definition of struct dirent they 21883221Smarcel * operate on. We use this to common the code, with the exception of 21983221Smarcel * accessing struct dirent. Note that linux_readdir(2) is implemented 22083221Smarcel * by means of linux_getdents(2). In this case we never operate on 22183221Smarcel * struct dirent64 and thus don't need to handle it... 22283221Smarcel */ 22383221Smarcel 22483221Smarcelstruct l_dirent { 22583221Smarcel l_long d_ino; 22683221Smarcel l_off_t d_off; 22783221Smarcel l_ushort d_reclen; 22883221Smarcel char d_name[LINUX_NAME_MAX + 1]; 22983221Smarcel}; 23083221Smarcel 23183221Smarcelstruct l_dirent64 { 23283221Smarcel uint64_t d_ino; 23383221Smarcel int64_t d_off; 23483221Smarcel l_ushort d_reclen; 23583221Smarcel u_char d_type; 23683221Smarcel char d_name[LINUX_NAME_MAX + 1]; 23783221Smarcel}; 23883221Smarcel 23983221Smarcel#define LINUX_RECLEN(de,namlen) \ 24083221Smarcel ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1)) 24183221Smarcel 24283221Smarcel#define LINUX_DIRBLKSIZ 512 24383221Smarcel 24483221Smarcelstatic int 24583366Sjuliangetdents_common(struct thread *td, struct linux_getdents64_args *args, 24683221Smarcel int is64bit) 24714331Speter{ 248111798Sdes struct dirent *bdp; 24983221Smarcel struct vnode *vp; 25083221Smarcel caddr_t inp, buf; /* BSD-format */ 25183221Smarcel int len, reclen; /* BSD-format */ 25283221Smarcel caddr_t outp; /* Linux-format */ 25383221Smarcel int resid, linuxreclen=0; /* Linux-format */ 25483221Smarcel struct file *fp; 25583221Smarcel struct uio auio; 25683221Smarcel struct iovec aiov; 25783221Smarcel off_t off; 25883221Smarcel struct l_dirent linux_dirent; 25983221Smarcel struct l_dirent64 linux_dirent64; 26083221Smarcel int buflen, error, eofflag, nbytes, justone; 26183221Smarcel u_long *cookies = NULL, *cookiep; 262160276Sjhb int ncookies, vfslocked; 2639313Ssos 264160276Sjhb nbytes = args->count; 265160276Sjhb if (nbytes == 1) { 266160276Sjhb /* readdir(2) case. Always struct dirent. */ 267160276Sjhb if (is64bit) 268160276Sjhb return (EINVAL); 269160276Sjhb nbytes = sizeof(linux_dirent); 270160276Sjhb justone = 1; 271160276Sjhb } else 272160276Sjhb justone = 0; 273160276Sjhb 27483366Sjulian if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0) 27583221Smarcel return (error); 2769313Ssos 27789306Salfred if ((fp->f_flag & FREAD) == 0) { 27889306Salfred fdrop(fp, td); 27983221Smarcel return (EBADF); 28089306Salfred } 2819313Ssos 282116678Sphk vp = fp->f_vnode; 283160276Sjhb vfslocked = VFS_LOCK_GIANT(vp->v_mount); 28489306Salfred if (vp->v_type != VDIR) { 285160276Sjhb VFS_UNLOCK_GIANT(vfslocked); 28689306Salfred fdrop(fp, td); 28783221Smarcel return (EINVAL); 28889306Salfred } 2899313Ssos 29083221Smarcel off = fp->f_offset; 2919313Ssos 29283221Smarcel buflen = max(LINUX_DIRBLKSIZ, nbytes); 29383221Smarcel buflen = min(buflen, MAXBSIZE); 294111119Simp buf = malloc(buflen, M_TEMP, M_WAITOK); 29583366Sjulian vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 29683221Smarcel 2979313Ssosagain: 29883221Smarcel aiov.iov_base = buf; 29983221Smarcel aiov.iov_len = buflen; 30083221Smarcel auio.uio_iov = &aiov; 30183221Smarcel auio.uio_iovcnt = 1; 30283221Smarcel auio.uio_rw = UIO_READ; 30383221Smarcel auio.uio_segflg = UIO_SYSSPACE; 30483366Sjulian auio.uio_td = td; 30583221Smarcel auio.uio_resid = buflen; 30683221Smarcel auio.uio_offset = off; 3079313Ssos 30883221Smarcel if (cookies) { 30983221Smarcel free(cookies, M_TEMP); 31083221Smarcel cookies = NULL; 31183221Smarcel } 31224654Sdfr 313101189Srwatson#ifdef MAC 314101189Srwatson /* 315101189Srwatson * Do directory search MAC check using non-cached credentials. 316101189Srwatson */ 317112451Sjhb if ((error = mac_check_vnode_readdir(td->td_ucred, vp))) 318101189Srwatson goto out; 319101189Srwatson#endif /* MAC */ 32083221Smarcel if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, 32183221Smarcel &cookies))) 32283221Smarcel goto out; 3239313Ssos 32483221Smarcel inp = buf; 32583221Smarcel outp = (caddr_t)args->dirent; 32683221Smarcel resid = nbytes; 32783221Smarcel if ((len = buflen - auio.uio_resid) <= 0) 32883221Smarcel goto eof; 3299313Ssos 33083221Smarcel cookiep = cookies; 33124654Sdfr 33283221Smarcel if (cookies) { 33383221Smarcel /* 33483221Smarcel * When using cookies, the vfs has the option of reading from 33583221Smarcel * a different offset than that supplied (UFS truncates the 33683221Smarcel * offset to a block boundary to make sure that it never reads 33783221Smarcel * partway through a directory entry, even if the directory 33883221Smarcel * has been compacted). 33983221Smarcel */ 34083221Smarcel while (len > 0 && ncookies > 0 && *cookiep <= off) { 34183221Smarcel bdp = (struct dirent *) inp; 34283221Smarcel len -= bdp->d_reclen; 34383221Smarcel inp += bdp->d_reclen; 34483221Smarcel cookiep++; 34583221Smarcel ncookies--; 34683221Smarcel } 34724654Sdfr } 34824654Sdfr 34983221Smarcel while (len > 0) { 35083221Smarcel if (cookiep && ncookies == 0) 35183221Smarcel break; 35283221Smarcel bdp = (struct dirent *) inp; 35383221Smarcel reclen = bdp->d_reclen; 35483221Smarcel if (reclen & 3) { 35583221Smarcel error = EFAULT; 35683221Smarcel goto out; 35783221Smarcel } 35883221Smarcel 35983221Smarcel if (bdp->d_fileno == 0) { 36083221Smarcel inp += reclen; 36183221Smarcel if (cookiep) { 36283221Smarcel off = *cookiep++; 36383221Smarcel ncookies--; 36483221Smarcel } else 36583221Smarcel off += reclen; 36683221Smarcel 36783221Smarcel len -= reclen; 36883221Smarcel continue; 36983221Smarcel } 37083221Smarcel 37183221Smarcel linuxreclen = (is64bit) 37283221Smarcel ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen) 37383221Smarcel : LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 37483221Smarcel 37583221Smarcel if (reclen > len || resid < linuxreclen) { 37683221Smarcel outp++; 37783221Smarcel break; 37883221Smarcel } 37983221Smarcel 38083221Smarcel if (justone) { 38183221Smarcel /* readdir(2) case. */ 38283221Smarcel linux_dirent.d_ino = (l_long)bdp->d_fileno; 38383221Smarcel linux_dirent.d_off = (l_off_t)linuxreclen; 38483221Smarcel linux_dirent.d_reclen = (l_ushort)bdp->d_namlen; 38583221Smarcel strcpy(linux_dirent.d_name, bdp->d_name); 38683221Smarcel error = copyout(&linux_dirent, outp, linuxreclen); 38783221Smarcel } else { 38883221Smarcel if (is64bit) { 38983221Smarcel linux_dirent64.d_ino = bdp->d_fileno; 39083221Smarcel linux_dirent64.d_off = (cookiep) 39183221Smarcel ? (l_off_t)*cookiep 39283221Smarcel : (l_off_t)(off + reclen); 39383221Smarcel linux_dirent64.d_reclen = 39483221Smarcel (l_ushort)linuxreclen; 39583221Smarcel linux_dirent64.d_type = bdp->d_type; 39683221Smarcel strcpy(linux_dirent64.d_name, bdp->d_name); 39783221Smarcel error = copyout(&linux_dirent64, outp, 39883221Smarcel linuxreclen); 39983221Smarcel } else { 40083221Smarcel linux_dirent.d_ino = bdp->d_fileno; 40183221Smarcel linux_dirent.d_off = (cookiep) 40283221Smarcel ? (l_off_t)*cookiep 40383221Smarcel : (l_off_t)(off + reclen); 40483221Smarcel linux_dirent.d_reclen = (l_ushort)linuxreclen; 40583221Smarcel strcpy(linux_dirent.d_name, bdp->d_name); 40683221Smarcel error = copyout(&linux_dirent, outp, 40783221Smarcel linuxreclen); 40883221Smarcel } 40983221Smarcel } 41083221Smarcel if (error) 41183221Smarcel goto out; 41283221Smarcel 41383221Smarcel inp += reclen; 41483221Smarcel if (cookiep) { 41583221Smarcel off = *cookiep++; 41683221Smarcel ncookies--; 41783221Smarcel } else 41883221Smarcel off += reclen; 41983221Smarcel 42083221Smarcel outp += linuxreclen; 42183221Smarcel resid -= linuxreclen; 42283221Smarcel len -= reclen; 42383221Smarcel if (justone) 42483221Smarcel break; 42510355Sswallace } 4269313Ssos 42783221Smarcel if (outp == (caddr_t)args->dirent) 42883221Smarcel goto again; 4299313Ssos 43083221Smarcel fp->f_offset = off; 43183221Smarcel if (justone) 43283221Smarcel nbytes = resid + linuxreclen; 43310355Sswallace 4349313Ssoseof: 43583366Sjulian td->td_retval[0] = nbytes - resid; 43683221Smarcel 4379313Ssosout: 43883221Smarcel if (cookies) 43983221Smarcel free(cookies, M_TEMP); 44083221Smarcel 44183366Sjulian VOP_UNLOCK(vp, 0, td); 442160276Sjhb VFS_UNLOCK_GIANT(vfslocked); 44389306Salfred fdrop(fp, td); 44483221Smarcel free(buf, M_TEMP); 44583221Smarcel return (error); 4469313Ssos} 44714331Speter 44883221Smarcelint 44983366Sjulianlinux_getdents(struct thread *td, struct linux_getdents_args *args) 45083221Smarcel{ 45183221Smarcel 45283221Smarcel#ifdef DEBUG 45383221Smarcel if (ldebug(getdents)) 45483221Smarcel printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count); 45583221Smarcel#endif 45683221Smarcel 45783366Sjulian return (getdents_common(td, (struct linux_getdents64_args*)args, 0)); 45883221Smarcel} 45983221Smarcel 46083221Smarcelint 46183366Sjulianlinux_getdents64(struct thread *td, struct linux_getdents64_args *args) 46283221Smarcel{ 46383221Smarcel 46483221Smarcel#ifdef DEBUG 46583221Smarcel if (ldebug(getdents64)) 46683221Smarcel printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count); 46783221Smarcel#endif 46883221Smarcel 46983366Sjulian return (getdents_common(td, args, 1)); 47083221Smarcel} 47183221Smarcel 47214331Speter/* 47314331Speter * These exist mainly for hooks for doing /compat/linux translation. 47414331Speter */ 47514331Speter 47614331Speterint 47783366Sjulianlinux_access(struct thread *td, struct linux_access_args *args) 47814331Speter{ 479102814Siedowse char *path; 480102814Siedowse int error; 48114331Speter 482102814Siedowse LCONVPATHEXIST(td, args->path, &path); 48314331Speter 48414331Speter#ifdef DEBUG 48572543Sjlemon if (ldebug(access)) 486102814Siedowse printf(ARGS(access, "%s, %d"), path, args->flags); 48714331Speter#endif 488102814Siedowse error = kern_access(td, path, UIO_SYSSPACE, args->flags); 489102814Siedowse LFREEPATH(path); 490102814Siedowse return (error); 49114331Speter} 49214331Speter 49314331Speterint 49483366Sjulianlinux_unlink(struct thread *td, struct linux_unlink_args *args) 49514331Speter{ 496102814Siedowse char *path; 497102814Siedowse int error; 49814331Speter 499102814Siedowse LCONVPATHEXIST(td, args->path, &path); 50014331Speter 50114331Speter#ifdef DEBUG 50272543Sjlemon if (ldebug(unlink)) 503102814Siedowse printf(ARGS(unlink, "%s"), path); 50414331Speter#endif 50514331Speter 506102814Siedowse error = kern_unlink(td, path, UIO_SYSSPACE); 507102814Siedowse LFREEPATH(path); 508102814Siedowse return (error); 50914331Speter} 51014331Speter 51114331Speterint 51283366Sjulianlinux_chdir(struct thread *td, struct linux_chdir_args *args) 51314331Speter{ 514102814Siedowse char *path; 515102814Siedowse int error; 51614331Speter 517102814Siedowse LCONVPATHEXIST(td, args->path, &path); 51814331Speter 51914331Speter#ifdef DEBUG 52072543Sjlemon if (ldebug(chdir)) 521102814Siedowse printf(ARGS(chdir, "%s"), path); 52214331Speter#endif 523102814Siedowse error = kern_chdir(td, path, UIO_SYSSPACE); 524102814Siedowse LFREEPATH(path); 525102814Siedowse return (error); 52614331Speter} 52714331Speter 52814331Speterint 52983366Sjulianlinux_chmod(struct thread *td, struct linux_chmod_args *args) 53014331Speter{ 531102814Siedowse char *path; 532102814Siedowse int error; 53314331Speter 534102814Siedowse LCONVPATHEXIST(td, args->path, &path); 53514331Speter 53614331Speter#ifdef DEBUG 53772543Sjlemon if (ldebug(chmod)) 538102814Siedowse printf(ARGS(chmod, "%s, %d"), path, args->mode); 53914331Speter#endif 540102814Siedowse error = kern_chmod(td, path, UIO_SYSSPACE, args->mode); 541102814Siedowse LFREEPATH(path); 542102814Siedowse return (error); 54314331Speter} 54414331Speter 54514331Speterint 54683366Sjulianlinux_mkdir(struct thread *td, struct linux_mkdir_args *args) 54714331Speter{ 548102814Siedowse char *path; 549102814Siedowse int error; 55014331Speter 551102814Siedowse LCONVPATHCREAT(td, args->path, &path); 55214331Speter 55314331Speter#ifdef DEBUG 55472543Sjlemon if (ldebug(mkdir)) 555102814Siedowse printf(ARGS(mkdir, "%s, %d"), path, args->mode); 55614331Speter#endif 557102814Siedowse error = kern_mkdir(td, path, UIO_SYSSPACE, args->mode); 558102814Siedowse LFREEPATH(path); 559102814Siedowse return (error); 56014331Speter} 56114331Speter 56214331Speterint 56383366Sjulianlinux_rmdir(struct thread *td, struct linux_rmdir_args *args) 56414331Speter{ 565102814Siedowse char *path; 566102814Siedowse int error; 56714331Speter 568102814Siedowse LCONVPATHEXIST(td, args->path, &path); 56914331Speter 57014331Speter#ifdef DEBUG 57172543Sjlemon if (ldebug(rmdir)) 572102814Siedowse printf(ARGS(rmdir, "%s"), path); 57314331Speter#endif 574102814Siedowse error = kern_rmdir(td, path, UIO_SYSSPACE); 575102814Siedowse LFREEPATH(path); 576102814Siedowse return (error); 57714331Speter} 57814331Speter 57914331Speterint 58083366Sjulianlinux_rename(struct thread *td, struct linux_rename_args *args) 58114331Speter{ 582102814Siedowse char *from, *to; 583102814Siedowse int error; 58414331Speter 585102814Siedowse LCONVPATHEXIST(td, args->from, &from); 586102814Siedowse /* Expand LCONVPATHCREATE so that `from' can be freed on errors */ 587102814Siedowse error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); 588102814Siedowse if (to == NULL) { 589102814Siedowse LFREEPATH(from); 590102814Siedowse return (error); 591102814Siedowse } 59214331Speter 59314331Speter#ifdef DEBUG 59472543Sjlemon if (ldebug(rename)) 595102814Siedowse printf(ARGS(rename, "%s, %s"), from, to); 59614331Speter#endif 597102814Siedowse error = kern_rename(td, from, to, UIO_SYSSPACE); 598102814Siedowse LFREEPATH(from); 599102814Siedowse LFREEPATH(to); 600102814Siedowse return (error); 60114331Speter} 60214331Speter 60314331Speterint 60483366Sjulianlinux_symlink(struct thread *td, struct linux_symlink_args *args) 60514331Speter{ 606102814Siedowse char *path, *to; 607102814Siedowse int error; 60814331Speter 609102814Siedowse LCONVPATHEXIST(td, args->path, &path); 610102814Siedowse /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 611102814Siedowse error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); 612102814Siedowse if (to == NULL) { 613102814Siedowse LFREEPATH(path); 614102814Siedowse return (error); 615102814Siedowse } 61614331Speter 61714331Speter#ifdef DEBUG 61872543Sjlemon if (ldebug(symlink)) 619102814Siedowse printf(ARGS(symlink, "%s, %s"), path, to); 62014331Speter#endif 621102814Siedowse error = kern_symlink(td, path, to, UIO_SYSSPACE); 622102814Siedowse LFREEPATH(path); 623102814Siedowse LFREEPATH(to); 624102814Siedowse return (error); 62514331Speter} 62614331Speter 62714331Speterint 62883366Sjulianlinux_readlink(struct thread *td, struct linux_readlink_args *args) 62914331Speter{ 630102814Siedowse char *name; 631102814Siedowse int error; 63214331Speter 633102814Siedowse LCONVPATHEXIST(td, args->name, &name); 63414331Speter 63514331Speter#ifdef DEBUG 63672543Sjlemon if (ldebug(readlink)) 637102814Siedowse printf(ARGS(readlink, "%s, %p, %d"), name, (void *)args->buf, 638102814Siedowse args->count); 63914331Speter#endif 640102814Siedowse error = kern_readlink(td, name, UIO_SYSSPACE, args->buf, UIO_USERSPACE, 641102814Siedowse args->count); 642102814Siedowse LFREEPATH(name); 643102814Siedowse return (error); 64414331Speter} 64514331Speter 64614331Speterint 64783366Sjulianlinux_truncate(struct thread *td, struct linux_truncate_args *args) 64814331Speter{ 649102814Siedowse char *path; 650102814Siedowse int error; 65114331Speter 652102814Siedowse LCONVPATHEXIST(td, args->path, &path); 65314331Speter 65414331Speter#ifdef DEBUG 65572543Sjlemon if (ldebug(truncate)) 656102814Siedowse printf(ARGS(truncate, "%s, %ld"), path, (long)args->length); 65714331Speter#endif 65814331Speter 659102814Siedowse error = kern_truncate(td, path, UIO_SYSSPACE, args->length); 660102814Siedowse LFREEPATH(path); 661102814Siedowse return (error); 66214331Speter} 66314331Speter 66449662Smarcelint 665156842Snetchildlinux_ftruncate(struct thread *td, struct linux_ftruncate_args *args) 666156842Snetchild{ 667156842Snetchild struct ftruncate_args /* { 668156842Snetchild int fd; 669156842Snetchild int pad; 670156842Snetchild off_t length; 671156842Snetchild } */ nuap; 672156842Snetchild 673156842Snetchild nuap.fd = args->fd; 674156842Snetchild nuap.pad = 0; 675156842Snetchild nuap.length = args->length; 676156842Snetchild return (ftruncate(td, &nuap)); 677156842Snetchild} 678156842Snetchild 679156842Snetchildint 68083366Sjulianlinux_link(struct thread *td, struct linux_link_args *args) 68149662Smarcel{ 682102814Siedowse char *path, *to; 683102814Siedowse int error; 68449662Smarcel 685102814Siedowse LCONVPATHEXIST(td, args->path, &path); 686102814Siedowse /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 687102814Siedowse error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); 688102814Siedowse if (to == NULL) { 689102814Siedowse LFREEPATH(path); 690102814Siedowse return (error); 691102814Siedowse } 69249662Smarcel 69349662Smarcel#ifdef DEBUG 69472543Sjlemon if (ldebug(link)) 695102814Siedowse printf(ARGS(link, "%s, %s"), path, to); 69649662Smarcel#endif 697102814Siedowse error = kern_link(td, path, to, UIO_SYSSPACE); 698102814Siedowse LFREEPATH(path); 699102814Siedowse LFREEPATH(to); 700102814Siedowse return (error); 70149662Smarcel} 70249788Smarcel 70353713Smarcelint 70483366Sjulianlinux_fdatasync(td, uap) 70583366Sjulian struct thread *td; 70653713Smarcel struct linux_fdatasync_args *uap; 70753713Smarcel{ 70853713Smarcel struct fsync_args bsd; 70953713Smarcel 71053713Smarcel bsd.fd = uap->fd; 71183366Sjulian return fsync(td, &bsd); 71253713Smarcel} 71363285Smarcel 71463285Smarcelint 71583366Sjulianlinux_pread(td, uap) 71683366Sjulian struct thread *td; 71763285Smarcel struct linux_pread_args *uap; 71863285Smarcel{ 71963285Smarcel struct pread_args bsd; 72063285Smarcel 72163285Smarcel bsd.fd = uap->fd; 72263285Smarcel bsd.buf = uap->buf; 72363285Smarcel bsd.nbyte = uap->nbyte; 72463285Smarcel bsd.offset = uap->offset; 72583366Sjulian return pread(td, &bsd); 72663285Smarcel} 72763285Smarcel 72863285Smarcelint 72983366Sjulianlinux_pwrite(td, uap) 73083366Sjulian struct thread *td; 73163285Smarcel struct linux_pwrite_args *uap; 73263285Smarcel{ 73363285Smarcel struct pwrite_args bsd; 73463285Smarcel 73563285Smarcel bsd.fd = uap->fd; 73663285Smarcel bsd.buf = uap->buf; 73763285Smarcel bsd.nbyte = uap->nbyte; 73863285Smarcel bsd.offset = uap->offset; 73983366Sjulian return pwrite(td, &bsd); 74063285Smarcel} 74172538Sjlemon 74272538Sjlemonint 74383366Sjulianlinux_mount(struct thread *td, struct linux_mount_args *args) 74472538Sjlemon{ 74572538Sjlemon struct ufs_args ufs; 746111798Sdes char fstypename[MFSNAMELEN]; 747111798Sdes char mntonname[MNAMELEN], mntfromname[MNAMELEN]; 74873286Sadrian int error; 74973286Sadrian int fsflags; 75073286Sadrian void *fsdata; 75172538Sjlemon 752111798Sdes error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1, 75373286Sadrian NULL); 75472538Sjlemon if (error) 755111798Sdes return (error); 756127057Stjr error = copyinstr(args->specialfile, mntfromname, MNAMELEN - 1, NULL); 75772538Sjlemon if (error) 758111798Sdes return (error); 759127057Stjr error = copyinstr(args->dir, mntonname, MNAMELEN - 1, NULL); 76072538Sjlemon if (error) 761111798Sdes return (error); 76272538Sjlemon 76372538Sjlemon#ifdef DEBUG 76472538Sjlemon if (ldebug(mount)) 76572538Sjlemon printf(ARGS(mount, "%s, %s, %s"), 76672538Sjlemon fstypename, mntfromname, mntonname); 76772538Sjlemon#endif 76872538Sjlemon 76972538Sjlemon if (strcmp(fstypename, "ext2") == 0) { 770127059Stjr strcpy(fstypename, "ext2fs"); 77173286Sadrian fsdata = &ufs; 77272538Sjlemon ufs.fspec = mntfromname; 77372538Sjlemon#define DEFAULT_ROOTID -2 77472538Sjlemon ufs.export.ex_root = DEFAULT_ROOTID; 77572538Sjlemon ufs.export.ex_flags = 77672538Sjlemon args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0; 77772538Sjlemon } else if (strcmp(fstypename, "proc") == 0) { 778127059Stjr strcpy(fstypename, "linprocfs"); 77973286Sadrian fsdata = NULL; 78072538Sjlemon } else { 78172538Sjlemon return (ENODEV); 78272538Sjlemon } 78372538Sjlemon 78473286Sadrian fsflags = 0; 78572538Sjlemon 78672538Sjlemon if ((args->rwflag & 0xffff0000) == 0xc0ed0000) { 78772538Sjlemon /* 78872538Sjlemon * Linux SYNC flag is not included; the closest equivalent 78972538Sjlemon * FreeBSD has is !ASYNC, which is our default. 79072538Sjlemon */ 79172538Sjlemon if (args->rwflag & LINUX_MS_RDONLY) 792111798Sdes fsflags |= MNT_RDONLY; 79372538Sjlemon if (args->rwflag & LINUX_MS_NOSUID) 794111798Sdes fsflags |= MNT_NOSUID; 79572538Sjlemon if (args->rwflag & LINUX_MS_NOEXEC) 796111798Sdes fsflags |= MNT_NOEXEC; 79772538Sjlemon if (args->rwflag & LINUX_MS_REMOUNT) 798111798Sdes fsflags |= MNT_UPDATE; 79972538Sjlemon } 80072538Sjlemon 801127059Stjr if (strcmp(fstypename, "linprocfs") == 0) { 802132708Sphk error = kernel_vmount(fsflags, 803132708Sphk "fstype", fstypename, 804132708Sphk "fspath", mntonname, 805132708Sphk NULL); 806127059Stjr } else 807138353Sphk error = EOPNOTSUPP; 808127059Stjr return (error); 80972538Sjlemon} 81072538Sjlemon 81172538Sjlemonint 81283366Sjulianlinux_oldumount(struct thread *td, struct linux_oldumount_args *args) 81372538Sjlemon{ 81483221Smarcel struct linux_umount_args args2; 81572538Sjlemon 81672538Sjlemon args2.path = args->path; 81772538Sjlemon args2.flags = 0; 81883366Sjulian return (linux_umount(td, &args2)); 81972538Sjlemon} 82072538Sjlemon 82172538Sjlemonint 82283366Sjulianlinux_umount(struct thread *td, struct linux_umount_args *args) 82372538Sjlemon{ 82472538Sjlemon struct unmount_args bsd; 82572538Sjlemon 82672538Sjlemon bsd.path = args->path; 82772538Sjlemon bsd.flags = args->flags; /* XXX correct? */ 82883366Sjulian return (unmount(td, &bsd)); 82972538Sjlemon} 83083221Smarcel 83183221Smarcel/* 83283221Smarcel * fcntl family of syscalls 83383221Smarcel */ 83483221Smarcel 83583221Smarcelstruct l_flock { 83683221Smarcel l_short l_type; 83783221Smarcel l_short l_whence; 83883221Smarcel l_off_t l_start; 83983221Smarcel l_off_t l_len; 84083221Smarcel l_pid_t l_pid; 841133816Stjr} 842140214Sobrien#if defined(__amd64__) && defined(COMPAT_LINUX32) 843133816Stjr__packed 844133816Stjr#endif 845133816Stjr; 84683221Smarcel 84783221Smarcelstatic void 84883221Smarcellinux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock) 84983221Smarcel{ 85083221Smarcel switch (linux_flock->l_type) { 85183221Smarcel case LINUX_F_RDLCK: 85283221Smarcel bsd_flock->l_type = F_RDLCK; 85383221Smarcel break; 85483221Smarcel case LINUX_F_WRLCK: 85583221Smarcel bsd_flock->l_type = F_WRLCK; 85683221Smarcel break; 85783221Smarcel case LINUX_F_UNLCK: 85883221Smarcel bsd_flock->l_type = F_UNLCK; 85983221Smarcel break; 86083221Smarcel default: 86183221Smarcel bsd_flock->l_type = -1; 86283221Smarcel break; 86383221Smarcel } 86483221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 86583221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 86683221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 86783221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 86883221Smarcel} 86983221Smarcel 87083221Smarcelstatic void 87183221Smarcelbsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock) 87283221Smarcel{ 87383221Smarcel switch (bsd_flock->l_type) { 87483221Smarcel case F_RDLCK: 87583221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 87683221Smarcel break; 87783221Smarcel case F_WRLCK: 87883221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 87983221Smarcel break; 88083221Smarcel case F_UNLCK: 88183221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 88283221Smarcel break; 88383221Smarcel } 88483221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 88583221Smarcel linux_flock->l_start = (l_off_t)bsd_flock->l_start; 88683221Smarcel linux_flock->l_len = (l_off_t)bsd_flock->l_len; 88783221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 88883221Smarcel} 88983221Smarcel 890140214Sobrien#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 89183221Smarcelstruct l_flock64 { 89283221Smarcel l_short l_type; 89383221Smarcel l_short l_whence; 89483221Smarcel l_loff_t l_start; 89583221Smarcel l_loff_t l_len; 89683221Smarcel l_pid_t l_pid; 897133816Stjr} 898140214Sobrien#if defined(__amd64__) && defined(COMPAT_LINUX32) 899133816Stjr__packed 900133816Stjr#endif 901133816Stjr; 90283221Smarcel 90383221Smarcelstatic void 90483221Smarcellinux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock) 90583221Smarcel{ 90683221Smarcel switch (linux_flock->l_type) { 90783221Smarcel case LINUX_F_RDLCK: 90883221Smarcel bsd_flock->l_type = F_RDLCK; 90983221Smarcel break; 91083221Smarcel case LINUX_F_WRLCK: 91183221Smarcel bsd_flock->l_type = F_WRLCK; 91283221Smarcel break; 91383221Smarcel case LINUX_F_UNLCK: 91483221Smarcel bsd_flock->l_type = F_UNLCK; 91583221Smarcel break; 91683221Smarcel default: 91783221Smarcel bsd_flock->l_type = -1; 91883221Smarcel break; 91983221Smarcel } 92083221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 92183221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 92283221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 92383221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 92483221Smarcel} 92583221Smarcel 92683221Smarcelstatic void 92783221Smarcelbsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) 92883221Smarcel{ 92983221Smarcel switch (bsd_flock->l_type) { 93083221Smarcel case F_RDLCK: 93183221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 93283221Smarcel break; 93383221Smarcel case F_WRLCK: 93483221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 93583221Smarcel break; 93683221Smarcel case F_UNLCK: 93783221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 93883221Smarcel break; 93983221Smarcel } 94083221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 94183221Smarcel linux_flock->l_start = (l_loff_t)bsd_flock->l_start; 94283221Smarcel linux_flock->l_len = (l_loff_t)bsd_flock->l_len; 94383221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 94483221Smarcel} 945133816Stjr#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 94683221Smarcel 94783221Smarcelstatic int 94883366Sjulianfcntl_common(struct thread *td, struct linux_fcntl64_args *args) 94983221Smarcel{ 950107680Siedowse struct l_flock linux_flock; 951107680Siedowse struct flock bsd_flock; 95283221Smarcel struct file *fp; 953102872Siedowse long arg; 95483221Smarcel int error, result; 95583221Smarcel 95683221Smarcel switch (args->cmd) { 95783221Smarcel case LINUX_F_DUPFD: 958102872Siedowse return (kern_fcntl(td, args->fd, F_DUPFD, args->arg)); 95983221Smarcel 96083221Smarcel case LINUX_F_GETFD: 961102872Siedowse return (kern_fcntl(td, args->fd, F_GETFD, 0)); 96283221Smarcel 96383221Smarcel case LINUX_F_SETFD: 964102872Siedowse return (kern_fcntl(td, args->fd, F_SETFD, args->arg)); 96583221Smarcel 96683221Smarcel case LINUX_F_GETFL: 967102872Siedowse error = kern_fcntl(td, args->fd, F_GETFL, 0); 96883366Sjulian result = td->td_retval[0]; 96983366Sjulian td->td_retval[0] = 0; 97083221Smarcel if (result & O_RDONLY) 97183366Sjulian td->td_retval[0] |= LINUX_O_RDONLY; 97283221Smarcel if (result & O_WRONLY) 97383366Sjulian td->td_retval[0] |= LINUX_O_WRONLY; 97483221Smarcel if (result & O_RDWR) 97583366Sjulian td->td_retval[0] |= LINUX_O_RDWR; 97683221Smarcel if (result & O_NDELAY) 97783366Sjulian td->td_retval[0] |= LINUX_O_NONBLOCK; 97883221Smarcel if (result & O_APPEND) 97983366Sjulian td->td_retval[0] |= LINUX_O_APPEND; 98083221Smarcel if (result & O_FSYNC) 98183366Sjulian td->td_retval[0] |= LINUX_O_SYNC; 98283221Smarcel if (result & O_ASYNC) 98383366Sjulian td->td_retval[0] |= LINUX_FASYNC; 984144987Smdodd#ifdef LINUX_O_NOFOLLOW 985144987Smdodd if (result & O_NOFOLLOW) 986144987Smdodd td->td_retval[0] |= LINUX_O_NOFOLLOW; 987144987Smdodd#endif 988144987Smdodd#ifdef LINUX_O_DIRECT 989144987Smdodd if (result & O_DIRECT) 990144987Smdodd td->td_retval[0] |= LINUX_O_DIRECT; 991144987Smdodd#endif 99283221Smarcel return (error); 99383221Smarcel 99483221Smarcel case LINUX_F_SETFL: 995102872Siedowse arg = 0; 99683221Smarcel if (args->arg & LINUX_O_NDELAY) 997102872Siedowse arg |= O_NONBLOCK; 99883221Smarcel if (args->arg & LINUX_O_APPEND) 999102872Siedowse arg |= O_APPEND; 100083221Smarcel if (args->arg & LINUX_O_SYNC) 1001102872Siedowse arg |= O_FSYNC; 100283221Smarcel if (args->arg & LINUX_FASYNC) 1003102872Siedowse arg |= O_ASYNC; 1004144987Smdodd#ifdef LINUX_O_NOFOLLOW 1005144987Smdodd if (args->arg & LINUX_O_NOFOLLOW) 1006144987Smdodd arg |= O_NOFOLLOW; 1007144987Smdodd#endif 1008144987Smdodd#ifdef LINUX_O_DIRECT 1009144987Smdodd if (args->arg & LINUX_O_DIRECT) 1010144987Smdodd arg |= O_DIRECT; 1011144987Smdodd#endif 1012102872Siedowse return (kern_fcntl(td, args->fd, F_SETFL, arg)); 101383221Smarcel 1014107680Siedowse case LINUX_F_GETLK: 1015111797Sdes error = copyin((void *)args->arg, &linux_flock, 1016107680Siedowse sizeof(linux_flock)); 1017107680Siedowse if (error) 1018107680Siedowse return (error); 1019107680Siedowse linux_to_bsd_flock(&linux_flock, &bsd_flock); 1020107680Siedowse error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); 1021107680Siedowse if (error) 1022107680Siedowse return (error); 1023107680Siedowse bsd_to_linux_flock(&bsd_flock, &linux_flock); 1024111797Sdes return (copyout(&linux_flock, (void *)args->arg, 1025107680Siedowse sizeof(linux_flock))); 1026107680Siedowse 1027107680Siedowse case LINUX_F_SETLK: 1028111797Sdes error = copyin((void *)args->arg, &linux_flock, 1029107680Siedowse sizeof(linux_flock)); 1030107680Siedowse if (error) 1031107680Siedowse return (error); 1032107680Siedowse linux_to_bsd_flock(&linux_flock, &bsd_flock); 1033107680Siedowse return (kern_fcntl(td, args->fd, F_SETLK, 1034107680Siedowse (intptr_t)&bsd_flock)); 1035107680Siedowse 1036107680Siedowse case LINUX_F_SETLKW: 1037111797Sdes error = copyin((void *)args->arg, &linux_flock, 1038107680Siedowse sizeof(linux_flock)); 1039107680Siedowse if (error) 1040107680Siedowse return (error); 1041107680Siedowse linux_to_bsd_flock(&linux_flock, &bsd_flock); 1042107680Siedowse return (kern_fcntl(td, args->fd, F_SETLKW, 1043107680Siedowse (intptr_t)&bsd_flock)); 1044107680Siedowse 104583221Smarcel case LINUX_F_GETOWN: 1046102872Siedowse return (kern_fcntl(td, args->fd, F_GETOWN, 0)); 104783221Smarcel 104883221Smarcel case LINUX_F_SETOWN: 104983221Smarcel /* 105083221Smarcel * XXX some Linux applications depend on F_SETOWN having no 105183221Smarcel * significant effect for pipes (SIGIO is not delivered for 105283221Smarcel * pipes under Linux-2.2.35 at least). 105383221Smarcel */ 105489319Salfred error = fget(td, args->fd, &fp); 105589319Salfred if (error) 105689319Salfred return (error); 105789306Salfred if (fp->f_type == DTYPE_PIPE) { 105889306Salfred fdrop(fp, td); 105983221Smarcel return (EINVAL); 106089306Salfred } 106189306Salfred fdrop(fp, td); 106283221Smarcel 1063102872Siedowse return (kern_fcntl(td, args->fd, F_SETOWN, args->arg)); 106483221Smarcel } 106583221Smarcel 106683221Smarcel return (EINVAL); 106783221Smarcel} 106883221Smarcel 106983221Smarcelint 107083366Sjulianlinux_fcntl(struct thread *td, struct linux_fcntl_args *args) 107183221Smarcel{ 107283221Smarcel struct linux_fcntl64_args args64; 107383221Smarcel 107483221Smarcel#ifdef DEBUG 107583221Smarcel if (ldebug(fcntl)) 107683221Smarcel printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); 107783221Smarcel#endif 107883221Smarcel 107983221Smarcel args64.fd = args->fd; 108083221Smarcel args64.cmd = args->cmd; 108183221Smarcel args64.arg = args->arg; 108283366Sjulian return (fcntl_common(td, &args64)); 108383221Smarcel} 108483221Smarcel 1085140214Sobrien#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 108683221Smarcelint 108783366Sjulianlinux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) 108883221Smarcel{ 108983221Smarcel struct l_flock64 linux_flock; 1090102872Siedowse struct flock bsd_flock; 109183221Smarcel int error; 109283221Smarcel 109383221Smarcel#ifdef DEBUG 109483221Smarcel if (ldebug(fcntl64)) 109583221Smarcel printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd); 109683221Smarcel#endif 109783221Smarcel 109883221Smarcel switch (args->cmd) { 109999687Srobert case LINUX_F_GETLK64: 1100111797Sdes error = copyin((void *)args->arg, &linux_flock, 110183221Smarcel sizeof(linux_flock)); 110283221Smarcel if (error) 110383221Smarcel return (error); 1104102872Siedowse linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1105102872Siedowse error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); 110683221Smarcel if (error) 110783221Smarcel return (error); 1108102872Siedowse bsd_to_linux_flock64(&bsd_flock, &linux_flock); 1109111797Sdes return (copyout(&linux_flock, (void *)args->arg, 1110111797Sdes sizeof(linux_flock))); 111183221Smarcel 111299687Srobert case LINUX_F_SETLK64: 1113111797Sdes error = copyin((void *)args->arg, &linux_flock, 111483221Smarcel sizeof(linux_flock)); 111583221Smarcel if (error) 111683221Smarcel return (error); 1117102872Siedowse linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1118102872Siedowse return (kern_fcntl(td, args->fd, F_SETLK, 1119102872Siedowse (intptr_t)&bsd_flock)); 112083221Smarcel 112199687Srobert case LINUX_F_SETLKW64: 1122111797Sdes error = copyin((void *)args->arg, &linux_flock, 112383221Smarcel sizeof(linux_flock)); 112483221Smarcel if (error) 112583221Smarcel return (error); 1126102872Siedowse linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1127102872Siedowse return (kern_fcntl(td, args->fd, F_SETLKW, 1128102872Siedowse (intptr_t)&bsd_flock)); 112983221Smarcel } 113083221Smarcel 113183366Sjulian return (fcntl_common(td, args)); 113283221Smarcel} 1133133816Stjr#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 113485022Smarcel 113585022Smarcelint 113685022Smarcellinux_chown(struct thread *td, struct linux_chown_args *args) 113785022Smarcel{ 1138102814Siedowse char *path; 1139102814Siedowse int error; 114085022Smarcel 1141102814Siedowse LCONVPATHEXIST(td, args->path, &path); 114285022Smarcel 114385022Smarcel#ifdef DEBUG 114485022Smarcel if (ldebug(chown)) 1145102814Siedowse printf(ARGS(chown, "%s, %d, %d"), path, args->uid, args->gid); 114685022Smarcel#endif 1147102814Siedowse error = kern_chown(td, path, UIO_SYSSPACE, args->uid, args->gid); 1148102814Siedowse LFREEPATH(path); 1149102814Siedowse return (error); 115085022Smarcel} 115185022Smarcel 115285022Smarcelint 115385022Smarcellinux_lchown(struct thread *td, struct linux_lchown_args *args) 115485022Smarcel{ 1155102814Siedowse char *path; 1156102814Siedowse int error; 115785022Smarcel 1158102814Siedowse LCONVPATHEXIST(td, args->path, &path); 115985022Smarcel 116085022Smarcel#ifdef DEBUG 116185022Smarcel if (ldebug(lchown)) 1162102814Siedowse printf(ARGS(lchown, "%s, %d, %d"), path, args->uid, args->gid); 116385022Smarcel#endif 1164102814Siedowse error = kern_lchown(td, path, UIO_SYSSPACE, args->uid, args->gid); 1165102814Siedowse LFREEPATH(path); 1166102814Siedowse return (error); 116785022Smarcel} 1168