linux_file.c revision 89319
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 89319 2002-01-14 00:13:45Z alfred $ 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)) { 13889306Salfred struct file *fp; 1399313Ssos 14089319Salfred error = fget(td, td->td_retval[0], &fp); 14170061Sjhb PROC_UNLOCK(p); 14289319Salfred if (!error) { 14389319Salfred if (fp->f_type == DTYPE_VNODE) 14489319Salfred fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td); 14589319Salfred fdrop(fp, td); 14689319Salfred } 14770061Sjhb } else 14870061Sjhb PROC_UNLOCK(p); 14914331Speter#ifdef DEBUG 15072543Sjlemon if (ldebug(open)) 15172543Sjlemon printf(LMSG("open returns error %d"), error); 15214331Speter#endif 1539313Ssos return error; 1549313Ssos} 1559313Ssos 1569313Ssosint 15783366Sjulianlinux_lseek(struct thread *td, struct linux_lseek_args *args) 1589313Ssos{ 1599313Ssos 16012858Speter struct lseek_args /* { 16112858Speter int fd; 1629313Ssos int pad; 16312858Speter off_t offset; 1649313Ssos int whence; 16512858Speter } */ tmp_args; 1669313Ssos int error; 1679313Ssos 1689313Ssos#ifdef DEBUG 16972543Sjlemon if (ldebug(lseek)) 17072543Sjlemon printf(ARGS(lseek, "%d, %ld, %d"), 17183221Smarcel args->fdes, (long)args->off, args->whence); 1729313Ssos#endif 17312858Speter tmp_args.fd = args->fdes; 17412858Speter tmp_args.offset = (off_t)args->off; 1759313Ssos tmp_args.whence = args->whence; 17683366Sjulian error = lseek(td, &tmp_args); 1779313Ssos return error; 1789313Ssos} 1799313Ssos 18068201Sobrien#ifndef __alpha__ 18114331Speterint 18283366Sjulianlinux_llseek(struct thread *td, struct linux_llseek_args *args) 18314331Speter{ 18414331Speter struct lseek_args bsd_args; 18514331Speter int error; 18614331Speter off_t off; 18714331Speter 18814331Speter#ifdef DEBUG 18972543Sjlemon if (ldebug(llseek)) 19072543Sjlemon printf(ARGS(llseek, "%d, %d:%d, %d"), 19172543Sjlemon args->fd, args->ohigh, args->olow, args->whence); 19214331Speter#endif 19314331Speter off = (args->olow) | (((off_t) args->ohigh) << 32); 19414331Speter 19514331Speter bsd_args.fd = args->fd; 19614331Speter bsd_args.offset = off; 19714331Speter bsd_args.whence = args->whence; 19814331Speter 19983366Sjulian if ((error = lseek(td, &bsd_args))) 20014331Speter return error; 20114331Speter 20283366Sjulian if ((error = copyout(td->td_retval, (caddr_t)args->res, sizeof (off_t)))) 20314331Speter return error; 20414331Speter 20583366Sjulian td->td_retval[0] = 0; 20614331Speter return 0; 20714331Speter} 20868201Sobrien#endif /*!__alpha__*/ 20914331Speter 21068201Sobrien#ifndef __alpha__ 2119313Ssosint 21283366Sjulianlinux_readdir(struct thread *td, struct linux_readdir_args *args) 2139313Ssos{ 21414331Speter struct linux_getdents_args lda; 21514331Speter 21614331Speter lda.fd = args->fd; 21714331Speter lda.dent = args->dent; 21814331Speter lda.count = 1; 21983366Sjulian return linux_getdents(td, &lda); 22014331Speter} 22168201Sobrien#endif /*!__alpha__*/ 22214331Speter 22383221Smarcel/* 22483221Smarcel * Note that linux_getdents(2) and linux_getdents64(2) have the same 22583221Smarcel * arguments. They only differ in the definition of struct dirent they 22683221Smarcel * operate on. We use this to common the code, with the exception of 22783221Smarcel * accessing struct dirent. Note that linux_readdir(2) is implemented 22883221Smarcel * by means of linux_getdents(2). In this case we never operate on 22983221Smarcel * struct dirent64 and thus don't need to handle it... 23083221Smarcel */ 23183221Smarcel 23283221Smarcelstruct l_dirent { 23383221Smarcel l_long d_ino; 23483221Smarcel l_off_t d_off; 23583221Smarcel l_ushort d_reclen; 23683221Smarcel char d_name[LINUX_NAME_MAX + 1]; 23783221Smarcel}; 23883221Smarcel 23983221Smarcelstruct l_dirent64 { 24083221Smarcel uint64_t d_ino; 24183221Smarcel int64_t d_off; 24283221Smarcel l_ushort d_reclen; 24383221Smarcel u_char d_type; 24483221Smarcel char d_name[LINUX_NAME_MAX + 1]; 24583221Smarcel}; 24683221Smarcel 24783221Smarcel#define LINUX_RECLEN(de,namlen) \ 24883221Smarcel ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1)) 24983221Smarcel 25083221Smarcel#define LINUX_DIRBLKSIZ 512 25183221Smarcel 25283221Smarcelstatic int 25383366Sjuliangetdents_common(struct thread *td, struct linux_getdents64_args *args, 25483221Smarcel int is64bit) 25514331Speter{ 25683221Smarcel register struct dirent *bdp; 25783221Smarcel struct vnode *vp; 25883221Smarcel caddr_t inp, buf; /* BSD-format */ 25983221Smarcel int len, reclen; /* BSD-format */ 26083221Smarcel caddr_t outp; /* Linux-format */ 26183221Smarcel int resid, linuxreclen=0; /* Linux-format */ 26283221Smarcel struct file *fp; 26383221Smarcel struct uio auio; 26483221Smarcel struct iovec aiov; 26583221Smarcel struct vattr va; 26683221Smarcel off_t off; 26783221Smarcel struct l_dirent linux_dirent; 26883221Smarcel struct l_dirent64 linux_dirent64; 26983221Smarcel int buflen, error, eofflag, nbytes, justone; 27083221Smarcel u_long *cookies = NULL, *cookiep; 27183221Smarcel int ncookies; 2729313Ssos 27383366Sjulian if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0) 27483221Smarcel return (error); 2759313Ssos 27689306Salfred if ((fp->f_flag & FREAD) == 0) { 27789306Salfred fdrop(fp, td); 27883221Smarcel return (EBADF); 27989306Salfred } 2809313Ssos 28183221Smarcel vp = (struct vnode *) fp->f_data; 28289306Salfred if (vp->v_type != VDIR) { 28389306Salfred fdrop(fp, td); 28483221Smarcel return (EINVAL); 28589306Salfred } 2869313Ssos 28789306Salfred if ((error = VOP_GETATTR(vp, &va, td->td_proc->p_ucred, td))) { 28889306Salfred fdrop(fp, td); 28983221Smarcel return (error); 29089306Salfred } 2919313Ssos 29283221Smarcel nbytes = args->count; 29383221Smarcel if (nbytes == 1) { 29483221Smarcel /* readdir(2) case. Always struct dirent. */ 29589306Salfred if (is64bit) { 29689306Salfred fdrop(fp, td); 29783221Smarcel return (EINVAL); 29889306Salfred } 29983221Smarcel nbytes = sizeof(linux_dirent); 30083221Smarcel justone = 1; 30183221Smarcel } else 30283221Smarcel justone = 0; 3039313Ssos 30483221Smarcel off = fp->f_offset; 3059313Ssos 30683221Smarcel buflen = max(LINUX_DIRBLKSIZ, nbytes); 30783221Smarcel buflen = min(buflen, MAXBSIZE); 30883221Smarcel buf = malloc(buflen, M_TEMP, M_WAITOK); 30983366Sjulian vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 31083221Smarcel 3119313Ssosagain: 31283221Smarcel aiov.iov_base = buf; 31383221Smarcel aiov.iov_len = buflen; 31483221Smarcel auio.uio_iov = &aiov; 31583221Smarcel auio.uio_iovcnt = 1; 31683221Smarcel auio.uio_rw = UIO_READ; 31783221Smarcel auio.uio_segflg = UIO_SYSSPACE; 31883366Sjulian auio.uio_td = td; 31983221Smarcel auio.uio_resid = buflen; 32083221Smarcel auio.uio_offset = off; 3219313Ssos 32283221Smarcel if (cookies) { 32383221Smarcel free(cookies, M_TEMP); 32483221Smarcel cookies = NULL; 32583221Smarcel } 32624654Sdfr 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{ 48514331Speter struct access_args bsd; 48614331Speter caddr_t sg; 48714331Speter 48814331Speter sg = stackgap_init(); 48983366Sjulian CHECKALTEXIST(td, &sg, args->path); 49014331Speter 49114331Speter#ifdef DEBUG 49272543Sjlemon if (ldebug(access)) 49372543Sjlemon printf(ARGS(access, "%s, %d"), args->path, args->flags); 49414331Speter#endif 49514331Speter bsd.path = args->path; 49614331Speter bsd.flags = args->flags; 49714331Speter 49883366Sjulian return access(td, &bsd); 49914331Speter} 50014331Speter 50114331Speterint 50283366Sjulianlinux_unlink(struct thread *td, struct linux_unlink_args *args) 50314331Speter{ 50414331Speter struct unlink_args bsd; 50514331Speter caddr_t sg; 50614331Speter 50714331Speter sg = stackgap_init(); 50883366Sjulian CHECKALTEXIST(td, &sg, args->path); 50914331Speter 51014331Speter#ifdef DEBUG 51172543Sjlemon if (ldebug(unlink)) 51272543Sjlemon printf(ARGS(unlink, "%s"), args->path); 51314331Speter#endif 51414331Speter bsd.path = args->path; 51514331Speter 51683366Sjulian return unlink(td, &bsd); 51714331Speter} 51814331Speter 51914331Speterint 52083366Sjulianlinux_chdir(struct thread *td, struct linux_chdir_args *args) 52114331Speter{ 52214331Speter struct chdir_args bsd; 52314331Speter caddr_t sg; 52414331Speter 52514331Speter sg = stackgap_init(); 52683366Sjulian CHECKALTEXIST(td, &sg, args->path); 52714331Speter 52814331Speter#ifdef DEBUG 52972543Sjlemon if (ldebug(chdir)) 53072543Sjlemon printf(ARGS(chdir, "%s"), args->path); 53114331Speter#endif 53214331Speter bsd.path = args->path; 53314331Speter 53483366Sjulian return chdir(td, &bsd); 53514331Speter} 53614331Speter 53714331Speterint 53883366Sjulianlinux_chmod(struct thread *td, struct linux_chmod_args *args) 53914331Speter{ 54014331Speter struct chmod_args bsd; 54114331Speter caddr_t sg; 54214331Speter 54314331Speter sg = stackgap_init(); 54483366Sjulian CHECKALTEXIST(td, &sg, args->path); 54514331Speter 54614331Speter#ifdef DEBUG 54772543Sjlemon if (ldebug(chmod)) 54872543Sjlemon printf(ARGS(chmod, "%s, %d"), args->path, args->mode); 54914331Speter#endif 55014331Speter bsd.path = args->path; 55114331Speter bsd.mode = args->mode; 55214331Speter 55383366Sjulian return chmod(td, &bsd); 55414331Speter} 55514331Speter 55614331Speterint 55783366Sjulianlinux_mkdir(struct thread *td, struct linux_mkdir_args *args) 55814331Speter{ 55914331Speter struct mkdir_args bsd; 56014331Speter caddr_t sg; 56114331Speter 56214331Speter sg = stackgap_init(); 56383366Sjulian CHECKALTCREAT(td, &sg, args->path); 56414331Speter 56514331Speter#ifdef DEBUG 56672543Sjlemon if (ldebug(mkdir)) 56772543Sjlemon printf(ARGS(mkdir, "%s, %d"), args->path, args->mode); 56814331Speter#endif 56914331Speter bsd.path = args->path; 57014331Speter bsd.mode = args->mode; 57114331Speter 57283366Sjulian return mkdir(td, &bsd); 57314331Speter} 57414331Speter 57514331Speterint 57683366Sjulianlinux_rmdir(struct thread *td, struct linux_rmdir_args *args) 57714331Speter{ 57814331Speter struct rmdir_args bsd; 57914331Speter caddr_t sg; 58014331Speter 58114331Speter sg = stackgap_init(); 58283366Sjulian CHECKALTEXIST(td, &sg, args->path); 58314331Speter 58414331Speter#ifdef DEBUG 58572543Sjlemon if (ldebug(rmdir)) 58672543Sjlemon printf(ARGS(rmdir, "%s"), args->path); 58714331Speter#endif 58814331Speter bsd.path = args->path; 58914331Speter 59083366Sjulian return rmdir(td, &bsd); 59114331Speter} 59214331Speter 59314331Speterint 59483366Sjulianlinux_rename(struct thread *td, struct linux_rename_args *args) 59514331Speter{ 59614331Speter struct rename_args bsd; 59714331Speter caddr_t sg; 59814331Speter 59914331Speter sg = stackgap_init(); 60083366Sjulian CHECKALTEXIST(td, &sg, args->from); 60183366Sjulian CHECKALTCREAT(td, &sg, args->to); 60214331Speter 60314331Speter#ifdef DEBUG 60472543Sjlemon if (ldebug(rename)) 60572543Sjlemon printf(ARGS(rename, "%s, %s"), args->from, args->to); 60614331Speter#endif 60714331Speter bsd.from = args->from; 60814331Speter bsd.to = args->to; 60914331Speter 61083366Sjulian return rename(td, &bsd); 61114331Speter} 61214331Speter 61314331Speterint 61483366Sjulianlinux_symlink(struct thread *td, struct linux_symlink_args *args) 61514331Speter{ 61614331Speter struct symlink_args bsd; 61714331Speter caddr_t sg; 61814331Speter 61914331Speter sg = stackgap_init(); 62083366Sjulian CHECKALTEXIST(td, &sg, args->path); 62183366Sjulian CHECKALTCREAT(td, &sg, args->to); 62214331Speter 62314331Speter#ifdef DEBUG 62472543Sjlemon if (ldebug(symlink)) 62572543Sjlemon printf(ARGS(symlink, "%s, %s"), args->path, args->to); 62614331Speter#endif 62714331Speter bsd.path = args->path; 62814331Speter bsd.link = args->to; 62914331Speter 63083366Sjulian return symlink(td, &bsd); 63114331Speter} 63214331Speter 63314331Speterint 63483366Sjulianlinux_readlink(struct thread *td, struct linux_readlink_args *args) 63514331Speter{ 63614331Speter struct readlink_args bsd; 63714331Speter caddr_t sg; 63814331Speter 63914331Speter sg = stackgap_init(); 64083366Sjulian CHECKALTEXIST(td, &sg, args->name); 64114331Speter 64214331Speter#ifdef DEBUG 64372543Sjlemon if (ldebug(readlink)) 64472543Sjlemon printf(ARGS(readlink, "%s, %p, %d"), 64572543Sjlemon args->name, (void *)args->buf, args->count); 64614331Speter#endif 64714331Speter bsd.path = args->name; 64814331Speter bsd.buf = args->buf; 64914331Speter bsd.count = args->count; 65014331Speter 65183366Sjulian return readlink(td, &bsd); 65214331Speter} 65314331Speter 65414331Speterint 65583366Sjulianlinux_truncate(struct thread *td, struct linux_truncate_args *args) 65614331Speter{ 65742499Seivind struct truncate_args bsd; 65814331Speter caddr_t sg; 65914331Speter 66014331Speter sg = stackgap_init(); 66183366Sjulian CHECKALTEXIST(td, &sg, args->path); 66214331Speter 66314331Speter#ifdef DEBUG 66472543Sjlemon if (ldebug(truncate)) 66583221Smarcel printf(ARGS(truncate, "%s, %ld"), args->path, 66683221Smarcel (long)args->length); 66714331Speter#endif 66814331Speter bsd.path = args->path; 66932265Sjmb bsd.length = args->length; 67014331Speter 67183366Sjulian return truncate(td, &bsd); 67214331Speter} 67314331Speter 67449662Smarcelint 67583366Sjulianlinux_link(struct thread *td, struct linux_link_args *args) 67649662Smarcel{ 67749662Smarcel struct link_args bsd; 67849662Smarcel caddr_t sg; 67949662Smarcel 68049662Smarcel sg = stackgap_init(); 68183366Sjulian CHECKALTEXIST(td, &sg, args->path); 68283366Sjulian CHECKALTCREAT(td, &sg, args->to); 68349662Smarcel 68449662Smarcel#ifdef DEBUG 68572543Sjlemon if (ldebug(link)) 68672543Sjlemon printf(ARGS(link, "%s, %s"), args->path, args->to); 68749662Smarcel#endif 68849662Smarcel 68949662Smarcel bsd.path = args->path; 69049662Smarcel bsd.link = args->to; 69149662Smarcel 69283366Sjulian return link(td, &bsd); 69349662Smarcel} 69449788Smarcel 69568201Sobrien#ifndef __alpha__ 69653713Smarcelint 69783366Sjulianlinux_fdatasync(td, uap) 69883366Sjulian struct thread *td; 69953713Smarcel struct linux_fdatasync_args *uap; 70053713Smarcel{ 70153713Smarcel struct fsync_args bsd; 70253713Smarcel 70353713Smarcel bsd.fd = uap->fd; 70483366Sjulian return fsync(td, &bsd); 70553713Smarcel} 70668201Sobrien#endif /*!__alpha__*/ 70763285Smarcel 70863285Smarcelint 70983366Sjulianlinux_pread(td, uap) 71083366Sjulian struct thread *td; 71163285Smarcel struct linux_pread_args *uap; 71263285Smarcel{ 71363285Smarcel struct pread_args bsd; 71463285Smarcel 71563285Smarcel bsd.fd = uap->fd; 71663285Smarcel bsd.buf = uap->buf; 71763285Smarcel bsd.nbyte = uap->nbyte; 71863285Smarcel bsd.offset = uap->offset; 71983366Sjulian return pread(td, &bsd); 72063285Smarcel} 72163285Smarcel 72263285Smarcelint 72383366Sjulianlinux_pwrite(td, uap) 72483366Sjulian struct thread *td; 72563285Smarcel struct linux_pwrite_args *uap; 72663285Smarcel{ 72763285Smarcel struct pwrite_args bsd; 72863285Smarcel 72963285Smarcel bsd.fd = uap->fd; 73063285Smarcel bsd.buf = uap->buf; 73163285Smarcel bsd.nbyte = uap->nbyte; 73263285Smarcel bsd.offset = uap->offset; 73383366Sjulian return pwrite(td, &bsd); 73463285Smarcel} 73572538Sjlemon 73672538Sjlemonint 73783366Sjulianlinux_mount(struct thread *td, struct linux_mount_args *args) 73872538Sjlemon{ 73972538Sjlemon struct ufs_args ufs; 74072538Sjlemon char fstypename[MFSNAMELEN]; 74172538Sjlemon char mntonname[MNAMELEN], mntfromname[MNAMELEN]; 74273286Sadrian int error; 74373286Sadrian int fsflags; 74473286Sadrian const char *fstype; 74573286Sadrian void *fsdata; 74672538Sjlemon 74773286Sadrian error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1, 74873286Sadrian NULL); 74972538Sjlemon if (error) 75072538Sjlemon return (error); 75172538Sjlemon error = copyinstr(args->specialfile, mntfromname, MFSNAMELEN - 1, NULL); 75272538Sjlemon if (error) 75372538Sjlemon return (error); 75472538Sjlemon error = copyinstr(args->dir, mntonname, MFSNAMELEN - 1, NULL); 75572538Sjlemon if (error) 75672538Sjlemon return (error); 75772538Sjlemon 75872538Sjlemon#ifdef DEBUG 75972538Sjlemon if (ldebug(mount)) 76072538Sjlemon printf(ARGS(mount, "%s, %s, %s"), 76172538Sjlemon fstypename, mntfromname, mntonname); 76272538Sjlemon#endif 76372538Sjlemon 76472538Sjlemon if (strcmp(fstypename, "ext2") == 0) { 76573286Sadrian fstype = "ext2fs"; 76673286Sadrian fsdata = &ufs; 76772538Sjlemon ufs.fspec = mntfromname; 76872538Sjlemon#define DEFAULT_ROOTID -2 76972538Sjlemon ufs.export.ex_root = DEFAULT_ROOTID; 77072538Sjlemon ufs.export.ex_flags = 77172538Sjlemon args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0; 77272538Sjlemon } else if (strcmp(fstypename, "proc") == 0) { 77373286Sadrian fstype = "linprocfs"; 77473286Sadrian fsdata = NULL; 77572538Sjlemon } else { 77672538Sjlemon return (ENODEV); 77772538Sjlemon } 77872538Sjlemon 77973286Sadrian fsflags = 0; 78072538Sjlemon 78172538Sjlemon if ((args->rwflag & 0xffff0000) == 0xc0ed0000) { 78272538Sjlemon /* 78372538Sjlemon * Linux SYNC flag is not included; the closest equivalent 78472538Sjlemon * FreeBSD has is !ASYNC, which is our default. 78572538Sjlemon */ 78672538Sjlemon if (args->rwflag & LINUX_MS_RDONLY) 78773286Sadrian fsflags |= MNT_RDONLY; 78872538Sjlemon if (args->rwflag & LINUX_MS_NOSUID) 78973286Sadrian fsflags |= MNT_NOSUID; 79072538Sjlemon if (args->rwflag & LINUX_MS_NODEV) 79173286Sadrian fsflags |= MNT_NODEV; 79272538Sjlemon if (args->rwflag & LINUX_MS_NOEXEC) 79373286Sadrian fsflags |= MNT_NOEXEC; 79472538Sjlemon if (args->rwflag & LINUX_MS_REMOUNT) 79573286Sadrian fsflags |= MNT_UPDATE; 79672538Sjlemon } 79772538Sjlemon 79883366Sjulian return (vfs_mount(td, fstype, mntonname, fsflags, fsdata)); 79972538Sjlemon} 80072538Sjlemon 80172538Sjlemonint 80283366Sjulianlinux_oldumount(struct thread *td, struct linux_oldumount_args *args) 80372538Sjlemon{ 80483221Smarcel struct linux_umount_args args2; 80572538Sjlemon 80672538Sjlemon args2.path = args->path; 80772538Sjlemon args2.flags = 0; 80883366Sjulian return (linux_umount(td, &args2)); 80972538Sjlemon} 81072538Sjlemon 81172538Sjlemonint 81283366Sjulianlinux_umount(struct thread *td, struct linux_umount_args *args) 81372538Sjlemon{ 81472538Sjlemon struct unmount_args bsd; 81572538Sjlemon 81672538Sjlemon bsd.path = args->path; 81772538Sjlemon bsd.flags = args->flags; /* XXX correct? */ 81883366Sjulian return (unmount(td, &bsd)); 81972538Sjlemon} 82083221Smarcel 82183221Smarcel/* 82283221Smarcel * fcntl family of syscalls 82383221Smarcel */ 82483221Smarcel 82583221Smarcelstruct l_flock { 82683221Smarcel l_short l_type; 82783221Smarcel l_short l_whence; 82883221Smarcel l_off_t l_start; 82983221Smarcel l_off_t l_len; 83083221Smarcel l_pid_t l_pid; 83183221Smarcel}; 83283221Smarcel 83383221Smarcelstatic void 83483221Smarcellinux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock) 83583221Smarcel{ 83683221Smarcel switch (linux_flock->l_type) { 83783221Smarcel case LINUX_F_RDLCK: 83883221Smarcel bsd_flock->l_type = F_RDLCK; 83983221Smarcel break; 84083221Smarcel case LINUX_F_WRLCK: 84183221Smarcel bsd_flock->l_type = F_WRLCK; 84283221Smarcel break; 84383221Smarcel case LINUX_F_UNLCK: 84483221Smarcel bsd_flock->l_type = F_UNLCK; 84583221Smarcel break; 84683221Smarcel default: 84783221Smarcel bsd_flock->l_type = -1; 84883221Smarcel break; 84983221Smarcel } 85083221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 85183221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 85283221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 85383221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 85483221Smarcel} 85583221Smarcel 85683221Smarcelstatic void 85783221Smarcelbsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock) 85883221Smarcel{ 85983221Smarcel switch (bsd_flock->l_type) { 86083221Smarcel case F_RDLCK: 86183221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 86283221Smarcel break; 86383221Smarcel case F_WRLCK: 86483221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 86583221Smarcel break; 86683221Smarcel case F_UNLCK: 86783221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 86883221Smarcel break; 86983221Smarcel } 87083221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 87183221Smarcel linux_flock->l_start = (l_off_t)bsd_flock->l_start; 87283221Smarcel linux_flock->l_len = (l_off_t)bsd_flock->l_len; 87383221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 87483221Smarcel} 87583221Smarcel 87683221Smarcel#if defined(__i386__) 87783221Smarcelstruct l_flock64 { 87883221Smarcel l_short l_type; 87983221Smarcel l_short l_whence; 88083221Smarcel l_loff_t l_start; 88183221Smarcel l_loff_t l_len; 88283221Smarcel l_pid_t l_pid; 88383221Smarcel}; 88483221Smarcel 88583221Smarcelstatic void 88683221Smarcellinux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock) 88783221Smarcel{ 88883221Smarcel switch (linux_flock->l_type) { 88983221Smarcel case LINUX_F_RDLCK: 89083221Smarcel bsd_flock->l_type = F_RDLCK; 89183221Smarcel break; 89283221Smarcel case LINUX_F_WRLCK: 89383221Smarcel bsd_flock->l_type = F_WRLCK; 89483221Smarcel break; 89583221Smarcel case LINUX_F_UNLCK: 89683221Smarcel bsd_flock->l_type = F_UNLCK; 89783221Smarcel break; 89883221Smarcel default: 89983221Smarcel bsd_flock->l_type = -1; 90083221Smarcel break; 90183221Smarcel } 90283221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 90383221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 90483221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 90583221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 90683221Smarcel} 90783221Smarcel 90883221Smarcelstatic void 90983221Smarcelbsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) 91083221Smarcel{ 91183221Smarcel switch (bsd_flock->l_type) { 91283221Smarcel case F_RDLCK: 91383221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 91483221Smarcel break; 91583221Smarcel case F_WRLCK: 91683221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 91783221Smarcel break; 91883221Smarcel case F_UNLCK: 91983221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 92083221Smarcel break; 92183221Smarcel } 92283221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 92383221Smarcel linux_flock->l_start = (l_loff_t)bsd_flock->l_start; 92483221Smarcel linux_flock->l_len = (l_loff_t)bsd_flock->l_len; 92583221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 92683221Smarcel} 92783221Smarcel#endif /* __i386__ */ 92883221Smarcel 92983221Smarcel#if defined(__alpha__) 93083221Smarcel#define linux_fcntl64_args linux_fcntl_args 93183221Smarcel#endif 93283221Smarcel 93383221Smarcelstatic int 93483366Sjulianfcntl_common(struct thread *td, struct linux_fcntl64_args *args) 93583221Smarcel{ 93683221Smarcel struct fcntl_args fcntl_args; 93783221Smarcel struct file *fp; 93883221Smarcel int error, result; 93983221Smarcel 94083221Smarcel fcntl_args.fd = args->fd; 94183221Smarcel 94283221Smarcel switch (args->cmd) { 94383221Smarcel case LINUX_F_DUPFD: 94483221Smarcel fcntl_args.cmd = F_DUPFD; 94583221Smarcel fcntl_args.arg = args->arg; 94683366Sjulian return (fcntl(td, &fcntl_args)); 94783221Smarcel 94883221Smarcel case LINUX_F_GETFD: 94983221Smarcel fcntl_args.cmd = F_GETFD; 95083366Sjulian return (fcntl(td, &fcntl_args)); 95183221Smarcel 95283221Smarcel case LINUX_F_SETFD: 95383221Smarcel fcntl_args.cmd = F_SETFD; 95483221Smarcel fcntl_args.arg = args->arg; 95583366Sjulian return (fcntl(td, &fcntl_args)); 95683221Smarcel 95783221Smarcel case LINUX_F_GETFL: 95883221Smarcel fcntl_args.cmd = F_GETFL; 95983366Sjulian error = fcntl(td, &fcntl_args); 96083366Sjulian result = td->td_retval[0]; 96183366Sjulian td->td_retval[0] = 0; 96283221Smarcel if (result & O_RDONLY) 96383366Sjulian td->td_retval[0] |= LINUX_O_RDONLY; 96483221Smarcel if (result & O_WRONLY) 96583366Sjulian td->td_retval[0] |= LINUX_O_WRONLY; 96683221Smarcel if (result & O_RDWR) 96783366Sjulian td->td_retval[0] |= LINUX_O_RDWR; 96883221Smarcel if (result & O_NDELAY) 96983366Sjulian td->td_retval[0] |= LINUX_O_NONBLOCK; 97083221Smarcel if (result & O_APPEND) 97183366Sjulian td->td_retval[0] |= LINUX_O_APPEND; 97283221Smarcel if (result & O_FSYNC) 97383366Sjulian td->td_retval[0] |= LINUX_O_SYNC; 97483221Smarcel if (result & O_ASYNC) 97583366Sjulian td->td_retval[0] |= LINUX_FASYNC; 97683221Smarcel return (error); 97783221Smarcel 97883221Smarcel case LINUX_F_SETFL: 97983221Smarcel fcntl_args.arg = 0; 98083221Smarcel if (args->arg & LINUX_O_NDELAY) 98183221Smarcel fcntl_args.arg |= O_NONBLOCK; 98283221Smarcel if (args->arg & LINUX_O_APPEND) 98383221Smarcel fcntl_args.arg |= O_APPEND; 98483221Smarcel if (args->arg & LINUX_O_SYNC) 98583221Smarcel fcntl_args.arg |= O_FSYNC; 98683221Smarcel if (args->arg & LINUX_FASYNC) 98783221Smarcel fcntl_args.arg |= O_ASYNC; 98883221Smarcel fcntl_args.cmd = F_SETFL; 98983366Sjulian return (fcntl(td, &fcntl_args)); 99083221Smarcel 99183221Smarcel case LINUX_F_GETOWN: 99283221Smarcel fcntl_args.cmd = F_GETOWN; 99383366Sjulian return (fcntl(td, &fcntl_args)); 99483221Smarcel 99583221Smarcel case LINUX_F_SETOWN: 99683221Smarcel /* 99783221Smarcel * XXX some Linux applications depend on F_SETOWN having no 99883221Smarcel * significant effect for pipes (SIGIO is not delivered for 99983221Smarcel * pipes under Linux-2.2.35 at least). 100083221Smarcel */ 100189319Salfred error = fget(td, args->fd, &fp); 100289319Salfred if (error) 100389319Salfred return (error); 100489306Salfred if (fp->f_type == DTYPE_PIPE) { 100589306Salfred fdrop(fp, td); 100683221Smarcel return (EINVAL); 100789306Salfred } 100889306Salfred fdrop(fp, td); 100983221Smarcel 101083221Smarcel fcntl_args.cmd = F_SETOWN; 101183221Smarcel fcntl_args.arg = args->arg; 101283366Sjulian return (fcntl(td, &fcntl_args)); 101383221Smarcel } 101483221Smarcel 101583221Smarcel return (EINVAL); 101683221Smarcel} 101783221Smarcel 101883221Smarcelint 101983366Sjulianlinux_fcntl(struct thread *td, struct linux_fcntl_args *args) 102083221Smarcel{ 102183221Smarcel struct linux_fcntl64_args args64; 102283221Smarcel struct fcntl_args fcntl_args; 102383221Smarcel struct l_flock linux_flock; 102483221Smarcel struct flock *bsd_flock; 102583221Smarcel int error; 102683221Smarcel caddr_t sg; 102783221Smarcel 102883221Smarcel sg = stackgap_init(); 102983221Smarcel bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock)); 103083221Smarcel 103183221Smarcel#ifdef DEBUG 103283221Smarcel if (ldebug(fcntl)) 103383221Smarcel printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); 103483221Smarcel#endif 103583221Smarcel 103683221Smarcel switch (args->cmd) { 103783221Smarcel case LINUX_F_GETLK: 103883221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 103983221Smarcel sizeof(linux_flock)); 104083221Smarcel if (error) 104183221Smarcel return (error); 104283221Smarcel linux_to_bsd_flock(&linux_flock, bsd_flock); 104383221Smarcel fcntl_args.fd = args->fd; 104483221Smarcel fcntl_args.cmd = F_GETLK; 104583221Smarcel fcntl_args.arg = (long)bsd_flock; 104683366Sjulian error = fcntl(td, &fcntl_args); 104783221Smarcel if (error) 104883221Smarcel return (error); 104983221Smarcel bsd_to_linux_flock(bsd_flock, &linux_flock); 105083221Smarcel return (copyout(&linux_flock, (caddr_t)args->arg, 105183221Smarcel sizeof(linux_flock))); 105283221Smarcel 105383221Smarcel case LINUX_F_SETLK: 105483221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 105583221Smarcel sizeof(linux_flock)); 105683221Smarcel if (error) 105783221Smarcel return (error); 105883221Smarcel linux_to_bsd_flock(&linux_flock, bsd_flock); 105983221Smarcel fcntl_args.fd = args->fd; 106083221Smarcel fcntl_args.cmd = F_SETLK; 106183221Smarcel fcntl_args.arg = (long)bsd_flock; 106283366Sjulian return (fcntl(td, &fcntl_args)); 106383221Smarcel 106483221Smarcel case LINUX_F_SETLKW: 106583221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 106683221Smarcel sizeof(linux_flock)); 106783221Smarcel if (error) 106883221Smarcel return (error); 106983221Smarcel linux_to_bsd_flock(&linux_flock, bsd_flock); 107083221Smarcel fcntl_args.fd = args->fd; 107183221Smarcel fcntl_args.cmd = F_SETLKW; 107283221Smarcel fcntl_args.arg = (long)bsd_flock; 107383366Sjulian return (fcntl(td, &fcntl_args)); 107483221Smarcel } 107583221Smarcel 107683221Smarcel args64.fd = args->fd; 107783221Smarcel args64.cmd = args->cmd; 107883221Smarcel args64.arg = args->arg; 107983366Sjulian return (fcntl_common(td, &args64)); 108083221Smarcel} 108183221Smarcel 108283221Smarcel#if defined(__i386__) 108383221Smarcelint 108483366Sjulianlinux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) 108583221Smarcel{ 108683221Smarcel struct fcntl_args fcntl_args; 108783221Smarcel struct l_flock64 linux_flock; 108883221Smarcel struct flock *bsd_flock; 108983221Smarcel int error; 109083221Smarcel caddr_t sg; 109183221Smarcel 109283221Smarcel sg = stackgap_init(); 109383221Smarcel bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock)); 109483221Smarcel 109583221Smarcel#ifdef DEBUG 109683221Smarcel if (ldebug(fcntl64)) 109783221Smarcel printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd); 109883221Smarcel#endif 109983221Smarcel 110083221Smarcel switch (args->cmd) { 110183221Smarcel case LINUX_F_GETLK: 110283221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 110383221Smarcel sizeof(linux_flock)); 110483221Smarcel if (error) 110583221Smarcel return (error); 110683221Smarcel linux_to_bsd_flock64(&linux_flock, bsd_flock); 110783221Smarcel fcntl_args.fd = args->fd; 110883221Smarcel fcntl_args.cmd = F_GETLK; 110983221Smarcel fcntl_args.arg = (long)bsd_flock; 111083366Sjulian error = fcntl(td, &fcntl_args); 111183221Smarcel if (error) 111283221Smarcel return (error); 111383221Smarcel bsd_to_linux_flock64(bsd_flock, &linux_flock); 111483221Smarcel return (copyout(&linux_flock, (caddr_t)args->arg, 111583221Smarcel sizeof(linux_flock))); 111683221Smarcel 111783221Smarcel case LINUX_F_SETLK: 111883221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 111983221Smarcel sizeof(linux_flock)); 112083221Smarcel if (error) 112183221Smarcel return (error); 112283221Smarcel linux_to_bsd_flock64(&linux_flock, bsd_flock); 112383221Smarcel fcntl_args.fd = args->fd; 112483221Smarcel fcntl_args.cmd = F_SETLK; 112583221Smarcel fcntl_args.arg = (long)bsd_flock; 112683366Sjulian return (fcntl(td, &fcntl_args)); 112783221Smarcel 112883221Smarcel case LINUX_F_SETLKW: 112983221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 113083221Smarcel sizeof(linux_flock)); 113183221Smarcel if (error) 113283221Smarcel return (error); 113383221Smarcel linux_to_bsd_flock64(&linux_flock, bsd_flock); 113483221Smarcel fcntl_args.fd = args->fd; 113583221Smarcel fcntl_args.cmd = F_SETLKW; 113683221Smarcel fcntl_args.arg = (long)bsd_flock; 113783366Sjulian return (fcntl(td, &fcntl_args)); 113883221Smarcel } 113983221Smarcel 114083366Sjulian return (fcntl_common(td, args)); 114183221Smarcel} 114283221Smarcel#endif /* __i386__ */ 114385022Smarcel 114485022Smarcelint 114585022Smarcellinux_chown(struct thread *td, struct linux_chown_args *args) 114685022Smarcel{ 114785022Smarcel struct chown_args bsd; 114885022Smarcel caddr_t sg; 114985022Smarcel 115085022Smarcel sg = stackgap_init(); 115185022Smarcel CHECKALTEXIST(td, &sg, args->path); 115285022Smarcel 115385022Smarcel#ifdef DEBUG 115485022Smarcel if (ldebug(chown)) 115585022Smarcel printf(ARGS(chown, "%s, %d, %d"), args->path, args->uid, 115685022Smarcel args->gid); 115785022Smarcel#endif 115885022Smarcel 115985022Smarcel bsd.path = args->path; 116085022Smarcel bsd.uid = args->uid; 116185022Smarcel bsd.gid = args->gid; 116285022Smarcel return (chown(td, &bsd)); 116385022Smarcel} 116485022Smarcel 116585022Smarcelint 116685022Smarcellinux_lchown(struct thread *td, struct linux_lchown_args *args) 116785022Smarcel{ 116885022Smarcel struct lchown_args bsd; 116985022Smarcel caddr_t sg; 117085022Smarcel 117185022Smarcel sg = stackgap_init(); 117285022Smarcel CHECKALTEXIST(td, &sg, args->path); 117385022Smarcel 117485022Smarcel#ifdef DEBUG 117585022Smarcel if (ldebug(lchown)) 117685022Smarcel printf(ARGS(lchown, "%s, %d, %d"), args->path, args->uid, 117785022Smarcel args->gid); 117885022Smarcel#endif 117985022Smarcel 118085022Smarcel bsd.path = args->path; 118185022Smarcel bsd.uid = args->uid; 118285022Smarcel bsd.gid = args->gid; 118385022Smarcel return (lchown(td, &bsd)); 118485022Smarcel} 1185