linux_file.c revision 111798
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 * 2850477Speter * $FreeBSD: head/sys/compat/linux/linux_file.c 111798 2003-03-03 09:17:12Z des $ 299313Ssos */ 309313Ssos 3131784Seivind#include "opt_compat.h" 32101189Srwatson#include "opt_mac.h" 3331784Seivind 349313Ssos#include <sys/param.h> 359313Ssos#include <sys/systm.h> 3676166Smarkm#include <sys/conf.h> 3776166Smarkm#include <sys/dirent.h> 389313Ssos#include <sys/fcntl.h> 399313Ssos#include <sys/file.h> 409313Ssos#include <sys/filedesc.h> 4131561Sbde#include <sys/lock.h> 42101189Srwatson#include <sys/mac.h> 439313Ssos#include <sys/malloc.h> 4472538Sjlemon#include <sys/mount.h> 4576166Smarkm#include <sys/mutex.h> 4676166Smarkm#include <sys/proc.h> 47102814Siedowse#include <sys/syscallsubr.h> 4876166Smarkm#include <sys/sysproto.h> 4914331Speter#include <sys/tty.h> 5076166Smarkm#include <sys/vnode.h> 5112458Sbde 5272538Sjlemon#include <ufs/ufs/extattr.h> 5372538Sjlemon#include <ufs/ufs/quota.h> 5472538Sjlemon#include <ufs/ufs/ufsmount.h> 5572538Sjlemon 5664905Smarcel#include <machine/../linux/linux.h> 5768583Smarcel#include <machine/../linux/linux_proto.h> 5864905Smarcel#include <compat/linux/linux_util.h> 599313Ssos 6068201Sobrien#ifndef __alpha__ 619313Ssosint 6283366Sjulianlinux_creat(struct thread *td, struct linux_creat_args *args) 639313Ssos{ 64102814Siedowse char *path; 65102814Siedowse int error; 669313Ssos 67102814Siedowse LCONVPATHEXIST(td, args->path, &path); 6814331Speter 699313Ssos#ifdef DEBUG 7072543Sjlemon if (ldebug(creat)) 71102814Siedowse printf(ARGS(creat, "%s, %d"), path, args->mode); 729313Ssos#endif 73102814Siedowse error = kern_open(td, path, UIO_SYSSPACE, O_WRONLY | O_CREAT | O_TRUNC, 74102814Siedowse args->mode); 75102814Siedowse LFREEPATH(path); 76102814Siedowse return (error); 779313Ssos} 7868201Sobrien#endif /*!__alpha__*/ 799313Ssos 809313Ssosint 8183366Sjulianlinux_open(struct thread *td, struct linux_open_args *args) 829313Ssos{ 8383382Sjhb struct proc *p = td->td_proc; 84102814Siedowse char *path; 85102814Siedowse int bsd_flags, error; 8614331Speter 8714331Speter if (args->flags & LINUX_O_CREAT) 88102814Siedowse LCONVPATHCREAT(td, args->path, &path); 8914331Speter else 90102814Siedowse LCONVPATHEXIST(td, args->path, &path); 9114331Speter 929313Ssos#ifdef DEBUG 9372543Sjlemon if (ldebug(open)) 9472543Sjlemon printf(ARGS(open, "%s, 0x%x, 0x%x"), 95102814Siedowse path, args->flags, args->mode); 969313Ssos#endif 97102814Siedowse bsd_flags = 0; 989313Ssos if (args->flags & LINUX_O_RDONLY) 99102814Siedowse bsd_flags |= O_RDONLY; 100111798Sdes if (args->flags & LINUX_O_WRONLY) 101102814Siedowse bsd_flags |= O_WRONLY; 1029313Ssos if (args->flags & LINUX_O_RDWR) 103102814Siedowse bsd_flags |= O_RDWR; 1049313Ssos if (args->flags & LINUX_O_NDELAY) 105102814Siedowse bsd_flags |= O_NONBLOCK; 1069313Ssos if (args->flags & LINUX_O_APPEND) 107102814Siedowse bsd_flags |= O_APPEND; 1089313Ssos if (args->flags & LINUX_O_SYNC) 109102814Siedowse bsd_flags |= O_FSYNC; 1109313Ssos if (args->flags & LINUX_O_NONBLOCK) 111102814Siedowse bsd_flags |= O_NONBLOCK; 1129313Ssos if (args->flags & LINUX_FASYNC) 113102814Siedowse bsd_flags |= O_ASYNC; 1149313Ssos if (args->flags & LINUX_O_CREAT) 115102814Siedowse bsd_flags |= O_CREAT; 1169313Ssos if (args->flags & LINUX_O_TRUNC) 117102814Siedowse bsd_flags |= O_TRUNC; 1189313Ssos if (args->flags & LINUX_O_EXCL) 119102814Siedowse bsd_flags |= O_EXCL; 1209313Ssos if (args->flags & LINUX_O_NOCTTY) 121102814Siedowse bsd_flags |= O_NOCTTY; 1229313Ssos 123102814Siedowse error = kern_open(td, path, UIO_SYSSPACE, bsd_flags, args->mode); 12470061Sjhb PROC_LOCK(p); 125102814Siedowse if (!error && !(bsd_flags & O_NOCTTY) && 1269313Ssos SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 12789306Salfred struct file *fp; 1289313Ssos 12989319Salfred error = fget(td, td->td_retval[0], &fp); 13070061Sjhb PROC_UNLOCK(p); 13189319Salfred if (!error) { 13289319Salfred if (fp->f_type == DTYPE_VNODE) 133102003Srwatson fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred, 134102003Srwatson td); 13589319Salfred fdrop(fp, td); 13689319Salfred } 13791140Stanimura } else { 13870061Sjhb PROC_UNLOCK(p); 13914331Speter#ifdef DEBUG 14072543Sjlemon if (ldebug(open)) 14172543Sjlemon printf(LMSG("open returns error %d"), error); 14214331Speter#endif 14391140Stanimura } 144102814Siedowse LFREEPATH(path); 1459313Ssos return error; 1469313Ssos} 1479313Ssos 1489313Ssosint 14983366Sjulianlinux_lseek(struct thread *td, struct linux_lseek_args *args) 1509313Ssos{ 1519313Ssos 15212858Speter struct lseek_args /* { 15312858Speter int fd; 1549313Ssos int pad; 15512858Speter off_t offset; 1569313Ssos int whence; 15712858Speter } */ tmp_args; 1589313Ssos int error; 1599313Ssos 1609313Ssos#ifdef DEBUG 16172543Sjlemon if (ldebug(lseek)) 16272543Sjlemon printf(ARGS(lseek, "%d, %ld, %d"), 16383221Smarcel args->fdes, (long)args->off, args->whence); 1649313Ssos#endif 16512858Speter tmp_args.fd = args->fdes; 16612858Speter tmp_args.offset = (off_t)args->off; 1679313Ssos tmp_args.whence = args->whence; 16883366Sjulian error = lseek(td, &tmp_args); 1699313Ssos return error; 1709313Ssos} 1719313Ssos 17268201Sobrien#ifndef __alpha__ 17314331Speterint 17483366Sjulianlinux_llseek(struct thread *td, struct linux_llseek_args *args) 17514331Speter{ 17614331Speter struct lseek_args bsd_args; 17714331Speter int error; 17814331Speter off_t off; 17914331Speter 18014331Speter#ifdef DEBUG 18172543Sjlemon if (ldebug(llseek)) 18272543Sjlemon printf(ARGS(llseek, "%d, %d:%d, %d"), 18372543Sjlemon args->fd, args->ohigh, args->olow, args->whence); 18414331Speter#endif 18514331Speter off = (args->olow) | (((off_t) args->ohigh) << 32); 18614331Speter 18714331Speter bsd_args.fd = args->fd; 18814331Speter bsd_args.offset = off; 18914331Speter bsd_args.whence = args->whence; 19014331Speter 19183366Sjulian if ((error = lseek(td, &bsd_args))) 19214331Speter return error; 19314331Speter 194111797Sdes if ((error = copyout(td->td_retval, args->res, sizeof (off_t)))) 19514331Speter return error; 19614331Speter 19783366Sjulian td->td_retval[0] = 0; 19814331Speter return 0; 19914331Speter} 20068201Sobrien#endif /*!__alpha__*/ 20114331Speter 20268201Sobrien#ifndef __alpha__ 2039313Ssosint 20483366Sjulianlinux_readdir(struct thread *td, struct linux_readdir_args *args) 2059313Ssos{ 20614331Speter struct linux_getdents_args lda; 20714331Speter 20814331Speter lda.fd = args->fd; 20914331Speter lda.dent = args->dent; 21014331Speter lda.count = 1; 21183366Sjulian return linux_getdents(td, &lda); 21214331Speter} 21368201Sobrien#endif /*!__alpha__*/ 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 struct vattr va; 25883221Smarcel off_t off; 25983221Smarcel struct l_dirent linux_dirent; 26083221Smarcel struct l_dirent64 linux_dirent64; 26183221Smarcel int buflen, error, eofflag, nbytes, justone; 26283221Smarcel u_long *cookies = NULL, *cookiep; 26383221Smarcel int ncookies; 2649313Ssos 26583366Sjulian if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0) 26683221Smarcel return (error); 2679313Ssos 26889306Salfred if ((fp->f_flag & FREAD) == 0) { 26989306Salfred fdrop(fp, td); 27083221Smarcel return (EBADF); 27189306Salfred } 2729313Ssos 273109153Sdillon vp = fp->f_data; 27489306Salfred if (vp->v_type != VDIR) { 27589306Salfred fdrop(fp, td); 27683221Smarcel return (EINVAL); 27789306Salfred } 2789313Ssos 27991406Sjhb if ((error = VOP_GETATTR(vp, &va, td->td_ucred, td))) { 28089306Salfred fdrop(fp, td); 28183221Smarcel return (error); 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 */ 323101706Srwatson if ((error = mac_check_vnode_readdir(td->td_proc->p_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 67083366Sjulianlinux_link(struct thread *td, struct linux_link_args *args) 67149662Smarcel{ 672102814Siedowse char *path, *to; 673102814Siedowse int error; 67449662Smarcel 675102814Siedowse LCONVPATHEXIST(td, args->path, &path); 676102814Siedowse /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 677102814Siedowse error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1); 678102814Siedowse if (to == NULL) { 679102814Siedowse LFREEPATH(path); 680102814Siedowse return (error); 681102814Siedowse } 68249662Smarcel 68349662Smarcel#ifdef DEBUG 68472543Sjlemon if (ldebug(link)) 685102814Siedowse printf(ARGS(link, "%s, %s"), path, to); 68649662Smarcel#endif 687102814Siedowse error = kern_link(td, path, to, UIO_SYSSPACE); 688102814Siedowse LFREEPATH(path); 689102814Siedowse LFREEPATH(to); 690102814Siedowse return (error); 69149662Smarcel} 69249788Smarcel 69368201Sobrien#ifndef __alpha__ 69453713Smarcelint 69583366Sjulianlinux_fdatasync(td, uap) 69683366Sjulian struct thread *td; 69753713Smarcel struct linux_fdatasync_args *uap; 69853713Smarcel{ 69953713Smarcel struct fsync_args bsd; 70053713Smarcel 70153713Smarcel bsd.fd = uap->fd; 70283366Sjulian return fsync(td, &bsd); 70353713Smarcel} 70468201Sobrien#endif /*!__alpha__*/ 70563285Smarcel 70663285Smarcelint 70783366Sjulianlinux_pread(td, uap) 70883366Sjulian struct thread *td; 70963285Smarcel struct linux_pread_args *uap; 71063285Smarcel{ 71163285Smarcel struct pread_args bsd; 71263285Smarcel 71363285Smarcel bsd.fd = uap->fd; 71463285Smarcel bsd.buf = uap->buf; 71563285Smarcel bsd.nbyte = uap->nbyte; 71663285Smarcel bsd.offset = uap->offset; 71783366Sjulian return pread(td, &bsd); 71863285Smarcel} 71963285Smarcel 72063285Smarcelint 72183366Sjulianlinux_pwrite(td, uap) 72283366Sjulian struct thread *td; 72363285Smarcel struct linux_pwrite_args *uap; 72463285Smarcel{ 72563285Smarcel struct pwrite_args bsd; 72663285Smarcel 72763285Smarcel bsd.fd = uap->fd; 72863285Smarcel bsd.buf = uap->buf; 72963285Smarcel bsd.nbyte = uap->nbyte; 73063285Smarcel bsd.offset = uap->offset; 73183366Sjulian return pwrite(td, &bsd); 73263285Smarcel} 73372538Sjlemon 73472538Sjlemonint 73583366Sjulianlinux_mount(struct thread *td, struct linux_mount_args *args) 73672538Sjlemon{ 73772538Sjlemon struct ufs_args ufs; 738111798Sdes char fstypename[MFSNAMELEN]; 739111798Sdes char mntonname[MNAMELEN], mntfromname[MNAMELEN]; 74073286Sadrian int error; 74173286Sadrian int fsflags; 74273286Sadrian const char *fstype; 74373286Sadrian void *fsdata; 74472538Sjlemon 745111798Sdes error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1, 74673286Sadrian NULL); 74772538Sjlemon if (error) 748111798Sdes return (error); 749111798Sdes error = copyinstr(args->specialfile, mntfromname, MFSNAMELEN - 1, NULL); 75072538Sjlemon if (error) 751111798Sdes return (error); 752111798Sdes error = copyinstr(args->dir, mntonname, MFSNAMELEN - 1, NULL); 75372538Sjlemon if (error) 754111798Sdes return (error); 75572538Sjlemon 75672538Sjlemon#ifdef DEBUG 75772538Sjlemon if (ldebug(mount)) 75872538Sjlemon printf(ARGS(mount, "%s, %s, %s"), 75972538Sjlemon fstypename, mntfromname, mntonname); 76072538Sjlemon#endif 76172538Sjlemon 76272538Sjlemon if (strcmp(fstypename, "ext2") == 0) { 76373286Sadrian fstype = "ext2fs"; 76473286Sadrian fsdata = &ufs; 76572538Sjlemon ufs.fspec = mntfromname; 76672538Sjlemon#define DEFAULT_ROOTID -2 76772538Sjlemon ufs.export.ex_root = DEFAULT_ROOTID; 76872538Sjlemon ufs.export.ex_flags = 76972538Sjlemon args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0; 77072538Sjlemon } else if (strcmp(fstypename, "proc") == 0) { 77173286Sadrian fstype = "linprocfs"; 77273286Sadrian fsdata = NULL; 77372538Sjlemon } else { 77472538Sjlemon return (ENODEV); 77572538Sjlemon } 77672538Sjlemon 77773286Sadrian fsflags = 0; 77872538Sjlemon 77972538Sjlemon if ((args->rwflag & 0xffff0000) == 0xc0ed0000) { 78072538Sjlemon /* 78172538Sjlemon * Linux SYNC flag is not included; the closest equivalent 78272538Sjlemon * FreeBSD has is !ASYNC, which is our default. 78372538Sjlemon */ 78472538Sjlemon if (args->rwflag & LINUX_MS_RDONLY) 785111798Sdes fsflags |= MNT_RDONLY; 78672538Sjlemon if (args->rwflag & LINUX_MS_NOSUID) 787111798Sdes fsflags |= MNT_NOSUID; 78872538Sjlemon if (args->rwflag & LINUX_MS_NODEV) 789111798Sdes fsflags |= MNT_NODEV; 79072538Sjlemon if (args->rwflag & LINUX_MS_NOEXEC) 791111798Sdes fsflags |= MNT_NOEXEC; 79272538Sjlemon if (args->rwflag & LINUX_MS_REMOUNT) 793111798Sdes fsflags |= MNT_UPDATE; 79472538Sjlemon } 79572538Sjlemon 79683366Sjulian return (vfs_mount(td, fstype, mntonname, fsflags, fsdata)); 79772538Sjlemon} 79872538Sjlemon 79972538Sjlemonint 80083366Sjulianlinux_oldumount(struct thread *td, struct linux_oldumount_args *args) 80172538Sjlemon{ 80283221Smarcel struct linux_umount_args args2; 80372538Sjlemon 80472538Sjlemon args2.path = args->path; 80572538Sjlemon args2.flags = 0; 80683366Sjulian return (linux_umount(td, &args2)); 80772538Sjlemon} 80872538Sjlemon 80972538Sjlemonint 81083366Sjulianlinux_umount(struct thread *td, struct linux_umount_args *args) 81172538Sjlemon{ 81272538Sjlemon struct unmount_args bsd; 81372538Sjlemon 81472538Sjlemon bsd.path = args->path; 81572538Sjlemon bsd.flags = args->flags; /* XXX correct? */ 81683366Sjulian return (unmount(td, &bsd)); 81772538Sjlemon} 81883221Smarcel 81983221Smarcel/* 82083221Smarcel * fcntl family of syscalls 82183221Smarcel */ 82283221Smarcel 82383221Smarcelstruct l_flock { 82483221Smarcel l_short l_type; 82583221Smarcel l_short l_whence; 82683221Smarcel l_off_t l_start; 82783221Smarcel l_off_t l_len; 82883221Smarcel l_pid_t l_pid; 82983221Smarcel}; 83083221Smarcel 83183221Smarcelstatic void 83283221Smarcellinux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock) 83383221Smarcel{ 83483221Smarcel switch (linux_flock->l_type) { 83583221Smarcel case LINUX_F_RDLCK: 83683221Smarcel bsd_flock->l_type = F_RDLCK; 83783221Smarcel break; 83883221Smarcel case LINUX_F_WRLCK: 83983221Smarcel bsd_flock->l_type = F_WRLCK; 84083221Smarcel break; 84183221Smarcel case LINUX_F_UNLCK: 84283221Smarcel bsd_flock->l_type = F_UNLCK; 84383221Smarcel break; 84483221Smarcel default: 84583221Smarcel bsd_flock->l_type = -1; 84683221Smarcel break; 84783221Smarcel } 84883221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 84983221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 85083221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 85183221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 85283221Smarcel} 85383221Smarcel 85483221Smarcelstatic void 85583221Smarcelbsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock) 85683221Smarcel{ 85783221Smarcel switch (bsd_flock->l_type) { 85883221Smarcel case F_RDLCK: 85983221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 86083221Smarcel break; 86183221Smarcel case F_WRLCK: 86283221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 86383221Smarcel break; 86483221Smarcel case F_UNLCK: 86583221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 86683221Smarcel break; 86783221Smarcel } 86883221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 86983221Smarcel linux_flock->l_start = (l_off_t)bsd_flock->l_start; 87083221Smarcel linux_flock->l_len = (l_off_t)bsd_flock->l_len; 87183221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 87283221Smarcel} 87383221Smarcel 87483221Smarcel#if defined(__i386__) 87583221Smarcelstruct l_flock64 { 87683221Smarcel l_short l_type; 87783221Smarcel l_short l_whence; 87883221Smarcel l_loff_t l_start; 87983221Smarcel l_loff_t l_len; 88083221Smarcel l_pid_t l_pid; 88183221Smarcel}; 88283221Smarcel 88383221Smarcelstatic void 88483221Smarcellinux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock) 88583221Smarcel{ 88683221Smarcel switch (linux_flock->l_type) { 88783221Smarcel case LINUX_F_RDLCK: 88883221Smarcel bsd_flock->l_type = F_RDLCK; 88983221Smarcel break; 89083221Smarcel case LINUX_F_WRLCK: 89183221Smarcel bsd_flock->l_type = F_WRLCK; 89283221Smarcel break; 89383221Smarcel case LINUX_F_UNLCK: 89483221Smarcel bsd_flock->l_type = F_UNLCK; 89583221Smarcel break; 89683221Smarcel default: 89783221Smarcel bsd_flock->l_type = -1; 89883221Smarcel break; 89983221Smarcel } 90083221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 90183221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 90283221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 90383221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 90483221Smarcel} 90583221Smarcel 90683221Smarcelstatic void 90783221Smarcelbsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) 90883221Smarcel{ 90983221Smarcel switch (bsd_flock->l_type) { 91083221Smarcel case F_RDLCK: 91183221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 91283221Smarcel break; 91383221Smarcel case F_WRLCK: 91483221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 91583221Smarcel break; 91683221Smarcel case F_UNLCK: 91783221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 91883221Smarcel break; 91983221Smarcel } 92083221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 92183221Smarcel linux_flock->l_start = (l_loff_t)bsd_flock->l_start; 92283221Smarcel linux_flock->l_len = (l_loff_t)bsd_flock->l_len; 92383221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 92483221Smarcel} 92583221Smarcel#endif /* __i386__ */ 92683221Smarcel 92783221Smarcel#if defined(__alpha__) 92883221Smarcel#define linux_fcntl64_args linux_fcntl_args 92983221Smarcel#endif 93083221Smarcel 93183221Smarcelstatic int 93283366Sjulianfcntl_common(struct thread *td, struct linux_fcntl64_args *args) 93383221Smarcel{ 934107680Siedowse struct l_flock linux_flock; 935107680Siedowse struct flock bsd_flock; 93683221Smarcel struct file *fp; 937102872Siedowse long arg; 93883221Smarcel int error, result; 93983221Smarcel 94083221Smarcel switch (args->cmd) { 94183221Smarcel case LINUX_F_DUPFD: 942102872Siedowse return (kern_fcntl(td, args->fd, F_DUPFD, args->arg)); 94383221Smarcel 94483221Smarcel case LINUX_F_GETFD: 945102872Siedowse return (kern_fcntl(td, args->fd, F_GETFD, 0)); 94683221Smarcel 94783221Smarcel case LINUX_F_SETFD: 948102872Siedowse return (kern_fcntl(td, args->fd, F_SETFD, args->arg)); 94983221Smarcel 95083221Smarcel case LINUX_F_GETFL: 951102872Siedowse error = kern_fcntl(td, args->fd, F_GETFL, 0); 95283366Sjulian result = td->td_retval[0]; 95383366Sjulian td->td_retval[0] = 0; 95483221Smarcel if (result & O_RDONLY) 95583366Sjulian td->td_retval[0] |= LINUX_O_RDONLY; 95683221Smarcel if (result & O_WRONLY) 95783366Sjulian td->td_retval[0] |= LINUX_O_WRONLY; 95883221Smarcel if (result & O_RDWR) 95983366Sjulian td->td_retval[0] |= LINUX_O_RDWR; 96083221Smarcel if (result & O_NDELAY) 96183366Sjulian td->td_retval[0] |= LINUX_O_NONBLOCK; 96283221Smarcel if (result & O_APPEND) 96383366Sjulian td->td_retval[0] |= LINUX_O_APPEND; 96483221Smarcel if (result & O_FSYNC) 96583366Sjulian td->td_retval[0] |= LINUX_O_SYNC; 96683221Smarcel if (result & O_ASYNC) 96783366Sjulian td->td_retval[0] |= LINUX_FASYNC; 96883221Smarcel return (error); 96983221Smarcel 97083221Smarcel case LINUX_F_SETFL: 971102872Siedowse arg = 0; 97283221Smarcel if (args->arg & LINUX_O_NDELAY) 973102872Siedowse arg |= O_NONBLOCK; 97483221Smarcel if (args->arg & LINUX_O_APPEND) 975102872Siedowse arg |= O_APPEND; 97683221Smarcel if (args->arg & LINUX_O_SYNC) 977102872Siedowse arg |= O_FSYNC; 97883221Smarcel if (args->arg & LINUX_FASYNC) 979102872Siedowse arg |= O_ASYNC; 980102872Siedowse return (kern_fcntl(td, args->fd, F_SETFL, arg)); 98183221Smarcel 982107680Siedowse case LINUX_F_GETLK: 983111797Sdes error = copyin((void *)args->arg, &linux_flock, 984107680Siedowse sizeof(linux_flock)); 985107680Siedowse if (error) 986107680Siedowse return (error); 987107680Siedowse linux_to_bsd_flock(&linux_flock, &bsd_flock); 988107680Siedowse error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); 989107680Siedowse if (error) 990107680Siedowse return (error); 991107680Siedowse bsd_to_linux_flock(&bsd_flock, &linux_flock); 992111797Sdes return (copyout(&linux_flock, (void *)args->arg, 993107680Siedowse sizeof(linux_flock))); 994107680Siedowse 995107680Siedowse case LINUX_F_SETLK: 996111797Sdes error = copyin((void *)args->arg, &linux_flock, 997107680Siedowse sizeof(linux_flock)); 998107680Siedowse if (error) 999107680Siedowse return (error); 1000107680Siedowse linux_to_bsd_flock(&linux_flock, &bsd_flock); 1001107680Siedowse return (kern_fcntl(td, args->fd, F_SETLK, 1002107680Siedowse (intptr_t)&bsd_flock)); 1003107680Siedowse 1004107680Siedowse case LINUX_F_SETLKW: 1005111797Sdes error = copyin((void *)args->arg, &linux_flock, 1006107680Siedowse sizeof(linux_flock)); 1007107680Siedowse if (error) 1008107680Siedowse return (error); 1009107680Siedowse linux_to_bsd_flock(&linux_flock, &bsd_flock); 1010107680Siedowse return (kern_fcntl(td, args->fd, F_SETLKW, 1011107680Siedowse (intptr_t)&bsd_flock)); 1012107680Siedowse 101383221Smarcel case LINUX_F_GETOWN: 1014102872Siedowse return (kern_fcntl(td, args->fd, F_GETOWN, 0)); 101583221Smarcel 101683221Smarcel case LINUX_F_SETOWN: 101783221Smarcel /* 101883221Smarcel * XXX some Linux applications depend on F_SETOWN having no 101983221Smarcel * significant effect for pipes (SIGIO is not delivered for 102083221Smarcel * pipes under Linux-2.2.35 at least). 102183221Smarcel */ 102289319Salfred error = fget(td, args->fd, &fp); 102389319Salfred if (error) 102489319Salfred return (error); 102589306Salfred if (fp->f_type == DTYPE_PIPE) { 102689306Salfred fdrop(fp, td); 102783221Smarcel return (EINVAL); 102889306Salfred } 102989306Salfred fdrop(fp, td); 103083221Smarcel 1031102872Siedowse return (kern_fcntl(td, args->fd, F_SETOWN, args->arg)); 103283221Smarcel } 103383221Smarcel 103483221Smarcel return (EINVAL); 103583221Smarcel} 103683221Smarcel 103783221Smarcelint 103883366Sjulianlinux_fcntl(struct thread *td, struct linux_fcntl_args *args) 103983221Smarcel{ 104083221Smarcel struct linux_fcntl64_args args64; 104183221Smarcel 104283221Smarcel#ifdef DEBUG 104383221Smarcel if (ldebug(fcntl)) 104483221Smarcel printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); 104583221Smarcel#endif 104683221Smarcel 104783221Smarcel args64.fd = args->fd; 104883221Smarcel args64.cmd = args->cmd; 104983221Smarcel args64.arg = args->arg; 105083366Sjulian return (fcntl_common(td, &args64)); 105183221Smarcel} 105283221Smarcel 105383221Smarcel#if defined(__i386__) 105483221Smarcelint 105583366Sjulianlinux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) 105683221Smarcel{ 105783221Smarcel struct l_flock64 linux_flock; 1058102872Siedowse struct flock bsd_flock; 105983221Smarcel int error; 106083221Smarcel 106183221Smarcel#ifdef DEBUG 106283221Smarcel if (ldebug(fcntl64)) 106383221Smarcel printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd); 106483221Smarcel#endif 106583221Smarcel 106683221Smarcel switch (args->cmd) { 106799687Srobert case LINUX_F_GETLK64: 1068111797Sdes error = copyin((void *)args->arg, &linux_flock, 106983221Smarcel sizeof(linux_flock)); 107083221Smarcel if (error) 107183221Smarcel return (error); 1072102872Siedowse linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1073102872Siedowse error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); 107483221Smarcel if (error) 107583221Smarcel return (error); 1076102872Siedowse bsd_to_linux_flock64(&bsd_flock, &linux_flock); 1077111797Sdes return (copyout(&linux_flock, (void *)args->arg, 1078111797Sdes sizeof(linux_flock))); 107983221Smarcel 108099687Srobert case LINUX_F_SETLK64: 1081111797Sdes error = copyin((void *)args->arg, &linux_flock, 108283221Smarcel sizeof(linux_flock)); 108383221Smarcel if (error) 108483221Smarcel return (error); 1085102872Siedowse linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1086102872Siedowse return (kern_fcntl(td, args->fd, F_SETLK, 1087102872Siedowse (intptr_t)&bsd_flock)); 108883221Smarcel 108999687Srobert case LINUX_F_SETLKW64: 1090111797Sdes error = copyin((void *)args->arg, &linux_flock, 109183221Smarcel sizeof(linux_flock)); 109283221Smarcel if (error) 109383221Smarcel return (error); 1094102872Siedowse linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1095102872Siedowse return (kern_fcntl(td, args->fd, F_SETLKW, 1096102872Siedowse (intptr_t)&bsd_flock)); 109783221Smarcel } 109883221Smarcel 109983366Sjulian return (fcntl_common(td, args)); 110083221Smarcel} 110183221Smarcel#endif /* __i386__ */ 110285022Smarcel 110385022Smarcelint 110485022Smarcellinux_chown(struct thread *td, struct linux_chown_args *args) 110585022Smarcel{ 1106102814Siedowse char *path; 1107102814Siedowse int error; 110885022Smarcel 1109102814Siedowse LCONVPATHEXIST(td, args->path, &path); 111085022Smarcel 111185022Smarcel#ifdef DEBUG 111285022Smarcel if (ldebug(chown)) 1113102814Siedowse printf(ARGS(chown, "%s, %d, %d"), path, args->uid, args->gid); 111485022Smarcel#endif 1115102814Siedowse error = kern_chown(td, path, UIO_SYSSPACE, args->uid, args->gid); 1116102814Siedowse LFREEPATH(path); 1117102814Siedowse return (error); 111885022Smarcel} 111985022Smarcel 112085022Smarcelint 112185022Smarcellinux_lchown(struct thread *td, struct linux_lchown_args *args) 112285022Smarcel{ 1123102814Siedowse char *path; 1124102814Siedowse int error; 112585022Smarcel 1126102814Siedowse LCONVPATHEXIST(td, args->path, &path); 112785022Smarcel 112885022Smarcel#ifdef DEBUG 112985022Smarcel if (ldebug(lchown)) 1130102814Siedowse printf(ARGS(lchown, "%s, %d, %d"), path, args->uid, args->gid); 113185022Smarcel#endif 1132102814Siedowse error = kern_lchown(td, path, UIO_SYSSPACE, args->uid, args->gid); 1133102814Siedowse LFREEPATH(path); 1134102814Siedowse return (error); 113585022Smarcel} 1136