linux_file.c revision 116678
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 116678 2003-06-22 08:41:43Z phk $"); 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 5764905Smarcel#include <machine/../linux/linux.h> 5868583Smarcel#include <machine/../linux/linux_proto.h> 5964905Smarcel#include <compat/linux/linux_util.h> 609313Ssos 6168201Sobrien#ifndef __alpha__ 629313Ssosint 6383366Sjulianlinux_creat(struct thread *td, struct linux_creat_args *args) 649313Ssos{ 65102814Siedowse char *path; 66102814Siedowse int error; 679313Ssos 68102814Siedowse LCONVPATHEXIST(td, args->path, &path); 6914331Speter 709313Ssos#ifdef DEBUG 7172543Sjlemon if (ldebug(creat)) 72102814Siedowse printf(ARGS(creat, "%s, %d"), path, args->mode); 739313Ssos#endif 74102814Siedowse error = kern_open(td, path, UIO_SYSSPACE, O_WRONLY | O_CREAT | O_TRUNC, 75102814Siedowse args->mode); 76102814Siedowse LFREEPATH(path); 77102814Siedowse return (error); 789313Ssos} 7968201Sobrien#endif /*!__alpha__*/ 809313Ssos 819313Ssosint 8283366Sjulianlinux_open(struct thread *td, struct linux_open_args *args) 839313Ssos{ 8483382Sjhb struct proc *p = td->td_proc; 85102814Siedowse char *path; 86102814Siedowse int bsd_flags, error; 8714331Speter 8814331Speter if (args->flags & LINUX_O_CREAT) 89102814Siedowse LCONVPATHCREAT(td, args->path, &path); 9014331Speter else 91102814Siedowse LCONVPATHEXIST(td, args->path, &path); 9214331Speter 939313Ssos#ifdef DEBUG 9472543Sjlemon if (ldebug(open)) 9572543Sjlemon printf(ARGS(open, "%s, 0x%x, 0x%x"), 96102814Siedowse path, args->flags, args->mode); 979313Ssos#endif 98102814Siedowse bsd_flags = 0; 999313Ssos if (args->flags & LINUX_O_RDONLY) 100102814Siedowse bsd_flags |= O_RDONLY; 101111798Sdes if (args->flags & LINUX_O_WRONLY) 102102814Siedowse bsd_flags |= O_WRONLY; 1039313Ssos if (args->flags & LINUX_O_RDWR) 104102814Siedowse bsd_flags |= O_RDWR; 1059313Ssos if (args->flags & LINUX_O_NDELAY) 106102814Siedowse bsd_flags |= O_NONBLOCK; 1079313Ssos if (args->flags & LINUX_O_APPEND) 108102814Siedowse bsd_flags |= O_APPEND; 1099313Ssos if (args->flags & LINUX_O_SYNC) 110102814Siedowse bsd_flags |= O_FSYNC; 1119313Ssos if (args->flags & LINUX_O_NONBLOCK) 112102814Siedowse bsd_flags |= O_NONBLOCK; 1139313Ssos if (args->flags & LINUX_FASYNC) 114102814Siedowse bsd_flags |= O_ASYNC; 1159313Ssos if (args->flags & LINUX_O_CREAT) 116102814Siedowse bsd_flags |= O_CREAT; 1179313Ssos if (args->flags & LINUX_O_TRUNC) 118102814Siedowse bsd_flags |= O_TRUNC; 1199313Ssos if (args->flags & LINUX_O_EXCL) 120102814Siedowse bsd_flags |= O_EXCL; 1219313Ssos if (args->flags & LINUX_O_NOCTTY) 122102814Siedowse bsd_flags |= O_NOCTTY; 1239313Ssos 124102814Siedowse error = kern_open(td, path, UIO_SYSSPACE, bsd_flags, args->mode); 12570061Sjhb PROC_LOCK(p); 126102814Siedowse if (!error && !(bsd_flags & O_NOCTTY) && 1279313Ssos SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 12889306Salfred struct file *fp; 1299313Ssos 130113917Sjhb PROC_UNLOCK(p); 13189319Salfred error = fget(td, td->td_retval[0], &fp); 13289319Salfred if (!error) { 13389319Salfred if (fp->f_type == DTYPE_VNODE) 134102003Srwatson fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred, 135102003Srwatson td); 13689319Salfred fdrop(fp, td); 13789319Salfred } 13891140Stanimura } else { 13970061Sjhb PROC_UNLOCK(p); 14014331Speter#ifdef DEBUG 14172543Sjlemon if (ldebug(open)) 14272543Sjlemon printf(LMSG("open returns error %d"), error); 14314331Speter#endif 14491140Stanimura } 145102814Siedowse LFREEPATH(path); 1469313Ssos return error; 1479313Ssos} 1489313Ssos 1499313Ssosint 15083366Sjulianlinux_lseek(struct thread *td, struct linux_lseek_args *args) 1519313Ssos{ 1529313Ssos 15312858Speter struct lseek_args /* { 15412858Speter int fd; 1559313Ssos int pad; 15612858Speter off_t offset; 1579313Ssos int whence; 15812858Speter } */ tmp_args; 1599313Ssos int error; 1609313Ssos 1619313Ssos#ifdef DEBUG 16272543Sjlemon if (ldebug(lseek)) 16372543Sjlemon printf(ARGS(lseek, "%d, %ld, %d"), 16483221Smarcel args->fdes, (long)args->off, args->whence); 1659313Ssos#endif 16612858Speter tmp_args.fd = args->fdes; 16712858Speter tmp_args.offset = (off_t)args->off; 1689313Ssos tmp_args.whence = args->whence; 16983366Sjulian error = lseek(td, &tmp_args); 1709313Ssos return error; 1719313Ssos} 1729313Ssos 17368201Sobrien#ifndef __alpha__ 17414331Speterint 17583366Sjulianlinux_llseek(struct thread *td, struct linux_llseek_args *args) 17614331Speter{ 17714331Speter struct lseek_args bsd_args; 17814331Speter int error; 17914331Speter off_t off; 18014331Speter 18114331Speter#ifdef DEBUG 18272543Sjlemon if (ldebug(llseek)) 18372543Sjlemon printf(ARGS(llseek, "%d, %d:%d, %d"), 18472543Sjlemon args->fd, args->ohigh, args->olow, args->whence); 18514331Speter#endif 18614331Speter off = (args->olow) | (((off_t) args->ohigh) << 32); 18714331Speter 18814331Speter bsd_args.fd = args->fd; 18914331Speter bsd_args.offset = off; 19014331Speter bsd_args.whence = args->whence; 19114331Speter 19283366Sjulian if ((error = lseek(td, &bsd_args))) 19314331Speter return error; 19414331Speter 195111797Sdes if ((error = copyout(td->td_retval, args->res, sizeof (off_t)))) 19614331Speter return error; 19714331Speter 19883366Sjulian td->td_retval[0] = 0; 19914331Speter return 0; 20014331Speter} 20168201Sobrien#endif /*!__alpha__*/ 20214331Speter 20368201Sobrien#ifndef __alpha__ 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} 21468201Sobrien#endif /*!__alpha__*/ 21514331Speter 21683221Smarcel/* 21783221Smarcel * Note that linux_getdents(2) and linux_getdents64(2) have the same 21883221Smarcel * arguments. They only differ in the definition of struct dirent they 21983221Smarcel * operate on. We use this to common the code, with the exception of 22083221Smarcel * accessing struct dirent. Note that linux_readdir(2) is implemented 22183221Smarcel * by means of linux_getdents(2). In this case we never operate on 22283221Smarcel * struct dirent64 and thus don't need to handle it... 22383221Smarcel */ 22483221Smarcel 22583221Smarcelstruct l_dirent { 22683221Smarcel l_long d_ino; 22783221Smarcel l_off_t d_off; 22883221Smarcel l_ushort d_reclen; 22983221Smarcel char d_name[LINUX_NAME_MAX + 1]; 23083221Smarcel}; 23183221Smarcel 23283221Smarcelstruct l_dirent64 { 23383221Smarcel uint64_t d_ino; 23483221Smarcel int64_t d_off; 23583221Smarcel l_ushort d_reclen; 23683221Smarcel u_char d_type; 23783221Smarcel char d_name[LINUX_NAME_MAX + 1]; 23883221Smarcel}; 23983221Smarcel 24083221Smarcel#define LINUX_RECLEN(de,namlen) \ 24183221Smarcel ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1)) 24283221Smarcel 24383221Smarcel#define LINUX_DIRBLKSIZ 512 24483221Smarcel 24583221Smarcelstatic int 24683366Sjuliangetdents_common(struct thread *td, struct linux_getdents64_args *args, 24783221Smarcel int is64bit) 24814331Speter{ 249111798Sdes struct dirent *bdp; 25083221Smarcel struct vnode *vp; 25183221Smarcel caddr_t inp, buf; /* BSD-format */ 25283221Smarcel int len, reclen; /* BSD-format */ 25383221Smarcel caddr_t outp; /* Linux-format */ 25483221Smarcel int resid, linuxreclen=0; /* Linux-format */ 25583221Smarcel struct file *fp; 25683221Smarcel struct uio auio; 25783221Smarcel struct iovec aiov; 25883221Smarcel struct vattr va; 25983221Smarcel off_t off; 26083221Smarcel struct l_dirent linux_dirent; 26183221Smarcel struct l_dirent64 linux_dirent64; 26283221Smarcel int buflen, error, eofflag, nbytes, justone; 26383221Smarcel u_long *cookies = NULL, *cookiep; 26483221Smarcel int ncookies; 2659313Ssos 26683366Sjulian if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0) 26783221Smarcel return (error); 2689313Ssos 26989306Salfred if ((fp->f_flag & FREAD) == 0) { 27089306Salfred fdrop(fp, td); 27183221Smarcel return (EBADF); 27289306Salfred } 2739313Ssos 274116678Sphk vp = fp->f_vnode; 27589306Salfred if (vp->v_type != VDIR) { 27689306Salfred fdrop(fp, td); 27783221Smarcel return (EINVAL); 27889306Salfred } 2799313Ssos 28091406Sjhb if ((error = VOP_GETATTR(vp, &va, td->td_ucred, td))) { 28189306Salfred fdrop(fp, td); 28283221Smarcel return (error); 28389306Salfred } 2849313Ssos 28583221Smarcel nbytes = args->count; 28683221Smarcel if (nbytes == 1) { 28783221Smarcel /* readdir(2) case. Always struct dirent. */ 28889306Salfred if (is64bit) { 28989306Salfred fdrop(fp, td); 29083221Smarcel return (EINVAL); 29189306Salfred } 29283221Smarcel nbytes = sizeof(linux_dirent); 29383221Smarcel justone = 1; 29483221Smarcel } else 29583221Smarcel justone = 0; 2969313Ssos 29783221Smarcel off = fp->f_offset; 2989313Ssos 29983221Smarcel buflen = max(LINUX_DIRBLKSIZ, nbytes); 30083221Smarcel buflen = min(buflen, MAXBSIZE); 301111119Simp buf = malloc(buflen, M_TEMP, M_WAITOK); 30283366Sjulian vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 30383221Smarcel 3049313Ssosagain: 30583221Smarcel aiov.iov_base = buf; 30683221Smarcel aiov.iov_len = buflen; 30783221Smarcel auio.uio_iov = &aiov; 30883221Smarcel auio.uio_iovcnt = 1; 30983221Smarcel auio.uio_rw = UIO_READ; 31083221Smarcel auio.uio_segflg = UIO_SYSSPACE; 31183366Sjulian auio.uio_td = td; 31283221Smarcel auio.uio_resid = buflen; 31383221Smarcel auio.uio_offset = off; 3149313Ssos 31583221Smarcel if (cookies) { 31683221Smarcel free(cookies, M_TEMP); 31783221Smarcel cookies = NULL; 31883221Smarcel } 31924654Sdfr 320101189Srwatson#ifdef MAC 321101189Srwatson /* 322101189Srwatson * Do directory search MAC check using non-cached credentials. 323101189Srwatson */ 324112451Sjhb if ((error = mac_check_vnode_readdir(td->td_ucred, vp))) 325101189Srwatson goto out; 326101189Srwatson#endif /* MAC */ 32783221Smarcel if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, 32883221Smarcel &cookies))) 32983221Smarcel goto out; 3309313Ssos 33183221Smarcel inp = buf; 33283221Smarcel outp = (caddr_t)args->dirent; 33383221Smarcel resid = nbytes; 33483221Smarcel if ((len = buflen - auio.uio_resid) <= 0) 33583221Smarcel goto eof; 3369313Ssos 33783221Smarcel cookiep = cookies; 33824654Sdfr 33983221Smarcel if (cookies) { 34083221Smarcel /* 34183221Smarcel * When using cookies, the vfs has the option of reading from 34283221Smarcel * a different offset than that supplied (UFS truncates the 34383221Smarcel * offset to a block boundary to make sure that it never reads 34483221Smarcel * partway through a directory entry, even if the directory 34583221Smarcel * has been compacted). 34683221Smarcel */ 34783221Smarcel while (len > 0 && ncookies > 0 && *cookiep <= off) { 34883221Smarcel bdp = (struct dirent *) inp; 34983221Smarcel len -= bdp->d_reclen; 35083221Smarcel inp += bdp->d_reclen; 35183221Smarcel cookiep++; 35283221Smarcel ncookies--; 35383221Smarcel } 35424654Sdfr } 35524654Sdfr 35683221Smarcel while (len > 0) { 35783221Smarcel if (cookiep && ncookies == 0) 35883221Smarcel break; 35983221Smarcel bdp = (struct dirent *) inp; 36083221Smarcel reclen = bdp->d_reclen; 36183221Smarcel if (reclen & 3) { 36283221Smarcel error = EFAULT; 36383221Smarcel goto out; 36483221Smarcel } 36583221Smarcel 36683221Smarcel if (bdp->d_fileno == 0) { 36783221Smarcel inp += reclen; 36883221Smarcel if (cookiep) { 36983221Smarcel off = *cookiep++; 37083221Smarcel ncookies--; 37183221Smarcel } else 37283221Smarcel off += reclen; 37383221Smarcel 37483221Smarcel len -= reclen; 37583221Smarcel continue; 37683221Smarcel } 37783221Smarcel 37883221Smarcel linuxreclen = (is64bit) 37983221Smarcel ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen) 38083221Smarcel : LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 38183221Smarcel 38283221Smarcel if (reclen > len || resid < linuxreclen) { 38383221Smarcel outp++; 38483221Smarcel break; 38583221Smarcel } 38683221Smarcel 38783221Smarcel if (justone) { 38883221Smarcel /* readdir(2) case. */ 38983221Smarcel linux_dirent.d_ino = (l_long)bdp->d_fileno; 39083221Smarcel linux_dirent.d_off = (l_off_t)linuxreclen; 39183221Smarcel linux_dirent.d_reclen = (l_ushort)bdp->d_namlen; 39283221Smarcel strcpy(linux_dirent.d_name, bdp->d_name); 39383221Smarcel error = copyout(&linux_dirent, outp, linuxreclen); 39483221Smarcel } else { 39583221Smarcel if (is64bit) { 39683221Smarcel linux_dirent64.d_ino = bdp->d_fileno; 39783221Smarcel linux_dirent64.d_off = (cookiep) 39883221Smarcel ? (l_off_t)*cookiep 39983221Smarcel : (l_off_t)(off + reclen); 40083221Smarcel linux_dirent64.d_reclen = 40183221Smarcel (l_ushort)linuxreclen; 40283221Smarcel linux_dirent64.d_type = bdp->d_type; 40383221Smarcel strcpy(linux_dirent64.d_name, bdp->d_name); 40483221Smarcel error = copyout(&linux_dirent64, outp, 40583221Smarcel linuxreclen); 40683221Smarcel } else { 40783221Smarcel linux_dirent.d_ino = bdp->d_fileno; 40883221Smarcel linux_dirent.d_off = (cookiep) 40983221Smarcel ? (l_off_t)*cookiep 41083221Smarcel : (l_off_t)(off + reclen); 41183221Smarcel linux_dirent.d_reclen = (l_ushort)linuxreclen; 41283221Smarcel strcpy(linux_dirent.d_name, bdp->d_name); 41383221Smarcel error = copyout(&linux_dirent, outp, 41483221Smarcel linuxreclen); 41583221Smarcel } 41683221Smarcel } 41783221Smarcel if (error) 41883221Smarcel goto out; 41983221Smarcel 42083221Smarcel inp += reclen; 42183221Smarcel if (cookiep) { 42283221Smarcel off = *cookiep++; 42383221Smarcel ncookies--; 42483221Smarcel } else 42583221Smarcel off += reclen; 42683221Smarcel 42783221Smarcel outp += linuxreclen; 42883221Smarcel resid -= linuxreclen; 42983221Smarcel len -= reclen; 43083221Smarcel if (justone) 43183221Smarcel break; 43210355Sswallace } 4339313Ssos 43483221Smarcel if (outp == (caddr_t)args->dirent) 43583221Smarcel goto again; 4369313Ssos 43783221Smarcel fp->f_offset = off; 43883221Smarcel if (justone) 43983221Smarcel nbytes = resid + linuxreclen; 44010355Sswallace 4419313Ssoseof: 44283366Sjulian td->td_retval[0] = nbytes - resid; 44383221Smarcel 4449313Ssosout: 44583221Smarcel if (cookies) 44683221Smarcel free(cookies, M_TEMP); 44783221Smarcel 44883366Sjulian VOP_UNLOCK(vp, 0, td); 44989306Salfred fdrop(fp, td); 45083221Smarcel free(buf, M_TEMP); 45183221Smarcel return (error); 4529313Ssos} 45314331Speter 45483221Smarcelint 45583366Sjulianlinux_getdents(struct thread *td, struct linux_getdents_args *args) 45683221Smarcel{ 45783221Smarcel 45883221Smarcel#ifdef DEBUG 45983221Smarcel if (ldebug(getdents)) 46083221Smarcel printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count); 46183221Smarcel#endif 46283221Smarcel 46383366Sjulian return (getdents_common(td, (struct linux_getdents64_args*)args, 0)); 46483221Smarcel} 46583221Smarcel 46683221Smarcelint 46783366Sjulianlinux_getdents64(struct thread *td, struct linux_getdents64_args *args) 46883221Smarcel{ 46983221Smarcel 47083221Smarcel#ifdef DEBUG 47183221Smarcel if (ldebug(getdents64)) 47283221Smarcel printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count); 47383221Smarcel#endif 47483221Smarcel 47583366Sjulian return (getdents_common(td, args, 1)); 47683221Smarcel} 47783221Smarcel 47814331Speter/* 47914331Speter * These exist mainly for hooks for doing /compat/linux translation. 48014331Speter */ 48114331Speter 48214331Speterint 48383366Sjulianlinux_access(struct thread *td, struct linux_access_args *args) 48414331Speter{ 485102814Siedowse char *path; 486102814Siedowse int error; 48714331Speter 488102814Siedowse LCONVPATHEXIST(td, args->path, &path); 48914331Speter 49014331Speter#ifdef DEBUG 49172543Sjlemon if (ldebug(access)) 492102814Siedowse printf(ARGS(access, "%s, %d"), path, args->flags); 49314331Speter#endif 494102814Siedowse error = kern_access(td, path, UIO_SYSSPACE, args->flags); 495102814Siedowse LFREEPATH(path); 496102814Siedowse return (error); 49714331Speter} 49814331Speter 49914331Speterint 50083366Sjulianlinux_unlink(struct thread *td, struct linux_unlink_args *args) 50114331Speter{ 502102814Siedowse char *path; 503102814Siedowse int error; 50414331Speter 505102814Siedowse LCONVPATHEXIST(td, args->path, &path); 50614331Speter 50714331Speter#ifdef DEBUG 50872543Sjlemon if (ldebug(unlink)) 509102814Siedowse printf(ARGS(unlink, "%s"), path); 51014331Speter#endif 51114331Speter 512102814Siedowse error = kern_unlink(td, path, UIO_SYSSPACE); 513102814Siedowse LFREEPATH(path); 514102814Siedowse return (error); 51514331Speter} 51614331Speter 51714331Speterint 51883366Sjulianlinux_chdir(struct thread *td, struct linux_chdir_args *args) 51914331Speter{ 520102814Siedowse char *path; 521102814Siedowse int error; 52214331Speter 523102814Siedowse LCONVPATHEXIST(td, args->path, &path); 52414331Speter 52514331Speter#ifdef DEBUG 52672543Sjlemon if (ldebug(chdir)) 527102814Siedowse printf(ARGS(chdir, "%s"), path); 52814331Speter#endif 529102814Siedowse error = kern_chdir(td, path, UIO_SYSSPACE); 530102814Siedowse LFREEPATH(path); 531102814Siedowse return (error); 53214331Speter} 53314331Speter 53414331Speterint 53583366Sjulianlinux_chmod(struct thread *td, struct linux_chmod_args *args) 53614331Speter{ 537102814Siedowse char *path; 538102814Siedowse int error; 53914331Speter 540102814Siedowse LCONVPATHEXIST(td, args->path, &path); 54114331Speter 54214331Speter#ifdef DEBUG 54372543Sjlemon if (ldebug(chmod)) 544102814Siedowse printf(ARGS(chmod, "%s, %d"), path, args->mode); 54514331Speter#endif 546102814Siedowse error = kern_chmod(td, path, UIO_SYSSPACE, args->mode); 547102814Siedowse LFREEPATH(path); 548102814Siedowse return (error); 54914331Speter} 55014331Speter 55114331Speterint 55283366Sjulianlinux_mkdir(struct thread *td, struct linux_mkdir_args *args) 55314331Speter{ 554102814Siedowse char *path; 555102814Siedowse int error; 55614331Speter 557102814Siedowse LCONVPATHCREAT(td, args->path, &path); 55814331Speter 55914331Speter#ifdef DEBUG 56072543Sjlemon if (ldebug(mkdir)) 561102814Siedowse printf(ARGS(mkdir, "%s, %d"), path, args->mode); 56214331Speter#endif 563102814Siedowse error = kern_mkdir(td, path, UIO_SYSSPACE, args->mode); 564102814Siedowse LFREEPATH(path); 565102814Siedowse return (error); 56614331Speter} 56714331Speter 56814331Speterint 56983366Sjulianlinux_rmdir(struct thread *td, struct linux_rmdir_args *args) 57014331Speter{ 571102814Siedowse char *path; 572102814Siedowse int error; 57314331Speter 574102814Siedowse LCONVPATHEXIST(td, args->path, &path); 57514331Speter 57614331Speter#ifdef DEBUG 57772543Sjlemon if (ldebug(rmdir)) 578102814Siedowse printf(ARGS(rmdir, "%s"), path); 57914331Speter#endif 580102814Siedowse error = kern_rmdir(td, path, UIO_SYSSPACE); 581102814Siedowse LFREEPATH(path); 582102814Siedowse return (error); 58314331Speter} 58414331Speter 58514331Speterint 58683366Sjulianlinux_rename(struct thread *td, struct linux_rename_args *args) 58714331Speter{ 588102814Siedowse char *from, *to; 589102814Siedowse int error; 59014331Speter 591102814Siedowse LCONVPATHEXIST(td, args->from, &from); 592102814Siedowse /* Expand LCONVPATHCREATE so that `from' can be freed on errors */ 593102814Siedowse error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); 594102814Siedowse if (to == NULL) { 595102814Siedowse LFREEPATH(from); 596102814Siedowse return (error); 597102814Siedowse } 59814331Speter 59914331Speter#ifdef DEBUG 60072543Sjlemon if (ldebug(rename)) 601102814Siedowse printf(ARGS(rename, "%s, %s"), from, to); 60214331Speter#endif 603102814Siedowse error = kern_rename(td, from, to, UIO_SYSSPACE); 604102814Siedowse LFREEPATH(from); 605102814Siedowse LFREEPATH(to); 606102814Siedowse return (error); 60714331Speter} 60814331Speter 60914331Speterint 61083366Sjulianlinux_symlink(struct thread *td, struct linux_symlink_args *args) 61114331Speter{ 612102814Siedowse char *path, *to; 613102814Siedowse int error; 61414331Speter 615102814Siedowse LCONVPATHEXIST(td, args->path, &path); 616102814Siedowse /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 617102814Siedowse error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); 618102814Siedowse if (to == NULL) { 619102814Siedowse LFREEPATH(path); 620102814Siedowse return (error); 621102814Siedowse } 62214331Speter 62314331Speter#ifdef DEBUG 62472543Sjlemon if (ldebug(symlink)) 625102814Siedowse printf(ARGS(symlink, "%s, %s"), path, to); 62614331Speter#endif 627102814Siedowse error = kern_symlink(td, path, to, UIO_SYSSPACE); 628102814Siedowse LFREEPATH(path); 629102814Siedowse LFREEPATH(to); 630102814Siedowse return (error); 63114331Speter} 63214331Speter 63314331Speterint 63483366Sjulianlinux_readlink(struct thread *td, struct linux_readlink_args *args) 63514331Speter{ 636102814Siedowse char *name; 637102814Siedowse int error; 63814331Speter 639102814Siedowse LCONVPATHEXIST(td, args->name, &name); 64014331Speter 64114331Speter#ifdef DEBUG 64272543Sjlemon if (ldebug(readlink)) 643102814Siedowse printf(ARGS(readlink, "%s, %p, %d"), name, (void *)args->buf, 644102814Siedowse args->count); 64514331Speter#endif 646102814Siedowse error = kern_readlink(td, name, UIO_SYSSPACE, args->buf, UIO_USERSPACE, 647102814Siedowse args->count); 648102814Siedowse LFREEPATH(name); 649102814Siedowse return (error); 65014331Speter} 65114331Speter 65214331Speterint 65383366Sjulianlinux_truncate(struct thread *td, struct linux_truncate_args *args) 65414331Speter{ 655102814Siedowse char *path; 656102814Siedowse int error; 65714331Speter 658102814Siedowse LCONVPATHEXIST(td, args->path, &path); 65914331Speter 66014331Speter#ifdef DEBUG 66172543Sjlemon if (ldebug(truncate)) 662102814Siedowse printf(ARGS(truncate, "%s, %ld"), path, (long)args->length); 66314331Speter#endif 66414331Speter 665102814Siedowse error = kern_truncate(td, path, UIO_SYSSPACE, args->length); 666102814Siedowse LFREEPATH(path); 667102814Siedowse return (error); 66814331Speter} 66914331Speter 67049662Smarcelint 67183366Sjulianlinux_link(struct thread *td, struct linux_link_args *args) 67249662Smarcel{ 673102814Siedowse char *path, *to; 674102814Siedowse int error; 67549662Smarcel 676102814Siedowse LCONVPATHEXIST(td, args->path, &path); 677102814Siedowse /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 678102814Siedowse error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); 679102814Siedowse if (to == NULL) { 680102814Siedowse LFREEPATH(path); 681102814Siedowse return (error); 682102814Siedowse } 68349662Smarcel 68449662Smarcel#ifdef DEBUG 68572543Sjlemon if (ldebug(link)) 686102814Siedowse printf(ARGS(link, "%s, %s"), path, to); 68749662Smarcel#endif 688102814Siedowse error = kern_link(td, path, to, UIO_SYSSPACE); 689102814Siedowse LFREEPATH(path); 690102814Siedowse LFREEPATH(to); 691102814Siedowse return (error); 69249662Smarcel} 69349788Smarcel 69468201Sobrien#ifndef __alpha__ 69553713Smarcelint 69683366Sjulianlinux_fdatasync(td, uap) 69783366Sjulian struct thread *td; 69853713Smarcel struct linux_fdatasync_args *uap; 69953713Smarcel{ 70053713Smarcel struct fsync_args bsd; 70153713Smarcel 70253713Smarcel bsd.fd = uap->fd; 70383366Sjulian return fsync(td, &bsd); 70453713Smarcel} 70568201Sobrien#endif /*!__alpha__*/ 70663285Smarcel 70763285Smarcelint 70883366Sjulianlinux_pread(td, uap) 70983366Sjulian struct thread *td; 71063285Smarcel struct linux_pread_args *uap; 71163285Smarcel{ 71263285Smarcel struct pread_args bsd; 71363285Smarcel 71463285Smarcel bsd.fd = uap->fd; 71563285Smarcel bsd.buf = uap->buf; 71663285Smarcel bsd.nbyte = uap->nbyte; 71763285Smarcel bsd.offset = uap->offset; 71883366Sjulian return pread(td, &bsd); 71963285Smarcel} 72063285Smarcel 72163285Smarcelint 72283366Sjulianlinux_pwrite(td, uap) 72383366Sjulian struct thread *td; 72463285Smarcel struct linux_pwrite_args *uap; 72563285Smarcel{ 72663285Smarcel struct pwrite_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 pwrite(td, &bsd); 73363285Smarcel} 73472538Sjlemon 73572538Sjlemonint 73683366Sjulianlinux_mount(struct thread *td, struct linux_mount_args *args) 73772538Sjlemon{ 73872538Sjlemon struct ufs_args ufs; 739111798Sdes char fstypename[MFSNAMELEN]; 740111798Sdes char mntonname[MNAMELEN], mntfromname[MNAMELEN]; 74173286Sadrian int error; 74273286Sadrian int fsflags; 74373286Sadrian const char *fstype; 74473286Sadrian void *fsdata; 74572538Sjlemon 746111798Sdes error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1, 74773286Sadrian NULL); 74872538Sjlemon if (error) 749111798Sdes return (error); 750111798Sdes error = copyinstr(args->specialfile, mntfromname, MFSNAMELEN - 1, NULL); 75172538Sjlemon if (error) 752111798Sdes return (error); 753111798Sdes error = copyinstr(args->dir, mntonname, MFSNAMELEN - 1, NULL); 75472538Sjlemon if (error) 755111798Sdes return (error); 75672538Sjlemon 75772538Sjlemon#ifdef DEBUG 75872538Sjlemon if (ldebug(mount)) 75972538Sjlemon printf(ARGS(mount, "%s, %s, %s"), 76072538Sjlemon fstypename, mntfromname, mntonname); 76172538Sjlemon#endif 76272538Sjlemon 76372538Sjlemon if (strcmp(fstypename, "ext2") == 0) { 76473286Sadrian fstype = "ext2fs"; 76573286Sadrian fsdata = &ufs; 76672538Sjlemon ufs.fspec = mntfromname; 76772538Sjlemon#define DEFAULT_ROOTID -2 76872538Sjlemon ufs.export.ex_root = DEFAULT_ROOTID; 76972538Sjlemon ufs.export.ex_flags = 77072538Sjlemon args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0; 77172538Sjlemon } else if (strcmp(fstypename, "proc") == 0) { 77273286Sadrian fstype = "linprocfs"; 77373286Sadrian fsdata = NULL; 77472538Sjlemon } else { 77572538Sjlemon return (ENODEV); 77672538Sjlemon } 77772538Sjlemon 77873286Sadrian fsflags = 0; 77972538Sjlemon 78072538Sjlemon if ((args->rwflag & 0xffff0000) == 0xc0ed0000) { 78172538Sjlemon /* 78272538Sjlemon * Linux SYNC flag is not included; the closest equivalent 78372538Sjlemon * FreeBSD has is !ASYNC, which is our default. 78472538Sjlemon */ 78572538Sjlemon if (args->rwflag & LINUX_MS_RDONLY) 786111798Sdes fsflags |= MNT_RDONLY; 78772538Sjlemon if (args->rwflag & LINUX_MS_NOSUID) 788111798Sdes fsflags |= MNT_NOSUID; 78972538Sjlemon if (args->rwflag & LINUX_MS_NODEV) 790111798Sdes fsflags |= MNT_NODEV; 79172538Sjlemon if (args->rwflag & LINUX_MS_NOEXEC) 792111798Sdes fsflags |= MNT_NOEXEC; 79372538Sjlemon if (args->rwflag & LINUX_MS_REMOUNT) 794111798Sdes fsflags |= MNT_UPDATE; 79572538Sjlemon } 79672538Sjlemon 79783366Sjulian return (vfs_mount(td, fstype, mntonname, fsflags, fsdata)); 79872538Sjlemon} 79972538Sjlemon 80072538Sjlemonint 80183366Sjulianlinux_oldumount(struct thread *td, struct linux_oldumount_args *args) 80272538Sjlemon{ 80383221Smarcel struct linux_umount_args args2; 80472538Sjlemon 80572538Sjlemon args2.path = args->path; 80672538Sjlemon args2.flags = 0; 80783366Sjulian return (linux_umount(td, &args2)); 80872538Sjlemon} 80972538Sjlemon 81072538Sjlemonint 81183366Sjulianlinux_umount(struct thread *td, struct linux_umount_args *args) 81272538Sjlemon{ 81372538Sjlemon struct unmount_args bsd; 81472538Sjlemon 81572538Sjlemon bsd.path = args->path; 81672538Sjlemon bsd.flags = args->flags; /* XXX correct? */ 81783366Sjulian return (unmount(td, &bsd)); 81872538Sjlemon} 81983221Smarcel 82083221Smarcel/* 82183221Smarcel * fcntl family of syscalls 82283221Smarcel */ 82383221Smarcel 82483221Smarcelstruct l_flock { 82583221Smarcel l_short l_type; 82683221Smarcel l_short l_whence; 82783221Smarcel l_off_t l_start; 82883221Smarcel l_off_t l_len; 82983221Smarcel l_pid_t l_pid; 83083221Smarcel}; 83183221Smarcel 83283221Smarcelstatic void 83383221Smarcellinux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock) 83483221Smarcel{ 83583221Smarcel switch (linux_flock->l_type) { 83683221Smarcel case LINUX_F_RDLCK: 83783221Smarcel bsd_flock->l_type = F_RDLCK; 83883221Smarcel break; 83983221Smarcel case LINUX_F_WRLCK: 84083221Smarcel bsd_flock->l_type = F_WRLCK; 84183221Smarcel break; 84283221Smarcel case LINUX_F_UNLCK: 84383221Smarcel bsd_flock->l_type = F_UNLCK; 84483221Smarcel break; 84583221Smarcel default: 84683221Smarcel bsd_flock->l_type = -1; 84783221Smarcel break; 84883221Smarcel } 84983221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 85083221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 85183221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 85283221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 85383221Smarcel} 85483221Smarcel 85583221Smarcelstatic void 85683221Smarcelbsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock) 85783221Smarcel{ 85883221Smarcel switch (bsd_flock->l_type) { 85983221Smarcel case F_RDLCK: 86083221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 86183221Smarcel break; 86283221Smarcel case F_WRLCK: 86383221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 86483221Smarcel break; 86583221Smarcel case F_UNLCK: 86683221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 86783221Smarcel break; 86883221Smarcel } 86983221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 87083221Smarcel linux_flock->l_start = (l_off_t)bsd_flock->l_start; 87183221Smarcel linux_flock->l_len = (l_off_t)bsd_flock->l_len; 87283221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 87383221Smarcel} 87483221Smarcel 87583221Smarcel#if defined(__i386__) 87683221Smarcelstruct l_flock64 { 87783221Smarcel l_short l_type; 87883221Smarcel l_short l_whence; 87983221Smarcel l_loff_t l_start; 88083221Smarcel l_loff_t l_len; 88183221Smarcel l_pid_t l_pid; 88283221Smarcel}; 88383221Smarcel 88483221Smarcelstatic void 88583221Smarcellinux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock) 88683221Smarcel{ 88783221Smarcel switch (linux_flock->l_type) { 88883221Smarcel case LINUX_F_RDLCK: 88983221Smarcel bsd_flock->l_type = F_RDLCK; 89083221Smarcel break; 89183221Smarcel case LINUX_F_WRLCK: 89283221Smarcel bsd_flock->l_type = F_WRLCK; 89383221Smarcel break; 89483221Smarcel case LINUX_F_UNLCK: 89583221Smarcel bsd_flock->l_type = F_UNLCK; 89683221Smarcel break; 89783221Smarcel default: 89883221Smarcel bsd_flock->l_type = -1; 89983221Smarcel break; 90083221Smarcel } 90183221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 90283221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 90383221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 90483221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 90583221Smarcel} 90683221Smarcel 90783221Smarcelstatic void 90883221Smarcelbsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) 90983221Smarcel{ 91083221Smarcel switch (bsd_flock->l_type) { 91183221Smarcel case F_RDLCK: 91283221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 91383221Smarcel break; 91483221Smarcel case F_WRLCK: 91583221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 91683221Smarcel break; 91783221Smarcel case F_UNLCK: 91883221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 91983221Smarcel break; 92083221Smarcel } 92183221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 92283221Smarcel linux_flock->l_start = (l_loff_t)bsd_flock->l_start; 92383221Smarcel linux_flock->l_len = (l_loff_t)bsd_flock->l_len; 92483221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 92583221Smarcel} 92683221Smarcel#endif /* __i386__ */ 92783221Smarcel 92883221Smarcel#if defined(__alpha__) 92983221Smarcel#define linux_fcntl64_args linux_fcntl_args 93083221Smarcel#endif 93183221Smarcel 93283221Smarcelstatic int 93383366Sjulianfcntl_common(struct thread *td, struct linux_fcntl64_args *args) 93483221Smarcel{ 935107680Siedowse struct l_flock linux_flock; 936107680Siedowse struct flock bsd_flock; 93783221Smarcel struct file *fp; 938102872Siedowse long arg; 93983221Smarcel int error, result; 94083221Smarcel 94183221Smarcel switch (args->cmd) { 94283221Smarcel case LINUX_F_DUPFD: 943102872Siedowse return (kern_fcntl(td, args->fd, F_DUPFD, args->arg)); 94483221Smarcel 94583221Smarcel case LINUX_F_GETFD: 946102872Siedowse return (kern_fcntl(td, args->fd, F_GETFD, 0)); 94783221Smarcel 94883221Smarcel case LINUX_F_SETFD: 949102872Siedowse return (kern_fcntl(td, args->fd, F_SETFD, args->arg)); 95083221Smarcel 95183221Smarcel case LINUX_F_GETFL: 952102872Siedowse error = kern_fcntl(td, args->fd, F_GETFL, 0); 95383366Sjulian result = td->td_retval[0]; 95483366Sjulian td->td_retval[0] = 0; 95583221Smarcel if (result & O_RDONLY) 95683366Sjulian td->td_retval[0] |= LINUX_O_RDONLY; 95783221Smarcel if (result & O_WRONLY) 95883366Sjulian td->td_retval[0] |= LINUX_O_WRONLY; 95983221Smarcel if (result & O_RDWR) 96083366Sjulian td->td_retval[0] |= LINUX_O_RDWR; 96183221Smarcel if (result & O_NDELAY) 96283366Sjulian td->td_retval[0] |= LINUX_O_NONBLOCK; 96383221Smarcel if (result & O_APPEND) 96483366Sjulian td->td_retval[0] |= LINUX_O_APPEND; 96583221Smarcel if (result & O_FSYNC) 96683366Sjulian td->td_retval[0] |= LINUX_O_SYNC; 96783221Smarcel if (result & O_ASYNC) 96883366Sjulian td->td_retval[0] |= LINUX_FASYNC; 96983221Smarcel return (error); 97083221Smarcel 97183221Smarcel case LINUX_F_SETFL: 972102872Siedowse arg = 0; 97383221Smarcel if (args->arg & LINUX_O_NDELAY) 974102872Siedowse arg |= O_NONBLOCK; 97583221Smarcel if (args->arg & LINUX_O_APPEND) 976102872Siedowse arg |= O_APPEND; 97783221Smarcel if (args->arg & LINUX_O_SYNC) 978102872Siedowse arg |= O_FSYNC; 97983221Smarcel if (args->arg & LINUX_FASYNC) 980102872Siedowse arg |= O_ASYNC; 981102872Siedowse return (kern_fcntl(td, args->fd, F_SETFL, arg)); 98283221Smarcel 983107680Siedowse case LINUX_F_GETLK: 984111797Sdes error = copyin((void *)args->arg, &linux_flock, 985107680Siedowse sizeof(linux_flock)); 986107680Siedowse if (error) 987107680Siedowse return (error); 988107680Siedowse linux_to_bsd_flock(&linux_flock, &bsd_flock); 989107680Siedowse error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); 990107680Siedowse if (error) 991107680Siedowse return (error); 992107680Siedowse bsd_to_linux_flock(&bsd_flock, &linux_flock); 993111797Sdes return (copyout(&linux_flock, (void *)args->arg, 994107680Siedowse sizeof(linux_flock))); 995107680Siedowse 996107680Siedowse case LINUX_F_SETLK: 997111797Sdes error = copyin((void *)args->arg, &linux_flock, 998107680Siedowse sizeof(linux_flock)); 999107680Siedowse if (error) 1000107680Siedowse return (error); 1001107680Siedowse linux_to_bsd_flock(&linux_flock, &bsd_flock); 1002107680Siedowse return (kern_fcntl(td, args->fd, F_SETLK, 1003107680Siedowse (intptr_t)&bsd_flock)); 1004107680Siedowse 1005107680Siedowse case LINUX_F_SETLKW: 1006111797Sdes error = copyin((void *)args->arg, &linux_flock, 1007107680Siedowse sizeof(linux_flock)); 1008107680Siedowse if (error) 1009107680Siedowse return (error); 1010107680Siedowse linux_to_bsd_flock(&linux_flock, &bsd_flock); 1011107680Siedowse return (kern_fcntl(td, args->fd, F_SETLKW, 1012107680Siedowse (intptr_t)&bsd_flock)); 1013107680Siedowse 101483221Smarcel case LINUX_F_GETOWN: 1015102872Siedowse return (kern_fcntl(td, args->fd, F_GETOWN, 0)); 101683221Smarcel 101783221Smarcel case LINUX_F_SETOWN: 101883221Smarcel /* 101983221Smarcel * XXX some Linux applications depend on F_SETOWN having no 102083221Smarcel * significant effect for pipes (SIGIO is not delivered for 102183221Smarcel * pipes under Linux-2.2.35 at least). 102283221Smarcel */ 102389319Salfred error = fget(td, args->fd, &fp); 102489319Salfred if (error) 102589319Salfred return (error); 102689306Salfred if (fp->f_type == DTYPE_PIPE) { 102789306Salfred fdrop(fp, td); 102883221Smarcel return (EINVAL); 102989306Salfred } 103089306Salfred fdrop(fp, td); 103183221Smarcel 1032102872Siedowse return (kern_fcntl(td, args->fd, F_SETOWN, args->arg)); 103383221Smarcel } 103483221Smarcel 103583221Smarcel return (EINVAL); 103683221Smarcel} 103783221Smarcel 103883221Smarcelint 103983366Sjulianlinux_fcntl(struct thread *td, struct linux_fcntl_args *args) 104083221Smarcel{ 104183221Smarcel struct linux_fcntl64_args args64; 104283221Smarcel 104383221Smarcel#ifdef DEBUG 104483221Smarcel if (ldebug(fcntl)) 104583221Smarcel printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); 104683221Smarcel#endif 104783221Smarcel 104883221Smarcel args64.fd = args->fd; 104983221Smarcel args64.cmd = args->cmd; 105083221Smarcel args64.arg = args->arg; 105183366Sjulian return (fcntl_common(td, &args64)); 105283221Smarcel} 105383221Smarcel 105483221Smarcel#if defined(__i386__) 105583221Smarcelint 105683366Sjulianlinux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) 105783221Smarcel{ 105883221Smarcel struct l_flock64 linux_flock; 1059102872Siedowse struct flock bsd_flock; 106083221Smarcel int error; 106183221Smarcel 106283221Smarcel#ifdef DEBUG 106383221Smarcel if (ldebug(fcntl64)) 106483221Smarcel printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd); 106583221Smarcel#endif 106683221Smarcel 106783221Smarcel switch (args->cmd) { 106899687Srobert case LINUX_F_GETLK64: 1069111797Sdes error = copyin((void *)args->arg, &linux_flock, 107083221Smarcel sizeof(linux_flock)); 107183221Smarcel if (error) 107283221Smarcel return (error); 1073102872Siedowse linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1074102872Siedowse error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); 107583221Smarcel if (error) 107683221Smarcel return (error); 1077102872Siedowse bsd_to_linux_flock64(&bsd_flock, &linux_flock); 1078111797Sdes return (copyout(&linux_flock, (void *)args->arg, 1079111797Sdes sizeof(linux_flock))); 108083221Smarcel 108199687Srobert case LINUX_F_SETLK64: 1082111797Sdes error = copyin((void *)args->arg, &linux_flock, 108383221Smarcel sizeof(linux_flock)); 108483221Smarcel if (error) 108583221Smarcel return (error); 1086102872Siedowse linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1087102872Siedowse return (kern_fcntl(td, args->fd, F_SETLK, 1088102872Siedowse (intptr_t)&bsd_flock)); 108983221Smarcel 109099687Srobert case LINUX_F_SETLKW64: 1091111797Sdes error = copyin((void *)args->arg, &linux_flock, 109283221Smarcel sizeof(linux_flock)); 109383221Smarcel if (error) 109483221Smarcel return (error); 1095102872Siedowse linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1096102872Siedowse return (kern_fcntl(td, args->fd, F_SETLKW, 1097102872Siedowse (intptr_t)&bsd_flock)); 109883221Smarcel } 109983221Smarcel 110083366Sjulian return (fcntl_common(td, args)); 110183221Smarcel} 110283221Smarcel#endif /* __i386__ */ 110385022Smarcel 110485022Smarcelint 110585022Smarcellinux_chown(struct thread *td, struct linux_chown_args *args) 110685022Smarcel{ 1107102814Siedowse char *path; 1108102814Siedowse int error; 110985022Smarcel 1110102814Siedowse LCONVPATHEXIST(td, args->path, &path); 111185022Smarcel 111285022Smarcel#ifdef DEBUG 111385022Smarcel if (ldebug(chown)) 1114102814Siedowse printf(ARGS(chown, "%s, %d, %d"), path, args->uid, args->gid); 111585022Smarcel#endif 1116102814Siedowse error = kern_chown(td, path, UIO_SYSSPACE, args->uid, args->gid); 1117102814Siedowse LFREEPATH(path); 1118102814Siedowse return (error); 111985022Smarcel} 112085022Smarcel 112185022Smarcelint 112285022Smarcellinux_lchown(struct thread *td, struct linux_lchown_args *args) 112385022Smarcel{ 1124102814Siedowse char *path; 1125102814Siedowse int error; 112685022Smarcel 1127102814Siedowse LCONVPATHEXIST(td, args->path, &path); 112885022Smarcel 112985022Smarcel#ifdef DEBUG 113085022Smarcel if (ldebug(lchown)) 1131102814Siedowse printf(ARGS(lchown, "%s, %d, %d"), path, args->uid, args->gid); 113285022Smarcel#endif 1133102814Siedowse error = kern_lchown(td, path, UIO_SYSSPACE, args->uid, args->gid); 1134102814Siedowse LFREEPATH(path); 1135102814Siedowse return (error); 113685022Smarcel} 1137