linux_file.c revision 85022
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 99313Ssos * 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 159313Ssos * derived from this software withough 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 85022 2001-10-16 06:15:36Z marcel $ 299313Ssos */ 309313Ssos 3131784Seivind#include "opt_compat.h" 3231784Seivind 339313Ssos#include <sys/param.h> 349313Ssos#include <sys/systm.h> 3576166Smarkm#include <sys/conf.h> 3676166Smarkm#include <sys/dirent.h> 379313Ssos#include <sys/fcntl.h> 389313Ssos#include <sys/file.h> 399313Ssos#include <sys/filedesc.h> 4031561Sbde#include <sys/lock.h> 419313Ssos#include <sys/malloc.h> 4272538Sjlemon#include <sys/mount.h> 4376166Smarkm#include <sys/mutex.h> 4476166Smarkm#include <sys/proc.h> 4576166Smarkm#include <sys/sysproto.h> 4614331Speter#include <sys/tty.h> 4776166Smarkm#include <sys/vnode.h> 4812458Sbde 4972538Sjlemon#include <ufs/ufs/extattr.h> 5072538Sjlemon#include <ufs/ufs/quota.h> 5172538Sjlemon#include <ufs/ufs/ufsmount.h> 5272538Sjlemon 5364905Smarcel#include <machine/../linux/linux.h> 5468583Smarcel#include <machine/../linux/linux_proto.h> 5564905Smarcel#include <compat/linux/linux_util.h> 569313Ssos 5768201Sobrien#ifndef __alpha__ 589313Ssosint 5983366Sjulianlinux_creat(struct thread *td, struct linux_creat_args *args) 609313Ssos{ 6112858Speter struct open_args /* { 629313Ssos char *path; 639313Ssos int flags; 649313Ssos int mode; 6512858Speter } */ bsd_open_args; 6614331Speter caddr_t sg; 679313Ssos 6814331Speter sg = stackgap_init(); 6983366Sjulian CHECKALTCREAT(td, &sg, args->path); 7014331Speter 719313Ssos#ifdef DEBUG 7272543Sjlemon if (ldebug(creat)) 7372543Sjlemon printf(ARGS(creat, "%s, %d"), args->path, args->mode); 749313Ssos#endif 759313Ssos bsd_open_args.path = args->path; 769313Ssos bsd_open_args.mode = args->mode; 779313Ssos bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC; 7883366Sjulian return open(td, &bsd_open_args); 799313Ssos} 8068201Sobrien#endif /*!__alpha__*/ 819313Ssos 829313Ssosint 8383366Sjulianlinux_open(struct thread *td, struct linux_open_args *args) 849313Ssos{ 8512858Speter struct open_args /* { 869313Ssos char *path; 879313Ssos int flags; 889313Ssos int mode; 8912858Speter } */ bsd_open_args; 9083382Sjhb struct proc *p = td->td_proc; 919313Ssos int error; 9214331Speter caddr_t sg; 9314331Speter 9414331Speter sg = stackgap_init(); 959313Ssos 9614331Speter if (args->flags & LINUX_O_CREAT) 9783366Sjulian CHECKALTCREAT(td, &sg, args->path); 9814331Speter else 9983366Sjulian CHECKALTEXIST(td, &sg, args->path); 10014331Speter 1019313Ssos#ifdef DEBUG 10272543Sjlemon if (ldebug(open)) 10372543Sjlemon printf(ARGS(open, "%s, 0x%x, 0x%x"), 10472543Sjlemon args->path, args->flags, args->mode); 1059313Ssos#endif 1069313Ssos bsd_open_args.flags = 0; 1079313Ssos if (args->flags & LINUX_O_RDONLY) 1089313Ssos bsd_open_args.flags |= O_RDONLY; 1099313Ssos if (args->flags & LINUX_O_WRONLY) 1109313Ssos bsd_open_args.flags |= O_WRONLY; 1119313Ssos if (args->flags & LINUX_O_RDWR) 1129313Ssos bsd_open_args.flags |= O_RDWR; 1139313Ssos if (args->flags & LINUX_O_NDELAY) 1149313Ssos bsd_open_args.flags |= O_NONBLOCK; 1159313Ssos if (args->flags & LINUX_O_APPEND) 1169313Ssos bsd_open_args.flags |= O_APPEND; 1179313Ssos if (args->flags & LINUX_O_SYNC) 1189313Ssos bsd_open_args.flags |= O_FSYNC; 1199313Ssos if (args->flags & LINUX_O_NONBLOCK) 1209313Ssos bsd_open_args.flags |= O_NONBLOCK; 1219313Ssos if (args->flags & LINUX_FASYNC) 1229313Ssos bsd_open_args.flags |= O_ASYNC; 1239313Ssos if (args->flags & LINUX_O_CREAT) 1249313Ssos bsd_open_args.flags |= O_CREAT; 1259313Ssos if (args->flags & LINUX_O_TRUNC) 1269313Ssos bsd_open_args.flags |= O_TRUNC; 1279313Ssos if (args->flags & LINUX_O_EXCL) 1289313Ssos bsd_open_args.flags |= O_EXCL; 1299313Ssos if (args->flags & LINUX_O_NOCTTY) 1309313Ssos bsd_open_args.flags |= O_NOCTTY; 1319313Ssos bsd_open_args.path = args->path; 1329313Ssos bsd_open_args.mode = args->mode; 1339313Ssos 13483366Sjulian error = open(td, &bsd_open_args); 13570061Sjhb PROC_LOCK(p); 1369313Ssos if (!error && !(bsd_open_args.flags & O_NOCTTY) && 1379313Ssos SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 1389313Ssos struct filedesc *fdp = p->p_fd; 13983366Sjulian struct file *fp = fdp->fd_ofiles[td->td_retval[0]]; 1409313Ssos 14170061Sjhb PROC_UNLOCK(p); 1429313Ssos if (fp->f_type == DTYPE_VNODE) 14383366Sjulian fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td); 14470061Sjhb } else 14570061Sjhb PROC_UNLOCK(p); 14614331Speter#ifdef DEBUG 14772543Sjlemon if (ldebug(open)) 14872543Sjlemon printf(LMSG("open returns error %d"), error); 14914331Speter#endif 1509313Ssos return error; 1519313Ssos} 1529313Ssos 1539313Ssosint 15483366Sjulianlinux_lseek(struct thread *td, struct linux_lseek_args *args) 1559313Ssos{ 1569313Ssos 15712858Speter struct lseek_args /* { 15812858Speter int fd; 1599313Ssos int pad; 16012858Speter off_t offset; 1619313Ssos int whence; 16212858Speter } */ tmp_args; 1639313Ssos int error; 1649313Ssos 1659313Ssos#ifdef DEBUG 16672543Sjlemon if (ldebug(lseek)) 16772543Sjlemon printf(ARGS(lseek, "%d, %ld, %d"), 16883221Smarcel args->fdes, (long)args->off, args->whence); 1699313Ssos#endif 17012858Speter tmp_args.fd = args->fdes; 17112858Speter tmp_args.offset = (off_t)args->off; 1729313Ssos tmp_args.whence = args->whence; 17383366Sjulian error = lseek(td, &tmp_args); 1749313Ssos return error; 1759313Ssos} 1769313Ssos 17768201Sobrien#ifndef __alpha__ 17814331Speterint 17983366Sjulianlinux_llseek(struct thread *td, struct linux_llseek_args *args) 18014331Speter{ 18114331Speter struct lseek_args bsd_args; 18214331Speter int error; 18314331Speter off_t off; 18414331Speter 18514331Speter#ifdef DEBUG 18672543Sjlemon if (ldebug(llseek)) 18772543Sjlemon printf(ARGS(llseek, "%d, %d:%d, %d"), 18872543Sjlemon args->fd, args->ohigh, args->olow, args->whence); 18914331Speter#endif 19014331Speter off = (args->olow) | (((off_t) args->ohigh) << 32); 19114331Speter 19214331Speter bsd_args.fd = args->fd; 19314331Speter bsd_args.offset = off; 19414331Speter bsd_args.whence = args->whence; 19514331Speter 19683366Sjulian if ((error = lseek(td, &bsd_args))) 19714331Speter return error; 19814331Speter 19983366Sjulian if ((error = copyout(td->td_retval, (caddr_t)args->res, sizeof (off_t)))) 20014331Speter return error; 20114331Speter 20283366Sjulian td->td_retval[0] = 0; 20314331Speter return 0; 20414331Speter} 20568201Sobrien#endif /*!__alpha__*/ 20614331Speter 20768201Sobrien#ifndef __alpha__ 2089313Ssosint 20983366Sjulianlinux_readdir(struct thread *td, struct linux_readdir_args *args) 2109313Ssos{ 21114331Speter struct linux_getdents_args lda; 21214331Speter 21314331Speter lda.fd = args->fd; 21414331Speter lda.dent = args->dent; 21514331Speter lda.count = 1; 21683366Sjulian return linux_getdents(td, &lda); 21714331Speter} 21868201Sobrien#endif /*!__alpha__*/ 21914331Speter 22083221Smarcel/* 22183221Smarcel * Note that linux_getdents(2) and linux_getdents64(2) have the same 22283221Smarcel * arguments. They only differ in the definition of struct dirent they 22383221Smarcel * operate on. We use this to common the code, with the exception of 22483221Smarcel * accessing struct dirent. Note that linux_readdir(2) is implemented 22583221Smarcel * by means of linux_getdents(2). In this case we never operate on 22683221Smarcel * struct dirent64 and thus don't need to handle it... 22783221Smarcel */ 22883221Smarcel 22983221Smarcelstruct l_dirent { 23083221Smarcel l_long d_ino; 23183221Smarcel l_off_t d_off; 23283221Smarcel l_ushort d_reclen; 23383221Smarcel char d_name[LINUX_NAME_MAX + 1]; 23483221Smarcel}; 23583221Smarcel 23683221Smarcelstruct l_dirent64 { 23783221Smarcel uint64_t d_ino; 23883221Smarcel int64_t d_off; 23983221Smarcel l_ushort d_reclen; 24083221Smarcel u_char d_type; 24183221Smarcel char d_name[LINUX_NAME_MAX + 1]; 24283221Smarcel}; 24383221Smarcel 24483221Smarcel#define LINUX_RECLEN(de,namlen) \ 24583221Smarcel ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1)) 24683221Smarcel 24783221Smarcel#define LINUX_DIRBLKSIZ 512 24883221Smarcel 24983221Smarcelstatic int 25083366Sjuliangetdents_common(struct thread *td, struct linux_getdents64_args *args, 25183221Smarcel int is64bit) 25214331Speter{ 25383221Smarcel register struct dirent *bdp; 25483221Smarcel struct vnode *vp; 25583221Smarcel caddr_t inp, buf; /* BSD-format */ 25683221Smarcel int len, reclen; /* BSD-format */ 25783221Smarcel caddr_t outp; /* Linux-format */ 25883221Smarcel int resid, linuxreclen=0; /* Linux-format */ 25983221Smarcel struct file *fp; 26083221Smarcel struct uio auio; 26183221Smarcel struct iovec aiov; 26283221Smarcel struct vattr va; 26383221Smarcel off_t off; 26483221Smarcel struct l_dirent linux_dirent; 26583221Smarcel struct l_dirent64 linux_dirent64; 26683221Smarcel int buflen, error, eofflag, nbytes, justone; 26783221Smarcel u_long *cookies = NULL, *cookiep; 26883221Smarcel int ncookies; 2699313Ssos 27083366Sjulian if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0) 27183221Smarcel return (error); 2729313Ssos 27383221Smarcel if ((fp->f_flag & FREAD) == 0) 27483221Smarcel return (EBADF); 2759313Ssos 27683221Smarcel vp = (struct vnode *) fp->f_data; 27783221Smarcel if (vp->v_type != VDIR) 27883221Smarcel return (EINVAL); 2799313Ssos 28083366Sjulian if ((error = VOP_GETATTR(vp, &va, td->td_proc->p_ucred, td))) 28183221Smarcel return (error); 2829313Ssos 28383221Smarcel nbytes = args->count; 28483221Smarcel if (nbytes == 1) { 28583221Smarcel /* readdir(2) case. Always struct dirent. */ 28683221Smarcel if (is64bit) 28783221Smarcel return (EINVAL); 28883221Smarcel nbytes = sizeof(linux_dirent); 28983221Smarcel justone = 1; 29083221Smarcel } else 29183221Smarcel justone = 0; 2929313Ssos 29383221Smarcel off = fp->f_offset; 2949313Ssos 29583221Smarcel buflen = max(LINUX_DIRBLKSIZ, nbytes); 29683221Smarcel buflen = min(buflen, MAXBSIZE); 29783221Smarcel buf = malloc(buflen, M_TEMP, M_WAITOK); 29883366Sjulian vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 29983221Smarcel 3009313Ssosagain: 30183221Smarcel aiov.iov_base = buf; 30283221Smarcel aiov.iov_len = buflen; 30383221Smarcel auio.uio_iov = &aiov; 30483221Smarcel auio.uio_iovcnt = 1; 30583221Smarcel auio.uio_rw = UIO_READ; 30683221Smarcel auio.uio_segflg = UIO_SYSSPACE; 30783366Sjulian auio.uio_td = td; 30883221Smarcel auio.uio_resid = buflen; 30983221Smarcel auio.uio_offset = off; 3109313Ssos 31183221Smarcel if (cookies) { 31283221Smarcel free(cookies, M_TEMP); 31383221Smarcel cookies = NULL; 31483221Smarcel } 31524654Sdfr 31683221Smarcel if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, 31783221Smarcel &cookies))) 31883221Smarcel goto out; 3199313Ssos 32083221Smarcel inp = buf; 32183221Smarcel outp = (caddr_t)args->dirent; 32283221Smarcel resid = nbytes; 32383221Smarcel if ((len = buflen - auio.uio_resid) <= 0) 32483221Smarcel goto eof; 3259313Ssos 32683221Smarcel cookiep = cookies; 32724654Sdfr 32883221Smarcel if (cookies) { 32983221Smarcel /* 33083221Smarcel * When using cookies, the vfs has the option of reading from 33183221Smarcel * a different offset than that supplied (UFS truncates the 33283221Smarcel * offset to a block boundary to make sure that it never reads 33383221Smarcel * partway through a directory entry, even if the directory 33483221Smarcel * has been compacted). 33583221Smarcel */ 33683221Smarcel while (len > 0 && ncookies > 0 && *cookiep <= off) { 33783221Smarcel bdp = (struct dirent *) inp; 33883221Smarcel len -= bdp->d_reclen; 33983221Smarcel inp += bdp->d_reclen; 34083221Smarcel cookiep++; 34183221Smarcel ncookies--; 34283221Smarcel } 34324654Sdfr } 34424654Sdfr 34583221Smarcel while (len > 0) { 34683221Smarcel if (cookiep && ncookies == 0) 34783221Smarcel break; 34883221Smarcel bdp = (struct dirent *) inp; 34983221Smarcel reclen = bdp->d_reclen; 35083221Smarcel if (reclen & 3) { 35183221Smarcel error = EFAULT; 35283221Smarcel goto out; 35383221Smarcel } 35483221Smarcel 35583221Smarcel if (bdp->d_fileno == 0) { 35683221Smarcel inp += reclen; 35783221Smarcel if (cookiep) { 35883221Smarcel off = *cookiep++; 35983221Smarcel ncookies--; 36083221Smarcel } else 36183221Smarcel off += reclen; 36283221Smarcel 36383221Smarcel len -= reclen; 36483221Smarcel continue; 36583221Smarcel } 36683221Smarcel 36783221Smarcel linuxreclen = (is64bit) 36883221Smarcel ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen) 36983221Smarcel : LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 37083221Smarcel 37183221Smarcel if (reclen > len || resid < linuxreclen) { 37283221Smarcel outp++; 37383221Smarcel break; 37483221Smarcel } 37583221Smarcel 37683221Smarcel if (justone) { 37783221Smarcel /* readdir(2) case. */ 37883221Smarcel linux_dirent.d_ino = (l_long)bdp->d_fileno; 37983221Smarcel linux_dirent.d_off = (l_off_t)linuxreclen; 38083221Smarcel linux_dirent.d_reclen = (l_ushort)bdp->d_namlen; 38183221Smarcel strcpy(linux_dirent.d_name, bdp->d_name); 38283221Smarcel error = copyout(&linux_dirent, outp, linuxreclen); 38383221Smarcel } else { 38483221Smarcel if (is64bit) { 38583221Smarcel linux_dirent64.d_ino = bdp->d_fileno; 38683221Smarcel linux_dirent64.d_off = (cookiep) 38783221Smarcel ? (l_off_t)*cookiep 38883221Smarcel : (l_off_t)(off + reclen); 38983221Smarcel linux_dirent64.d_reclen = 39083221Smarcel (l_ushort)linuxreclen; 39183221Smarcel linux_dirent64.d_type = bdp->d_type; 39283221Smarcel strcpy(linux_dirent64.d_name, bdp->d_name); 39383221Smarcel error = copyout(&linux_dirent64, outp, 39483221Smarcel linuxreclen); 39583221Smarcel } else { 39683221Smarcel linux_dirent.d_ino = bdp->d_fileno; 39783221Smarcel linux_dirent.d_off = (cookiep) 39883221Smarcel ? (l_off_t)*cookiep 39983221Smarcel : (l_off_t)(off + reclen); 40083221Smarcel linux_dirent.d_reclen = (l_ushort)linuxreclen; 40183221Smarcel strcpy(linux_dirent.d_name, bdp->d_name); 40283221Smarcel error = copyout(&linux_dirent, outp, 40383221Smarcel linuxreclen); 40483221Smarcel } 40583221Smarcel } 40683221Smarcel if (error) 40783221Smarcel goto out; 40883221Smarcel 40983221Smarcel inp += reclen; 41083221Smarcel if (cookiep) { 41183221Smarcel off = *cookiep++; 41283221Smarcel ncookies--; 41383221Smarcel } else 41483221Smarcel off += reclen; 41583221Smarcel 41683221Smarcel outp += linuxreclen; 41783221Smarcel resid -= linuxreclen; 41883221Smarcel len -= reclen; 41983221Smarcel if (justone) 42083221Smarcel break; 42110355Sswallace } 4229313Ssos 42383221Smarcel if (outp == (caddr_t)args->dirent) 42483221Smarcel goto again; 4259313Ssos 42683221Smarcel fp->f_offset = off; 42783221Smarcel if (justone) 42883221Smarcel nbytes = resid + linuxreclen; 42910355Sswallace 4309313Ssoseof: 43183366Sjulian td->td_retval[0] = nbytes - resid; 43283221Smarcel 4339313Ssosout: 43483221Smarcel if (cookies) 43583221Smarcel free(cookies, M_TEMP); 43683221Smarcel 43783366Sjulian VOP_UNLOCK(vp, 0, td); 43883221Smarcel free(buf, M_TEMP); 43983221Smarcel return (error); 4409313Ssos} 44114331Speter 44283221Smarcelint 44383366Sjulianlinux_getdents(struct thread *td, struct linux_getdents_args *args) 44483221Smarcel{ 44583221Smarcel 44683221Smarcel#ifdef DEBUG 44783221Smarcel if (ldebug(getdents)) 44883221Smarcel printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count); 44983221Smarcel#endif 45083221Smarcel 45183366Sjulian return (getdents_common(td, (struct linux_getdents64_args*)args, 0)); 45283221Smarcel} 45383221Smarcel 45483221Smarcelint 45583366Sjulianlinux_getdents64(struct thread *td, struct linux_getdents64_args *args) 45683221Smarcel{ 45783221Smarcel 45883221Smarcel#ifdef DEBUG 45983221Smarcel if (ldebug(getdents64)) 46083221Smarcel printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count); 46183221Smarcel#endif 46283221Smarcel 46383366Sjulian return (getdents_common(td, args, 1)); 46483221Smarcel} 46583221Smarcel 46614331Speter/* 46714331Speter * These exist mainly for hooks for doing /compat/linux translation. 46814331Speter */ 46914331Speter 47014331Speterint 47183366Sjulianlinux_access(struct thread *td, struct linux_access_args *args) 47214331Speter{ 47314331Speter struct access_args bsd; 47414331Speter caddr_t sg; 47514331Speter 47614331Speter sg = stackgap_init(); 47783366Sjulian CHECKALTEXIST(td, &sg, args->path); 47814331Speter 47914331Speter#ifdef DEBUG 48072543Sjlemon if (ldebug(access)) 48172543Sjlemon printf(ARGS(access, "%s, %d"), args->path, args->flags); 48214331Speter#endif 48314331Speter bsd.path = args->path; 48414331Speter bsd.flags = args->flags; 48514331Speter 48683366Sjulian return access(td, &bsd); 48714331Speter} 48814331Speter 48914331Speterint 49083366Sjulianlinux_unlink(struct thread *td, struct linux_unlink_args *args) 49114331Speter{ 49214331Speter struct unlink_args bsd; 49314331Speter caddr_t sg; 49414331Speter 49514331Speter sg = stackgap_init(); 49683366Sjulian CHECKALTEXIST(td, &sg, args->path); 49714331Speter 49814331Speter#ifdef DEBUG 49972543Sjlemon if (ldebug(unlink)) 50072543Sjlemon printf(ARGS(unlink, "%s"), args->path); 50114331Speter#endif 50214331Speter bsd.path = args->path; 50314331Speter 50483366Sjulian return unlink(td, &bsd); 50514331Speter} 50614331Speter 50714331Speterint 50883366Sjulianlinux_chdir(struct thread *td, struct linux_chdir_args *args) 50914331Speter{ 51014331Speter struct chdir_args bsd; 51114331Speter caddr_t sg; 51214331Speter 51314331Speter sg = stackgap_init(); 51483366Sjulian CHECKALTEXIST(td, &sg, args->path); 51514331Speter 51614331Speter#ifdef DEBUG 51772543Sjlemon if (ldebug(chdir)) 51872543Sjlemon printf(ARGS(chdir, "%s"), args->path); 51914331Speter#endif 52014331Speter bsd.path = args->path; 52114331Speter 52283366Sjulian return chdir(td, &bsd); 52314331Speter} 52414331Speter 52514331Speterint 52683366Sjulianlinux_chmod(struct thread *td, struct linux_chmod_args *args) 52714331Speter{ 52814331Speter struct chmod_args bsd; 52914331Speter caddr_t sg; 53014331Speter 53114331Speter sg = stackgap_init(); 53283366Sjulian CHECKALTEXIST(td, &sg, args->path); 53314331Speter 53414331Speter#ifdef DEBUG 53572543Sjlemon if (ldebug(chmod)) 53672543Sjlemon printf(ARGS(chmod, "%s, %d"), args->path, args->mode); 53714331Speter#endif 53814331Speter bsd.path = args->path; 53914331Speter bsd.mode = args->mode; 54014331Speter 54183366Sjulian return chmod(td, &bsd); 54214331Speter} 54314331Speter 54414331Speterint 54583366Sjulianlinux_mkdir(struct thread *td, struct linux_mkdir_args *args) 54614331Speter{ 54714331Speter struct mkdir_args bsd; 54814331Speter caddr_t sg; 54914331Speter 55014331Speter sg = stackgap_init(); 55183366Sjulian CHECKALTCREAT(td, &sg, args->path); 55214331Speter 55314331Speter#ifdef DEBUG 55472543Sjlemon if (ldebug(mkdir)) 55572543Sjlemon printf(ARGS(mkdir, "%s, %d"), args->path, args->mode); 55614331Speter#endif 55714331Speter bsd.path = args->path; 55814331Speter bsd.mode = args->mode; 55914331Speter 56083366Sjulian return mkdir(td, &bsd); 56114331Speter} 56214331Speter 56314331Speterint 56483366Sjulianlinux_rmdir(struct thread *td, struct linux_rmdir_args *args) 56514331Speter{ 56614331Speter struct rmdir_args bsd; 56714331Speter caddr_t sg; 56814331Speter 56914331Speter sg = stackgap_init(); 57083366Sjulian CHECKALTEXIST(td, &sg, args->path); 57114331Speter 57214331Speter#ifdef DEBUG 57372543Sjlemon if (ldebug(rmdir)) 57472543Sjlemon printf(ARGS(rmdir, "%s"), args->path); 57514331Speter#endif 57614331Speter bsd.path = args->path; 57714331Speter 57883366Sjulian return rmdir(td, &bsd); 57914331Speter} 58014331Speter 58114331Speterint 58283366Sjulianlinux_rename(struct thread *td, struct linux_rename_args *args) 58314331Speter{ 58414331Speter struct rename_args bsd; 58514331Speter caddr_t sg; 58614331Speter 58714331Speter sg = stackgap_init(); 58883366Sjulian CHECKALTEXIST(td, &sg, args->from); 58983366Sjulian CHECKALTCREAT(td, &sg, args->to); 59014331Speter 59114331Speter#ifdef DEBUG 59272543Sjlemon if (ldebug(rename)) 59372543Sjlemon printf(ARGS(rename, "%s, %s"), args->from, args->to); 59414331Speter#endif 59514331Speter bsd.from = args->from; 59614331Speter bsd.to = args->to; 59714331Speter 59883366Sjulian return rename(td, &bsd); 59914331Speter} 60014331Speter 60114331Speterint 60283366Sjulianlinux_symlink(struct thread *td, struct linux_symlink_args *args) 60314331Speter{ 60414331Speter struct symlink_args bsd; 60514331Speter caddr_t sg; 60614331Speter 60714331Speter sg = stackgap_init(); 60883366Sjulian CHECKALTEXIST(td, &sg, args->path); 60983366Sjulian CHECKALTCREAT(td, &sg, args->to); 61014331Speter 61114331Speter#ifdef DEBUG 61272543Sjlemon if (ldebug(symlink)) 61372543Sjlemon printf(ARGS(symlink, "%s, %s"), args->path, args->to); 61414331Speter#endif 61514331Speter bsd.path = args->path; 61614331Speter bsd.link = args->to; 61714331Speter 61883366Sjulian return symlink(td, &bsd); 61914331Speter} 62014331Speter 62114331Speterint 62283366Sjulianlinux_readlink(struct thread *td, struct linux_readlink_args *args) 62314331Speter{ 62414331Speter struct readlink_args bsd; 62514331Speter caddr_t sg; 62614331Speter 62714331Speter sg = stackgap_init(); 62883366Sjulian CHECKALTEXIST(td, &sg, args->name); 62914331Speter 63014331Speter#ifdef DEBUG 63172543Sjlemon if (ldebug(readlink)) 63272543Sjlemon printf(ARGS(readlink, "%s, %p, %d"), 63372543Sjlemon args->name, (void *)args->buf, args->count); 63414331Speter#endif 63514331Speter bsd.path = args->name; 63614331Speter bsd.buf = args->buf; 63714331Speter bsd.count = args->count; 63814331Speter 63983366Sjulian return readlink(td, &bsd); 64014331Speter} 64114331Speter 64214331Speterint 64383366Sjulianlinux_truncate(struct thread *td, struct linux_truncate_args *args) 64414331Speter{ 64542499Seivind struct truncate_args bsd; 64614331Speter caddr_t sg; 64714331Speter 64814331Speter sg = stackgap_init(); 64983366Sjulian CHECKALTEXIST(td, &sg, args->path); 65014331Speter 65114331Speter#ifdef DEBUG 65272543Sjlemon if (ldebug(truncate)) 65383221Smarcel printf(ARGS(truncate, "%s, %ld"), args->path, 65483221Smarcel (long)args->length); 65514331Speter#endif 65614331Speter bsd.path = args->path; 65732265Sjmb bsd.length = args->length; 65814331Speter 65983366Sjulian return truncate(td, &bsd); 66014331Speter} 66114331Speter 66249662Smarcelint 66383366Sjulianlinux_link(struct thread *td, struct linux_link_args *args) 66449662Smarcel{ 66549662Smarcel struct link_args bsd; 66649662Smarcel caddr_t sg; 66749662Smarcel 66849662Smarcel sg = stackgap_init(); 66983366Sjulian CHECKALTEXIST(td, &sg, args->path); 67083366Sjulian CHECKALTCREAT(td, &sg, args->to); 67149662Smarcel 67249662Smarcel#ifdef DEBUG 67372543Sjlemon if (ldebug(link)) 67472543Sjlemon printf(ARGS(link, "%s, %s"), args->path, args->to); 67549662Smarcel#endif 67649662Smarcel 67749662Smarcel bsd.path = args->path; 67849662Smarcel bsd.link = args->to; 67949662Smarcel 68083366Sjulian return link(td, &bsd); 68149662Smarcel} 68249788Smarcel 68368201Sobrien#ifndef __alpha__ 68453713Smarcelint 68583366Sjulianlinux_fdatasync(td, uap) 68683366Sjulian struct thread *td; 68753713Smarcel struct linux_fdatasync_args *uap; 68853713Smarcel{ 68953713Smarcel struct fsync_args bsd; 69053713Smarcel 69153713Smarcel bsd.fd = uap->fd; 69283366Sjulian return fsync(td, &bsd); 69353713Smarcel} 69468201Sobrien#endif /*!__alpha__*/ 69563285Smarcel 69663285Smarcelint 69783366Sjulianlinux_pread(td, uap) 69883366Sjulian struct thread *td; 69963285Smarcel struct linux_pread_args *uap; 70063285Smarcel{ 70163285Smarcel struct pread_args bsd; 70263285Smarcel 70363285Smarcel bsd.fd = uap->fd; 70463285Smarcel bsd.buf = uap->buf; 70563285Smarcel bsd.nbyte = uap->nbyte; 70663285Smarcel bsd.offset = uap->offset; 70783366Sjulian return pread(td, &bsd); 70863285Smarcel} 70963285Smarcel 71063285Smarcelint 71183366Sjulianlinux_pwrite(td, uap) 71283366Sjulian struct thread *td; 71363285Smarcel struct linux_pwrite_args *uap; 71463285Smarcel{ 71563285Smarcel struct pwrite_args bsd; 71663285Smarcel 71763285Smarcel bsd.fd = uap->fd; 71863285Smarcel bsd.buf = uap->buf; 71963285Smarcel bsd.nbyte = uap->nbyte; 72063285Smarcel bsd.offset = uap->offset; 72183366Sjulian return pwrite(td, &bsd); 72263285Smarcel} 72372538Sjlemon 72472538Sjlemonint 72583366Sjulianlinux_mount(struct thread *td, struct linux_mount_args *args) 72672538Sjlemon{ 72772538Sjlemon struct ufs_args ufs; 72872538Sjlemon char fstypename[MFSNAMELEN]; 72972538Sjlemon char mntonname[MNAMELEN], mntfromname[MNAMELEN]; 73073286Sadrian int error; 73173286Sadrian int fsflags; 73273286Sadrian const char *fstype; 73373286Sadrian void *fsdata; 73472538Sjlemon 73573286Sadrian error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1, 73673286Sadrian NULL); 73772538Sjlemon if (error) 73872538Sjlemon return (error); 73972538Sjlemon error = copyinstr(args->specialfile, mntfromname, MFSNAMELEN - 1, NULL); 74072538Sjlemon if (error) 74172538Sjlemon return (error); 74272538Sjlemon error = copyinstr(args->dir, mntonname, MFSNAMELEN - 1, NULL); 74372538Sjlemon if (error) 74472538Sjlemon return (error); 74572538Sjlemon 74672538Sjlemon#ifdef DEBUG 74772538Sjlemon if (ldebug(mount)) 74872538Sjlemon printf(ARGS(mount, "%s, %s, %s"), 74972538Sjlemon fstypename, mntfromname, mntonname); 75072538Sjlemon#endif 75172538Sjlemon 75272538Sjlemon if (strcmp(fstypename, "ext2") == 0) { 75373286Sadrian fstype = "ext2fs"; 75473286Sadrian fsdata = &ufs; 75572538Sjlemon ufs.fspec = mntfromname; 75672538Sjlemon#define DEFAULT_ROOTID -2 75772538Sjlemon ufs.export.ex_root = DEFAULT_ROOTID; 75872538Sjlemon ufs.export.ex_flags = 75972538Sjlemon args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0; 76072538Sjlemon } else if (strcmp(fstypename, "proc") == 0) { 76173286Sadrian fstype = "linprocfs"; 76273286Sadrian fsdata = NULL; 76372538Sjlemon } else { 76472538Sjlemon return (ENODEV); 76572538Sjlemon } 76672538Sjlemon 76773286Sadrian fsflags = 0; 76872538Sjlemon 76972538Sjlemon if ((args->rwflag & 0xffff0000) == 0xc0ed0000) { 77072538Sjlemon /* 77172538Sjlemon * Linux SYNC flag is not included; the closest equivalent 77272538Sjlemon * FreeBSD has is !ASYNC, which is our default. 77372538Sjlemon */ 77472538Sjlemon if (args->rwflag & LINUX_MS_RDONLY) 77573286Sadrian fsflags |= MNT_RDONLY; 77672538Sjlemon if (args->rwflag & LINUX_MS_NOSUID) 77773286Sadrian fsflags |= MNT_NOSUID; 77872538Sjlemon if (args->rwflag & LINUX_MS_NODEV) 77973286Sadrian fsflags |= MNT_NODEV; 78072538Sjlemon if (args->rwflag & LINUX_MS_NOEXEC) 78173286Sadrian fsflags |= MNT_NOEXEC; 78272538Sjlemon if (args->rwflag & LINUX_MS_REMOUNT) 78373286Sadrian fsflags |= MNT_UPDATE; 78472538Sjlemon } 78572538Sjlemon 78683366Sjulian return (vfs_mount(td, fstype, mntonname, fsflags, fsdata)); 78772538Sjlemon} 78872538Sjlemon 78972538Sjlemonint 79083366Sjulianlinux_oldumount(struct thread *td, struct linux_oldumount_args *args) 79172538Sjlemon{ 79283221Smarcel struct linux_umount_args args2; 79372538Sjlemon 79472538Sjlemon args2.path = args->path; 79572538Sjlemon args2.flags = 0; 79683366Sjulian return (linux_umount(td, &args2)); 79772538Sjlemon} 79872538Sjlemon 79972538Sjlemonint 80083366Sjulianlinux_umount(struct thread *td, struct linux_umount_args *args) 80172538Sjlemon{ 80272538Sjlemon struct unmount_args bsd; 80372538Sjlemon 80472538Sjlemon bsd.path = args->path; 80572538Sjlemon bsd.flags = args->flags; /* XXX correct? */ 80683366Sjulian return (unmount(td, &bsd)); 80772538Sjlemon} 80883221Smarcel 80983221Smarcel/* 81083221Smarcel * fcntl family of syscalls 81183221Smarcel */ 81283221Smarcel 81383221Smarcelstruct l_flock { 81483221Smarcel l_short l_type; 81583221Smarcel l_short l_whence; 81683221Smarcel l_off_t l_start; 81783221Smarcel l_off_t l_len; 81883221Smarcel l_pid_t l_pid; 81983221Smarcel}; 82083221Smarcel 82183221Smarcelstatic void 82283221Smarcellinux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock) 82383221Smarcel{ 82483221Smarcel switch (linux_flock->l_type) { 82583221Smarcel case LINUX_F_RDLCK: 82683221Smarcel bsd_flock->l_type = F_RDLCK; 82783221Smarcel break; 82883221Smarcel case LINUX_F_WRLCK: 82983221Smarcel bsd_flock->l_type = F_WRLCK; 83083221Smarcel break; 83183221Smarcel case LINUX_F_UNLCK: 83283221Smarcel bsd_flock->l_type = F_UNLCK; 83383221Smarcel break; 83483221Smarcel default: 83583221Smarcel bsd_flock->l_type = -1; 83683221Smarcel break; 83783221Smarcel } 83883221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 83983221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 84083221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 84183221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 84283221Smarcel} 84383221Smarcel 84483221Smarcelstatic void 84583221Smarcelbsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock) 84683221Smarcel{ 84783221Smarcel switch (bsd_flock->l_type) { 84883221Smarcel case F_RDLCK: 84983221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 85083221Smarcel break; 85183221Smarcel case F_WRLCK: 85283221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 85383221Smarcel break; 85483221Smarcel case F_UNLCK: 85583221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 85683221Smarcel break; 85783221Smarcel } 85883221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 85983221Smarcel linux_flock->l_start = (l_off_t)bsd_flock->l_start; 86083221Smarcel linux_flock->l_len = (l_off_t)bsd_flock->l_len; 86183221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 86283221Smarcel} 86383221Smarcel 86483221Smarcel#if defined(__i386__) 86583221Smarcelstruct l_flock64 { 86683221Smarcel l_short l_type; 86783221Smarcel l_short l_whence; 86883221Smarcel l_loff_t l_start; 86983221Smarcel l_loff_t l_len; 87083221Smarcel l_pid_t l_pid; 87183221Smarcel}; 87283221Smarcel 87383221Smarcelstatic void 87483221Smarcellinux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock) 87583221Smarcel{ 87683221Smarcel switch (linux_flock->l_type) { 87783221Smarcel case LINUX_F_RDLCK: 87883221Smarcel bsd_flock->l_type = F_RDLCK; 87983221Smarcel break; 88083221Smarcel case LINUX_F_WRLCK: 88183221Smarcel bsd_flock->l_type = F_WRLCK; 88283221Smarcel break; 88383221Smarcel case LINUX_F_UNLCK: 88483221Smarcel bsd_flock->l_type = F_UNLCK; 88583221Smarcel break; 88683221Smarcel default: 88783221Smarcel bsd_flock->l_type = -1; 88883221Smarcel break; 88983221Smarcel } 89083221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 89183221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 89283221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 89383221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 89483221Smarcel} 89583221Smarcel 89683221Smarcelstatic void 89783221Smarcelbsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) 89883221Smarcel{ 89983221Smarcel switch (bsd_flock->l_type) { 90083221Smarcel case F_RDLCK: 90183221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 90283221Smarcel break; 90383221Smarcel case F_WRLCK: 90483221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 90583221Smarcel break; 90683221Smarcel case F_UNLCK: 90783221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 90883221Smarcel break; 90983221Smarcel } 91083221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 91183221Smarcel linux_flock->l_start = (l_loff_t)bsd_flock->l_start; 91283221Smarcel linux_flock->l_len = (l_loff_t)bsd_flock->l_len; 91383221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 91483221Smarcel} 91583221Smarcel#endif /* __i386__ */ 91683221Smarcel 91783221Smarcel#if defined(__alpha__) 91883221Smarcel#define linux_fcntl64_args linux_fcntl_args 91983221Smarcel#endif 92083221Smarcel 92183221Smarcelstatic int 92283366Sjulianfcntl_common(struct thread *td, struct linux_fcntl64_args *args) 92383221Smarcel{ 92483221Smarcel struct fcntl_args fcntl_args; 92583221Smarcel struct filedesc *fdp; 92683221Smarcel struct file *fp; 92783221Smarcel int error, result; 92883221Smarcel 92983221Smarcel fcntl_args.fd = args->fd; 93083221Smarcel 93183221Smarcel switch (args->cmd) { 93283221Smarcel case LINUX_F_DUPFD: 93383221Smarcel fcntl_args.cmd = F_DUPFD; 93483221Smarcel fcntl_args.arg = args->arg; 93583366Sjulian return (fcntl(td, &fcntl_args)); 93683221Smarcel 93783221Smarcel case LINUX_F_GETFD: 93883221Smarcel fcntl_args.cmd = F_GETFD; 93983366Sjulian return (fcntl(td, &fcntl_args)); 94083221Smarcel 94183221Smarcel case LINUX_F_SETFD: 94283221Smarcel fcntl_args.cmd = F_SETFD; 94383221Smarcel fcntl_args.arg = args->arg; 94483366Sjulian return (fcntl(td, &fcntl_args)); 94583221Smarcel 94683221Smarcel case LINUX_F_GETFL: 94783221Smarcel fcntl_args.cmd = F_GETFL; 94883366Sjulian error = fcntl(td, &fcntl_args); 94983366Sjulian result = td->td_retval[0]; 95083366Sjulian td->td_retval[0] = 0; 95183221Smarcel if (result & O_RDONLY) 95283366Sjulian td->td_retval[0] |= LINUX_O_RDONLY; 95383221Smarcel if (result & O_WRONLY) 95483366Sjulian td->td_retval[0] |= LINUX_O_WRONLY; 95583221Smarcel if (result & O_RDWR) 95683366Sjulian td->td_retval[0] |= LINUX_O_RDWR; 95783221Smarcel if (result & O_NDELAY) 95883366Sjulian td->td_retval[0] |= LINUX_O_NONBLOCK; 95983221Smarcel if (result & O_APPEND) 96083366Sjulian td->td_retval[0] |= LINUX_O_APPEND; 96183221Smarcel if (result & O_FSYNC) 96283366Sjulian td->td_retval[0] |= LINUX_O_SYNC; 96383221Smarcel if (result & O_ASYNC) 96483366Sjulian td->td_retval[0] |= LINUX_FASYNC; 96583221Smarcel return (error); 96683221Smarcel 96783221Smarcel case LINUX_F_SETFL: 96883221Smarcel fcntl_args.arg = 0; 96983221Smarcel if (args->arg & LINUX_O_NDELAY) 97083221Smarcel fcntl_args.arg |= O_NONBLOCK; 97183221Smarcel if (args->arg & LINUX_O_APPEND) 97283221Smarcel fcntl_args.arg |= O_APPEND; 97383221Smarcel if (args->arg & LINUX_O_SYNC) 97483221Smarcel fcntl_args.arg |= O_FSYNC; 97583221Smarcel if (args->arg & LINUX_FASYNC) 97683221Smarcel fcntl_args.arg |= O_ASYNC; 97783221Smarcel fcntl_args.cmd = F_SETFL; 97883366Sjulian return (fcntl(td, &fcntl_args)); 97983221Smarcel 98083221Smarcel case LINUX_F_GETOWN: 98183221Smarcel fcntl_args.cmd = F_GETOWN; 98283366Sjulian return (fcntl(td, &fcntl_args)); 98383221Smarcel 98483221Smarcel case LINUX_F_SETOWN: 98583221Smarcel /* 98683221Smarcel * XXX some Linux applications depend on F_SETOWN having no 98783221Smarcel * significant effect for pipes (SIGIO is not delivered for 98883221Smarcel * pipes under Linux-2.2.35 at least). 98983221Smarcel */ 99083366Sjulian fdp = td->td_proc->p_fd; 99183221Smarcel if ((u_int)args->fd >= fdp->fd_nfiles || 99283221Smarcel (fp = fdp->fd_ofiles[args->fd]) == NULL) 99383221Smarcel return (EBADF); 99483221Smarcel if (fp->f_type == DTYPE_PIPE) 99583221Smarcel return (EINVAL); 99683221Smarcel 99783221Smarcel fcntl_args.cmd = F_SETOWN; 99883221Smarcel fcntl_args.arg = args->arg; 99983366Sjulian return (fcntl(td, &fcntl_args)); 100083221Smarcel } 100183221Smarcel 100283221Smarcel return (EINVAL); 100383221Smarcel} 100483221Smarcel 100583221Smarcelint 100683366Sjulianlinux_fcntl(struct thread *td, struct linux_fcntl_args *args) 100783221Smarcel{ 100883221Smarcel struct linux_fcntl64_args args64; 100983221Smarcel struct fcntl_args fcntl_args; 101083221Smarcel struct l_flock linux_flock; 101183221Smarcel struct flock *bsd_flock; 101283221Smarcel int error; 101383221Smarcel caddr_t sg; 101483221Smarcel 101583221Smarcel sg = stackgap_init(); 101683221Smarcel bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock)); 101783221Smarcel 101883221Smarcel#ifdef DEBUG 101983221Smarcel if (ldebug(fcntl)) 102083221Smarcel printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); 102183221Smarcel#endif 102283221Smarcel 102383221Smarcel switch (args->cmd) { 102483221Smarcel case LINUX_F_GETLK: 102583221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 102683221Smarcel sizeof(linux_flock)); 102783221Smarcel if (error) 102883221Smarcel return (error); 102983221Smarcel linux_to_bsd_flock(&linux_flock, bsd_flock); 103083221Smarcel fcntl_args.fd = args->fd; 103183221Smarcel fcntl_args.cmd = F_GETLK; 103283221Smarcel fcntl_args.arg = (long)bsd_flock; 103383366Sjulian error = fcntl(td, &fcntl_args); 103483221Smarcel if (error) 103583221Smarcel return (error); 103683221Smarcel bsd_to_linux_flock(bsd_flock, &linux_flock); 103783221Smarcel return (copyout(&linux_flock, (caddr_t)args->arg, 103883221Smarcel sizeof(linux_flock))); 103983221Smarcel 104083221Smarcel case LINUX_F_SETLK: 104183221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 104283221Smarcel sizeof(linux_flock)); 104383221Smarcel if (error) 104483221Smarcel return (error); 104583221Smarcel linux_to_bsd_flock(&linux_flock, bsd_flock); 104683221Smarcel fcntl_args.fd = args->fd; 104783221Smarcel fcntl_args.cmd = F_SETLK; 104883221Smarcel fcntl_args.arg = (long)bsd_flock; 104983366Sjulian return (fcntl(td, &fcntl_args)); 105083221Smarcel 105183221Smarcel case LINUX_F_SETLKW: 105283221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 105383221Smarcel sizeof(linux_flock)); 105483221Smarcel if (error) 105583221Smarcel return (error); 105683221Smarcel linux_to_bsd_flock(&linux_flock, bsd_flock); 105783221Smarcel fcntl_args.fd = args->fd; 105883221Smarcel fcntl_args.cmd = F_SETLKW; 105983221Smarcel fcntl_args.arg = (long)bsd_flock; 106083366Sjulian return (fcntl(td, &fcntl_args)); 106183221Smarcel } 106283221Smarcel 106383221Smarcel args64.fd = args->fd; 106483221Smarcel args64.cmd = args->cmd; 106583221Smarcel args64.arg = args->arg; 106683366Sjulian return (fcntl_common(td, &args64)); 106783221Smarcel} 106883221Smarcel 106983221Smarcel#if defined(__i386__) 107083221Smarcelint 107183366Sjulianlinux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) 107283221Smarcel{ 107383221Smarcel struct fcntl_args fcntl_args; 107483221Smarcel struct l_flock64 linux_flock; 107583221Smarcel struct flock *bsd_flock; 107683221Smarcel int error; 107783221Smarcel caddr_t sg; 107883221Smarcel 107983221Smarcel sg = stackgap_init(); 108083221Smarcel bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock)); 108183221Smarcel 108283221Smarcel#ifdef DEBUG 108383221Smarcel if (ldebug(fcntl64)) 108483221Smarcel printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd); 108583221Smarcel#endif 108683221Smarcel 108783221Smarcel switch (args->cmd) { 108883221Smarcel case LINUX_F_GETLK: 108983221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 109083221Smarcel sizeof(linux_flock)); 109183221Smarcel if (error) 109283221Smarcel return (error); 109383221Smarcel linux_to_bsd_flock64(&linux_flock, bsd_flock); 109483221Smarcel fcntl_args.fd = args->fd; 109583221Smarcel fcntl_args.cmd = F_GETLK; 109683221Smarcel fcntl_args.arg = (long)bsd_flock; 109783366Sjulian error = fcntl(td, &fcntl_args); 109883221Smarcel if (error) 109983221Smarcel return (error); 110083221Smarcel bsd_to_linux_flock64(bsd_flock, &linux_flock); 110183221Smarcel return (copyout(&linux_flock, (caddr_t)args->arg, 110283221Smarcel sizeof(linux_flock))); 110383221Smarcel 110483221Smarcel case LINUX_F_SETLK: 110583221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 110683221Smarcel sizeof(linux_flock)); 110783221Smarcel if (error) 110883221Smarcel return (error); 110983221Smarcel linux_to_bsd_flock64(&linux_flock, bsd_flock); 111083221Smarcel fcntl_args.fd = args->fd; 111183221Smarcel fcntl_args.cmd = F_SETLK; 111283221Smarcel fcntl_args.arg = (long)bsd_flock; 111383366Sjulian return (fcntl(td, &fcntl_args)); 111483221Smarcel 111583221Smarcel case LINUX_F_SETLKW: 111683221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 111783221Smarcel sizeof(linux_flock)); 111883221Smarcel if (error) 111983221Smarcel return (error); 112083221Smarcel linux_to_bsd_flock64(&linux_flock, bsd_flock); 112183221Smarcel fcntl_args.fd = args->fd; 112283221Smarcel fcntl_args.cmd = F_SETLKW; 112383221Smarcel fcntl_args.arg = (long)bsd_flock; 112483366Sjulian return (fcntl(td, &fcntl_args)); 112583221Smarcel } 112683221Smarcel 112783366Sjulian return (fcntl_common(td, args)); 112883221Smarcel} 112983221Smarcel#endif /* __i386__ */ 113085022Smarcel 113185022Smarcelint 113285022Smarcellinux_chown(struct thread *td, struct linux_chown_args *args) 113385022Smarcel{ 113485022Smarcel struct chown_args bsd; 113585022Smarcel caddr_t sg; 113685022Smarcel 113785022Smarcel sg = stackgap_init(); 113885022Smarcel CHECKALTEXIST(td, &sg, args->path); 113985022Smarcel 114085022Smarcel#ifdef DEBUG 114185022Smarcel if (ldebug(chown)) 114285022Smarcel printf(ARGS(chown, "%s, %d, %d"), args->path, args->uid, 114385022Smarcel args->gid); 114485022Smarcel#endif 114585022Smarcel 114685022Smarcel bsd.path = args->path; 114785022Smarcel bsd.uid = args->uid; 114885022Smarcel bsd.gid = args->gid; 114985022Smarcel return (chown(td, &bsd)); 115085022Smarcel} 115185022Smarcel 115285022Smarcelint 115385022Smarcellinux_lchown(struct thread *td, struct linux_lchown_args *args) 115485022Smarcel{ 115585022Smarcel struct lchown_args bsd; 115685022Smarcel caddr_t sg; 115785022Smarcel 115885022Smarcel sg = stackgap_init(); 115985022Smarcel CHECKALTEXIST(td, &sg, args->path); 116085022Smarcel 116185022Smarcel#ifdef DEBUG 116285022Smarcel if (ldebug(lchown)) 116385022Smarcel printf(ARGS(lchown, "%s, %d, %d"), args->path, args->uid, 116485022Smarcel args->gid); 116585022Smarcel#endif 116685022Smarcel 116785022Smarcel bsd.path = args->path; 116885022Smarcel bsd.uid = args->uid; 116985022Smarcel bsd.gid = args->gid; 117085022Smarcel return (lchown(td, &bsd)); 117185022Smarcel} 1172