linux_file.c revision 99687
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 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 99687 2002-07-09 19:25:43Z robert $ 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 } 14791140Stanimura } else { 14870061Sjhb PROC_UNLOCK(p); 14914331Speter#ifdef DEBUG 15072543Sjlemon if (ldebug(open)) 15172543Sjlemon printf(LMSG("open returns error %d"), error); 15214331Speter#endif 15391140Stanimura } 1549313Ssos return error; 1559313Ssos} 1569313Ssos 1579313Ssosint 15883366Sjulianlinux_lseek(struct thread *td, struct linux_lseek_args *args) 1599313Ssos{ 1609313Ssos 16112858Speter struct lseek_args /* { 16212858Speter int fd; 1639313Ssos int pad; 16412858Speter off_t offset; 1659313Ssos int whence; 16612858Speter } */ tmp_args; 1679313Ssos int error; 1689313Ssos 1699313Ssos#ifdef DEBUG 17072543Sjlemon if (ldebug(lseek)) 17172543Sjlemon printf(ARGS(lseek, "%d, %ld, %d"), 17283221Smarcel args->fdes, (long)args->off, args->whence); 1739313Ssos#endif 17412858Speter tmp_args.fd = args->fdes; 17512858Speter tmp_args.offset = (off_t)args->off; 1769313Ssos tmp_args.whence = args->whence; 17783366Sjulian error = lseek(td, &tmp_args); 1789313Ssos return error; 1799313Ssos} 1809313Ssos 18168201Sobrien#ifndef __alpha__ 18214331Speterint 18383366Sjulianlinux_llseek(struct thread *td, struct linux_llseek_args *args) 18414331Speter{ 18514331Speter struct lseek_args bsd_args; 18614331Speter int error; 18714331Speter off_t off; 18814331Speter 18914331Speter#ifdef DEBUG 19072543Sjlemon if (ldebug(llseek)) 19172543Sjlemon printf(ARGS(llseek, "%d, %d:%d, %d"), 19272543Sjlemon args->fd, args->ohigh, args->olow, args->whence); 19314331Speter#endif 19414331Speter off = (args->olow) | (((off_t) args->ohigh) << 32); 19514331Speter 19614331Speter bsd_args.fd = args->fd; 19714331Speter bsd_args.offset = off; 19814331Speter bsd_args.whence = args->whence; 19914331Speter 20083366Sjulian if ((error = lseek(td, &bsd_args))) 20114331Speter return error; 20214331Speter 20383366Sjulian if ((error = copyout(td->td_retval, (caddr_t)args->res, sizeof (off_t)))) 20414331Speter return error; 20514331Speter 20683366Sjulian td->td_retval[0] = 0; 20714331Speter return 0; 20814331Speter} 20968201Sobrien#endif /*!__alpha__*/ 21014331Speter 21168201Sobrien#ifndef __alpha__ 2129313Ssosint 21383366Sjulianlinux_readdir(struct thread *td, struct linux_readdir_args *args) 2149313Ssos{ 21514331Speter struct linux_getdents_args lda; 21614331Speter 21714331Speter lda.fd = args->fd; 21814331Speter lda.dent = args->dent; 21914331Speter lda.count = 1; 22083366Sjulian return linux_getdents(td, &lda); 22114331Speter} 22268201Sobrien#endif /*!__alpha__*/ 22314331Speter 22483221Smarcel/* 22583221Smarcel * Note that linux_getdents(2) and linux_getdents64(2) have the same 22683221Smarcel * arguments. They only differ in the definition of struct dirent they 22783221Smarcel * operate on. We use this to common the code, with the exception of 22883221Smarcel * accessing struct dirent. Note that linux_readdir(2) is implemented 22983221Smarcel * by means of linux_getdents(2). In this case we never operate on 23083221Smarcel * struct dirent64 and thus don't need to handle it... 23183221Smarcel */ 23283221Smarcel 23383221Smarcelstruct l_dirent { 23483221Smarcel l_long d_ino; 23583221Smarcel l_off_t d_off; 23683221Smarcel l_ushort d_reclen; 23783221Smarcel char d_name[LINUX_NAME_MAX + 1]; 23883221Smarcel}; 23983221Smarcel 24083221Smarcelstruct l_dirent64 { 24183221Smarcel uint64_t d_ino; 24283221Smarcel int64_t d_off; 24383221Smarcel l_ushort d_reclen; 24483221Smarcel u_char d_type; 24583221Smarcel char d_name[LINUX_NAME_MAX + 1]; 24683221Smarcel}; 24783221Smarcel 24883221Smarcel#define LINUX_RECLEN(de,namlen) \ 24983221Smarcel ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1)) 25083221Smarcel 25183221Smarcel#define LINUX_DIRBLKSIZ 512 25283221Smarcel 25383221Smarcelstatic int 25483366Sjuliangetdents_common(struct thread *td, struct linux_getdents64_args *args, 25583221Smarcel int is64bit) 25614331Speter{ 25783221Smarcel register struct dirent *bdp; 25883221Smarcel struct vnode *vp; 25983221Smarcel caddr_t inp, buf; /* BSD-format */ 26083221Smarcel int len, reclen; /* BSD-format */ 26183221Smarcel caddr_t outp; /* Linux-format */ 26283221Smarcel int resid, linuxreclen=0; /* Linux-format */ 26383221Smarcel struct file *fp; 26483221Smarcel struct uio auio; 26583221Smarcel struct iovec aiov; 26683221Smarcel struct vattr va; 26783221Smarcel off_t off; 26883221Smarcel struct l_dirent linux_dirent; 26983221Smarcel struct l_dirent64 linux_dirent64; 27083221Smarcel int buflen, error, eofflag, nbytes, justone; 27183221Smarcel u_long *cookies = NULL, *cookiep; 27283221Smarcel int ncookies; 2739313Ssos 27483366Sjulian if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0) 27583221Smarcel return (error); 2769313Ssos 27789306Salfred if ((fp->f_flag & FREAD) == 0) { 27889306Salfred fdrop(fp, td); 27983221Smarcel return (EBADF); 28089306Salfred } 2819313Ssos 28283221Smarcel vp = (struct vnode *) fp->f_data; 28389306Salfred if (vp->v_type != VDIR) { 28489306Salfred fdrop(fp, td); 28583221Smarcel return (EINVAL); 28689306Salfred } 2879313Ssos 28891406Sjhb if ((error = VOP_GETATTR(vp, &va, td->td_ucred, td))) { 28989306Salfred fdrop(fp, td); 29083221Smarcel return (error); 29189306Salfred } 2929313Ssos 29383221Smarcel nbytes = args->count; 29483221Smarcel if (nbytes == 1) { 29583221Smarcel /* readdir(2) case. Always struct dirent. */ 29689306Salfred if (is64bit) { 29789306Salfred fdrop(fp, td); 29883221Smarcel return (EINVAL); 29989306Salfred } 30083221Smarcel nbytes = sizeof(linux_dirent); 30183221Smarcel justone = 1; 30283221Smarcel } else 30383221Smarcel justone = 0; 3049313Ssos 30583221Smarcel off = fp->f_offset; 3069313Ssos 30783221Smarcel buflen = max(LINUX_DIRBLKSIZ, nbytes); 30883221Smarcel buflen = min(buflen, MAXBSIZE); 30983221Smarcel buf = malloc(buflen, M_TEMP, M_WAITOK); 31083366Sjulian vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 31183221Smarcel 3129313Ssosagain: 31383221Smarcel aiov.iov_base = buf; 31483221Smarcel aiov.iov_len = buflen; 31583221Smarcel auio.uio_iov = &aiov; 31683221Smarcel auio.uio_iovcnt = 1; 31783221Smarcel auio.uio_rw = UIO_READ; 31883221Smarcel auio.uio_segflg = UIO_SYSSPACE; 31983366Sjulian auio.uio_td = td; 32083221Smarcel auio.uio_resid = buflen; 32183221Smarcel auio.uio_offset = off; 3229313Ssos 32383221Smarcel if (cookies) { 32483221Smarcel free(cookies, M_TEMP); 32583221Smarcel cookies = NULL; 32683221Smarcel } 32724654Sdfr 32883221Smarcel if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, 32983221Smarcel &cookies))) 33083221Smarcel goto out; 3319313Ssos 33283221Smarcel inp = buf; 33383221Smarcel outp = (caddr_t)args->dirent; 33483221Smarcel resid = nbytes; 33583221Smarcel if ((len = buflen - auio.uio_resid) <= 0) 33683221Smarcel goto eof; 3379313Ssos 33883221Smarcel cookiep = cookies; 33924654Sdfr 34083221Smarcel if (cookies) { 34183221Smarcel /* 34283221Smarcel * When using cookies, the vfs has the option of reading from 34383221Smarcel * a different offset than that supplied (UFS truncates the 34483221Smarcel * offset to a block boundary to make sure that it never reads 34583221Smarcel * partway through a directory entry, even if the directory 34683221Smarcel * has been compacted). 34783221Smarcel */ 34883221Smarcel while (len > 0 && ncookies > 0 && *cookiep <= off) { 34983221Smarcel bdp = (struct dirent *) inp; 35083221Smarcel len -= bdp->d_reclen; 35183221Smarcel inp += bdp->d_reclen; 35283221Smarcel cookiep++; 35383221Smarcel ncookies--; 35483221Smarcel } 35524654Sdfr } 35624654Sdfr 35783221Smarcel while (len > 0) { 35883221Smarcel if (cookiep && ncookies == 0) 35983221Smarcel break; 36083221Smarcel bdp = (struct dirent *) inp; 36183221Smarcel reclen = bdp->d_reclen; 36283221Smarcel if (reclen & 3) { 36383221Smarcel error = EFAULT; 36483221Smarcel goto out; 36583221Smarcel } 36683221Smarcel 36783221Smarcel if (bdp->d_fileno == 0) { 36883221Smarcel inp += reclen; 36983221Smarcel if (cookiep) { 37083221Smarcel off = *cookiep++; 37183221Smarcel ncookies--; 37283221Smarcel } else 37383221Smarcel off += reclen; 37483221Smarcel 37583221Smarcel len -= reclen; 37683221Smarcel continue; 37783221Smarcel } 37883221Smarcel 37983221Smarcel linuxreclen = (is64bit) 38083221Smarcel ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen) 38183221Smarcel : LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 38283221Smarcel 38383221Smarcel if (reclen > len || resid < linuxreclen) { 38483221Smarcel outp++; 38583221Smarcel break; 38683221Smarcel } 38783221Smarcel 38883221Smarcel if (justone) { 38983221Smarcel /* readdir(2) case. */ 39083221Smarcel linux_dirent.d_ino = (l_long)bdp->d_fileno; 39183221Smarcel linux_dirent.d_off = (l_off_t)linuxreclen; 39283221Smarcel linux_dirent.d_reclen = (l_ushort)bdp->d_namlen; 39383221Smarcel strcpy(linux_dirent.d_name, bdp->d_name); 39483221Smarcel error = copyout(&linux_dirent, outp, linuxreclen); 39583221Smarcel } else { 39683221Smarcel if (is64bit) { 39783221Smarcel linux_dirent64.d_ino = bdp->d_fileno; 39883221Smarcel linux_dirent64.d_off = (cookiep) 39983221Smarcel ? (l_off_t)*cookiep 40083221Smarcel : (l_off_t)(off + reclen); 40183221Smarcel linux_dirent64.d_reclen = 40283221Smarcel (l_ushort)linuxreclen; 40383221Smarcel linux_dirent64.d_type = bdp->d_type; 40483221Smarcel strcpy(linux_dirent64.d_name, bdp->d_name); 40583221Smarcel error = copyout(&linux_dirent64, outp, 40683221Smarcel linuxreclen); 40783221Smarcel } else { 40883221Smarcel linux_dirent.d_ino = bdp->d_fileno; 40983221Smarcel linux_dirent.d_off = (cookiep) 41083221Smarcel ? (l_off_t)*cookiep 41183221Smarcel : (l_off_t)(off + reclen); 41283221Smarcel linux_dirent.d_reclen = (l_ushort)linuxreclen; 41383221Smarcel strcpy(linux_dirent.d_name, bdp->d_name); 41483221Smarcel error = copyout(&linux_dirent, outp, 41583221Smarcel linuxreclen); 41683221Smarcel } 41783221Smarcel } 41883221Smarcel if (error) 41983221Smarcel goto out; 42083221Smarcel 42183221Smarcel inp += reclen; 42283221Smarcel if (cookiep) { 42383221Smarcel off = *cookiep++; 42483221Smarcel ncookies--; 42583221Smarcel } else 42683221Smarcel off += reclen; 42783221Smarcel 42883221Smarcel outp += linuxreclen; 42983221Smarcel resid -= linuxreclen; 43083221Smarcel len -= reclen; 43183221Smarcel if (justone) 43283221Smarcel break; 43310355Sswallace } 4349313Ssos 43583221Smarcel if (outp == (caddr_t)args->dirent) 43683221Smarcel goto again; 4379313Ssos 43883221Smarcel fp->f_offset = off; 43983221Smarcel if (justone) 44083221Smarcel nbytes = resid + linuxreclen; 44110355Sswallace 4429313Ssoseof: 44383366Sjulian td->td_retval[0] = nbytes - resid; 44483221Smarcel 4459313Ssosout: 44683221Smarcel if (cookies) 44783221Smarcel free(cookies, M_TEMP); 44883221Smarcel 44983366Sjulian VOP_UNLOCK(vp, 0, td); 45089306Salfred fdrop(fp, td); 45183221Smarcel free(buf, M_TEMP); 45283221Smarcel return (error); 4539313Ssos} 45414331Speter 45583221Smarcelint 45683366Sjulianlinux_getdents(struct thread *td, struct linux_getdents_args *args) 45783221Smarcel{ 45883221Smarcel 45983221Smarcel#ifdef DEBUG 46083221Smarcel if (ldebug(getdents)) 46183221Smarcel printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count); 46283221Smarcel#endif 46383221Smarcel 46483366Sjulian return (getdents_common(td, (struct linux_getdents64_args*)args, 0)); 46583221Smarcel} 46683221Smarcel 46783221Smarcelint 46883366Sjulianlinux_getdents64(struct thread *td, struct linux_getdents64_args *args) 46983221Smarcel{ 47083221Smarcel 47183221Smarcel#ifdef DEBUG 47283221Smarcel if (ldebug(getdents64)) 47383221Smarcel printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count); 47483221Smarcel#endif 47583221Smarcel 47683366Sjulian return (getdents_common(td, args, 1)); 47783221Smarcel} 47883221Smarcel 47914331Speter/* 48014331Speter * These exist mainly for hooks for doing /compat/linux translation. 48114331Speter */ 48214331Speter 48314331Speterint 48483366Sjulianlinux_access(struct thread *td, struct linux_access_args *args) 48514331Speter{ 48614331Speter struct access_args bsd; 48714331Speter caddr_t sg; 48814331Speter 48914331Speter sg = stackgap_init(); 49083366Sjulian CHECKALTEXIST(td, &sg, args->path); 49114331Speter 49214331Speter#ifdef DEBUG 49372543Sjlemon if (ldebug(access)) 49472543Sjlemon printf(ARGS(access, "%s, %d"), args->path, args->flags); 49514331Speter#endif 49614331Speter bsd.path = args->path; 49714331Speter bsd.flags = args->flags; 49814331Speter 49983366Sjulian return access(td, &bsd); 50014331Speter} 50114331Speter 50214331Speterint 50383366Sjulianlinux_unlink(struct thread *td, struct linux_unlink_args *args) 50414331Speter{ 50514331Speter struct unlink_args bsd; 50614331Speter caddr_t sg; 50714331Speter 50814331Speter sg = stackgap_init(); 50983366Sjulian CHECKALTEXIST(td, &sg, args->path); 51014331Speter 51114331Speter#ifdef DEBUG 51272543Sjlemon if (ldebug(unlink)) 51372543Sjlemon printf(ARGS(unlink, "%s"), args->path); 51414331Speter#endif 51514331Speter bsd.path = args->path; 51614331Speter 51783366Sjulian return unlink(td, &bsd); 51814331Speter} 51914331Speter 52014331Speterint 52183366Sjulianlinux_chdir(struct thread *td, struct linux_chdir_args *args) 52214331Speter{ 52314331Speter struct chdir_args bsd; 52414331Speter caddr_t sg; 52514331Speter 52614331Speter sg = stackgap_init(); 52783366Sjulian CHECKALTEXIST(td, &sg, args->path); 52814331Speter 52914331Speter#ifdef DEBUG 53072543Sjlemon if (ldebug(chdir)) 53172543Sjlemon printf(ARGS(chdir, "%s"), args->path); 53214331Speter#endif 53314331Speter bsd.path = args->path; 53414331Speter 53583366Sjulian return chdir(td, &bsd); 53614331Speter} 53714331Speter 53814331Speterint 53983366Sjulianlinux_chmod(struct thread *td, struct linux_chmod_args *args) 54014331Speter{ 54114331Speter struct chmod_args bsd; 54214331Speter caddr_t sg; 54314331Speter 54414331Speter sg = stackgap_init(); 54583366Sjulian CHECKALTEXIST(td, &sg, args->path); 54614331Speter 54714331Speter#ifdef DEBUG 54872543Sjlemon if (ldebug(chmod)) 54972543Sjlemon printf(ARGS(chmod, "%s, %d"), args->path, args->mode); 55014331Speter#endif 55114331Speter bsd.path = args->path; 55214331Speter bsd.mode = args->mode; 55314331Speter 55483366Sjulian return chmod(td, &bsd); 55514331Speter} 55614331Speter 55714331Speterint 55883366Sjulianlinux_mkdir(struct thread *td, struct linux_mkdir_args *args) 55914331Speter{ 56014331Speter struct mkdir_args bsd; 56114331Speter caddr_t sg; 56214331Speter 56314331Speter sg = stackgap_init(); 56483366Sjulian CHECKALTCREAT(td, &sg, args->path); 56514331Speter 56614331Speter#ifdef DEBUG 56772543Sjlemon if (ldebug(mkdir)) 56872543Sjlemon printf(ARGS(mkdir, "%s, %d"), args->path, args->mode); 56914331Speter#endif 57014331Speter bsd.path = args->path; 57114331Speter bsd.mode = args->mode; 57214331Speter 57383366Sjulian return mkdir(td, &bsd); 57414331Speter} 57514331Speter 57614331Speterint 57783366Sjulianlinux_rmdir(struct thread *td, struct linux_rmdir_args *args) 57814331Speter{ 57914331Speter struct rmdir_args bsd; 58014331Speter caddr_t sg; 58114331Speter 58214331Speter sg = stackgap_init(); 58383366Sjulian CHECKALTEXIST(td, &sg, args->path); 58414331Speter 58514331Speter#ifdef DEBUG 58672543Sjlemon if (ldebug(rmdir)) 58772543Sjlemon printf(ARGS(rmdir, "%s"), args->path); 58814331Speter#endif 58914331Speter bsd.path = args->path; 59014331Speter 59183366Sjulian return rmdir(td, &bsd); 59214331Speter} 59314331Speter 59414331Speterint 59583366Sjulianlinux_rename(struct thread *td, struct linux_rename_args *args) 59614331Speter{ 59714331Speter struct rename_args bsd; 59814331Speter caddr_t sg; 59914331Speter 60014331Speter sg = stackgap_init(); 60183366Sjulian CHECKALTEXIST(td, &sg, args->from); 60283366Sjulian CHECKALTCREAT(td, &sg, args->to); 60314331Speter 60414331Speter#ifdef DEBUG 60572543Sjlemon if (ldebug(rename)) 60672543Sjlemon printf(ARGS(rename, "%s, %s"), args->from, args->to); 60714331Speter#endif 60814331Speter bsd.from = args->from; 60914331Speter bsd.to = args->to; 61014331Speter 61183366Sjulian return rename(td, &bsd); 61214331Speter} 61314331Speter 61414331Speterint 61583366Sjulianlinux_symlink(struct thread *td, struct linux_symlink_args *args) 61614331Speter{ 61714331Speter struct symlink_args bsd; 61814331Speter caddr_t sg; 61914331Speter 62014331Speter sg = stackgap_init(); 62183366Sjulian CHECKALTEXIST(td, &sg, args->path); 62283366Sjulian CHECKALTCREAT(td, &sg, args->to); 62314331Speter 62414331Speter#ifdef DEBUG 62572543Sjlemon if (ldebug(symlink)) 62672543Sjlemon printf(ARGS(symlink, "%s, %s"), args->path, args->to); 62714331Speter#endif 62814331Speter bsd.path = args->path; 62914331Speter bsd.link = args->to; 63014331Speter 63183366Sjulian return symlink(td, &bsd); 63214331Speter} 63314331Speter 63414331Speterint 63583366Sjulianlinux_readlink(struct thread *td, struct linux_readlink_args *args) 63614331Speter{ 63714331Speter struct readlink_args bsd; 63814331Speter caddr_t sg; 63914331Speter 64014331Speter sg = stackgap_init(); 64183366Sjulian CHECKALTEXIST(td, &sg, args->name); 64214331Speter 64314331Speter#ifdef DEBUG 64472543Sjlemon if (ldebug(readlink)) 64572543Sjlemon printf(ARGS(readlink, "%s, %p, %d"), 64672543Sjlemon args->name, (void *)args->buf, args->count); 64714331Speter#endif 64814331Speter bsd.path = args->name; 64914331Speter bsd.buf = args->buf; 65014331Speter bsd.count = args->count; 65114331Speter 65283366Sjulian return readlink(td, &bsd); 65314331Speter} 65414331Speter 65514331Speterint 65683366Sjulianlinux_truncate(struct thread *td, struct linux_truncate_args *args) 65714331Speter{ 65842499Seivind struct truncate_args bsd; 65914331Speter caddr_t sg; 66014331Speter 66114331Speter sg = stackgap_init(); 66283366Sjulian CHECKALTEXIST(td, &sg, args->path); 66314331Speter 66414331Speter#ifdef DEBUG 66572543Sjlemon if (ldebug(truncate)) 66683221Smarcel printf(ARGS(truncate, "%s, %ld"), args->path, 66783221Smarcel (long)args->length); 66814331Speter#endif 66914331Speter bsd.path = args->path; 67032265Sjmb bsd.length = args->length; 67114331Speter 67283366Sjulian return truncate(td, &bsd); 67314331Speter} 67414331Speter 67549662Smarcelint 67683366Sjulianlinux_link(struct thread *td, struct linux_link_args *args) 67749662Smarcel{ 67849662Smarcel struct link_args bsd; 67949662Smarcel caddr_t sg; 68049662Smarcel 68149662Smarcel sg = stackgap_init(); 68283366Sjulian CHECKALTEXIST(td, &sg, args->path); 68383366Sjulian CHECKALTCREAT(td, &sg, args->to); 68449662Smarcel 68549662Smarcel#ifdef DEBUG 68672543Sjlemon if (ldebug(link)) 68772543Sjlemon printf(ARGS(link, "%s, %s"), args->path, args->to); 68849662Smarcel#endif 68949662Smarcel 69049662Smarcel bsd.path = args->path; 69149662Smarcel bsd.link = args->to; 69249662Smarcel 69383366Sjulian return link(td, &bsd); 69449662Smarcel} 69549788Smarcel 69668201Sobrien#ifndef __alpha__ 69753713Smarcelint 69883366Sjulianlinux_fdatasync(td, uap) 69983366Sjulian struct thread *td; 70053713Smarcel struct linux_fdatasync_args *uap; 70153713Smarcel{ 70253713Smarcel struct fsync_args bsd; 70353713Smarcel 70453713Smarcel bsd.fd = uap->fd; 70583366Sjulian return fsync(td, &bsd); 70653713Smarcel} 70768201Sobrien#endif /*!__alpha__*/ 70863285Smarcel 70963285Smarcelint 71083366Sjulianlinux_pread(td, uap) 71183366Sjulian struct thread *td; 71263285Smarcel struct linux_pread_args *uap; 71363285Smarcel{ 71463285Smarcel struct pread_args bsd; 71563285Smarcel 71663285Smarcel bsd.fd = uap->fd; 71763285Smarcel bsd.buf = uap->buf; 71863285Smarcel bsd.nbyte = uap->nbyte; 71963285Smarcel bsd.offset = uap->offset; 72083366Sjulian return pread(td, &bsd); 72163285Smarcel} 72263285Smarcel 72363285Smarcelint 72483366Sjulianlinux_pwrite(td, uap) 72583366Sjulian struct thread *td; 72663285Smarcel struct linux_pwrite_args *uap; 72763285Smarcel{ 72863285Smarcel struct pwrite_args bsd; 72963285Smarcel 73063285Smarcel bsd.fd = uap->fd; 73163285Smarcel bsd.buf = uap->buf; 73263285Smarcel bsd.nbyte = uap->nbyte; 73363285Smarcel bsd.offset = uap->offset; 73483366Sjulian return pwrite(td, &bsd); 73563285Smarcel} 73672538Sjlemon 73772538Sjlemonint 73883366Sjulianlinux_mount(struct thread *td, struct linux_mount_args *args) 73972538Sjlemon{ 74072538Sjlemon struct ufs_args ufs; 74172538Sjlemon char fstypename[MFSNAMELEN]; 74272538Sjlemon char mntonname[MNAMELEN], mntfromname[MNAMELEN]; 74373286Sadrian int error; 74473286Sadrian int fsflags; 74573286Sadrian const char *fstype; 74673286Sadrian void *fsdata; 74772538Sjlemon 74873286Sadrian error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1, 74973286Sadrian NULL); 75072538Sjlemon if (error) 75172538Sjlemon return (error); 75272538Sjlemon error = copyinstr(args->specialfile, mntfromname, MFSNAMELEN - 1, NULL); 75372538Sjlemon if (error) 75472538Sjlemon return (error); 75572538Sjlemon error = copyinstr(args->dir, mntonname, MFSNAMELEN - 1, NULL); 75672538Sjlemon if (error) 75772538Sjlemon return (error); 75872538Sjlemon 75972538Sjlemon#ifdef DEBUG 76072538Sjlemon if (ldebug(mount)) 76172538Sjlemon printf(ARGS(mount, "%s, %s, %s"), 76272538Sjlemon fstypename, mntfromname, mntonname); 76372538Sjlemon#endif 76472538Sjlemon 76572538Sjlemon if (strcmp(fstypename, "ext2") == 0) { 76673286Sadrian fstype = "ext2fs"; 76773286Sadrian fsdata = &ufs; 76872538Sjlemon ufs.fspec = mntfromname; 76972538Sjlemon#define DEFAULT_ROOTID -2 77072538Sjlemon ufs.export.ex_root = DEFAULT_ROOTID; 77172538Sjlemon ufs.export.ex_flags = 77272538Sjlemon args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0; 77372538Sjlemon } else if (strcmp(fstypename, "proc") == 0) { 77473286Sadrian fstype = "linprocfs"; 77573286Sadrian fsdata = NULL; 77672538Sjlemon } else { 77772538Sjlemon return (ENODEV); 77872538Sjlemon } 77972538Sjlemon 78073286Sadrian fsflags = 0; 78172538Sjlemon 78272538Sjlemon if ((args->rwflag & 0xffff0000) == 0xc0ed0000) { 78372538Sjlemon /* 78472538Sjlemon * Linux SYNC flag is not included; the closest equivalent 78572538Sjlemon * FreeBSD has is !ASYNC, which is our default. 78672538Sjlemon */ 78772538Sjlemon if (args->rwflag & LINUX_MS_RDONLY) 78873286Sadrian fsflags |= MNT_RDONLY; 78972538Sjlemon if (args->rwflag & LINUX_MS_NOSUID) 79073286Sadrian fsflags |= MNT_NOSUID; 79172538Sjlemon if (args->rwflag & LINUX_MS_NODEV) 79273286Sadrian fsflags |= MNT_NODEV; 79372538Sjlemon if (args->rwflag & LINUX_MS_NOEXEC) 79473286Sadrian fsflags |= MNT_NOEXEC; 79572538Sjlemon if (args->rwflag & LINUX_MS_REMOUNT) 79673286Sadrian fsflags |= MNT_UPDATE; 79772538Sjlemon } 79872538Sjlemon 79983366Sjulian return (vfs_mount(td, fstype, mntonname, fsflags, fsdata)); 80072538Sjlemon} 80172538Sjlemon 80272538Sjlemonint 80383366Sjulianlinux_oldumount(struct thread *td, struct linux_oldumount_args *args) 80472538Sjlemon{ 80583221Smarcel struct linux_umount_args args2; 80672538Sjlemon 80772538Sjlemon args2.path = args->path; 80872538Sjlemon args2.flags = 0; 80983366Sjulian return (linux_umount(td, &args2)); 81072538Sjlemon} 81172538Sjlemon 81272538Sjlemonint 81383366Sjulianlinux_umount(struct thread *td, struct linux_umount_args *args) 81472538Sjlemon{ 81572538Sjlemon struct unmount_args bsd; 81672538Sjlemon 81772538Sjlemon bsd.path = args->path; 81872538Sjlemon bsd.flags = args->flags; /* XXX correct? */ 81983366Sjulian return (unmount(td, &bsd)); 82072538Sjlemon} 82183221Smarcel 82283221Smarcel/* 82383221Smarcel * fcntl family of syscalls 82483221Smarcel */ 82583221Smarcel 82683221Smarcelstruct l_flock { 82783221Smarcel l_short l_type; 82883221Smarcel l_short l_whence; 82983221Smarcel l_off_t l_start; 83083221Smarcel l_off_t l_len; 83183221Smarcel l_pid_t l_pid; 83283221Smarcel}; 83383221Smarcel 83483221Smarcelstatic void 83583221Smarcellinux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock) 83683221Smarcel{ 83783221Smarcel switch (linux_flock->l_type) { 83883221Smarcel case LINUX_F_RDLCK: 83983221Smarcel bsd_flock->l_type = F_RDLCK; 84083221Smarcel break; 84183221Smarcel case LINUX_F_WRLCK: 84283221Smarcel bsd_flock->l_type = F_WRLCK; 84383221Smarcel break; 84483221Smarcel case LINUX_F_UNLCK: 84583221Smarcel bsd_flock->l_type = F_UNLCK; 84683221Smarcel break; 84783221Smarcel default: 84883221Smarcel bsd_flock->l_type = -1; 84983221Smarcel break; 85083221Smarcel } 85183221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 85283221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 85383221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 85483221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 85583221Smarcel} 85683221Smarcel 85783221Smarcelstatic void 85883221Smarcelbsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock) 85983221Smarcel{ 86083221Smarcel switch (bsd_flock->l_type) { 86183221Smarcel case F_RDLCK: 86283221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 86383221Smarcel break; 86483221Smarcel case F_WRLCK: 86583221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 86683221Smarcel break; 86783221Smarcel case F_UNLCK: 86883221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 86983221Smarcel break; 87083221Smarcel } 87183221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 87283221Smarcel linux_flock->l_start = (l_off_t)bsd_flock->l_start; 87383221Smarcel linux_flock->l_len = (l_off_t)bsd_flock->l_len; 87483221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 87583221Smarcel} 87683221Smarcel 87783221Smarcel#if defined(__i386__) 87883221Smarcelstruct l_flock64 { 87983221Smarcel l_short l_type; 88083221Smarcel l_short l_whence; 88183221Smarcel l_loff_t l_start; 88283221Smarcel l_loff_t l_len; 88383221Smarcel l_pid_t l_pid; 88483221Smarcel}; 88583221Smarcel 88683221Smarcelstatic void 88783221Smarcellinux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock) 88883221Smarcel{ 88983221Smarcel switch (linux_flock->l_type) { 89083221Smarcel case LINUX_F_RDLCK: 89183221Smarcel bsd_flock->l_type = F_RDLCK; 89283221Smarcel break; 89383221Smarcel case LINUX_F_WRLCK: 89483221Smarcel bsd_flock->l_type = F_WRLCK; 89583221Smarcel break; 89683221Smarcel case LINUX_F_UNLCK: 89783221Smarcel bsd_flock->l_type = F_UNLCK; 89883221Smarcel break; 89983221Smarcel default: 90083221Smarcel bsd_flock->l_type = -1; 90183221Smarcel break; 90283221Smarcel } 90383221Smarcel bsd_flock->l_whence = linux_flock->l_whence; 90483221Smarcel bsd_flock->l_start = (off_t)linux_flock->l_start; 90583221Smarcel bsd_flock->l_len = (off_t)linux_flock->l_len; 90683221Smarcel bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 90783221Smarcel} 90883221Smarcel 90983221Smarcelstatic void 91083221Smarcelbsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) 91183221Smarcel{ 91283221Smarcel switch (bsd_flock->l_type) { 91383221Smarcel case F_RDLCK: 91483221Smarcel linux_flock->l_type = LINUX_F_RDLCK; 91583221Smarcel break; 91683221Smarcel case F_WRLCK: 91783221Smarcel linux_flock->l_type = LINUX_F_WRLCK; 91883221Smarcel break; 91983221Smarcel case F_UNLCK: 92083221Smarcel linux_flock->l_type = LINUX_F_UNLCK; 92183221Smarcel break; 92283221Smarcel } 92383221Smarcel linux_flock->l_whence = bsd_flock->l_whence; 92483221Smarcel linux_flock->l_start = (l_loff_t)bsd_flock->l_start; 92583221Smarcel linux_flock->l_len = (l_loff_t)bsd_flock->l_len; 92683221Smarcel linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 92783221Smarcel} 92883221Smarcel#endif /* __i386__ */ 92983221Smarcel 93083221Smarcel#if defined(__alpha__) 93183221Smarcel#define linux_fcntl64_args linux_fcntl_args 93283221Smarcel#endif 93383221Smarcel 93483221Smarcelstatic int 93583366Sjulianfcntl_common(struct thread *td, struct linux_fcntl64_args *args) 93683221Smarcel{ 93783221Smarcel struct fcntl_args fcntl_args; 93883221Smarcel struct file *fp; 93983221Smarcel int error, result; 94083221Smarcel 94183221Smarcel fcntl_args.fd = args->fd; 94283221Smarcel 94383221Smarcel switch (args->cmd) { 94483221Smarcel case LINUX_F_DUPFD: 94583221Smarcel fcntl_args.cmd = F_DUPFD; 94683221Smarcel fcntl_args.arg = args->arg; 94783366Sjulian return (fcntl(td, &fcntl_args)); 94883221Smarcel 94983221Smarcel case LINUX_F_GETFD: 95083221Smarcel fcntl_args.cmd = F_GETFD; 95183366Sjulian return (fcntl(td, &fcntl_args)); 95283221Smarcel 95383221Smarcel case LINUX_F_SETFD: 95483221Smarcel fcntl_args.cmd = F_SETFD; 95583221Smarcel fcntl_args.arg = args->arg; 95683366Sjulian return (fcntl(td, &fcntl_args)); 95783221Smarcel 95883221Smarcel case LINUX_F_GETFL: 95983221Smarcel fcntl_args.cmd = F_GETFL; 96083366Sjulian error = fcntl(td, &fcntl_args); 96183366Sjulian result = td->td_retval[0]; 96283366Sjulian td->td_retval[0] = 0; 96383221Smarcel if (result & O_RDONLY) 96483366Sjulian td->td_retval[0] |= LINUX_O_RDONLY; 96583221Smarcel if (result & O_WRONLY) 96683366Sjulian td->td_retval[0] |= LINUX_O_WRONLY; 96783221Smarcel if (result & O_RDWR) 96883366Sjulian td->td_retval[0] |= LINUX_O_RDWR; 96983221Smarcel if (result & O_NDELAY) 97083366Sjulian td->td_retval[0] |= LINUX_O_NONBLOCK; 97183221Smarcel if (result & O_APPEND) 97283366Sjulian td->td_retval[0] |= LINUX_O_APPEND; 97383221Smarcel if (result & O_FSYNC) 97483366Sjulian td->td_retval[0] |= LINUX_O_SYNC; 97583221Smarcel if (result & O_ASYNC) 97683366Sjulian td->td_retval[0] |= LINUX_FASYNC; 97783221Smarcel return (error); 97883221Smarcel 97983221Smarcel case LINUX_F_SETFL: 98083221Smarcel fcntl_args.arg = 0; 98183221Smarcel if (args->arg & LINUX_O_NDELAY) 98283221Smarcel fcntl_args.arg |= O_NONBLOCK; 98383221Smarcel if (args->arg & LINUX_O_APPEND) 98483221Smarcel fcntl_args.arg |= O_APPEND; 98583221Smarcel if (args->arg & LINUX_O_SYNC) 98683221Smarcel fcntl_args.arg |= O_FSYNC; 98783221Smarcel if (args->arg & LINUX_FASYNC) 98883221Smarcel fcntl_args.arg |= O_ASYNC; 98983221Smarcel fcntl_args.cmd = F_SETFL; 99083366Sjulian return (fcntl(td, &fcntl_args)); 99183221Smarcel 99283221Smarcel case LINUX_F_GETOWN: 99383221Smarcel fcntl_args.cmd = F_GETOWN; 99483366Sjulian return (fcntl(td, &fcntl_args)); 99583221Smarcel 99683221Smarcel case LINUX_F_SETOWN: 99783221Smarcel /* 99883221Smarcel * XXX some Linux applications depend on F_SETOWN having no 99983221Smarcel * significant effect for pipes (SIGIO is not delivered for 100083221Smarcel * pipes under Linux-2.2.35 at least). 100183221Smarcel */ 100289319Salfred error = fget(td, args->fd, &fp); 100389319Salfred if (error) 100489319Salfred return (error); 100589306Salfred if (fp->f_type == DTYPE_PIPE) { 100689306Salfred fdrop(fp, td); 100783221Smarcel return (EINVAL); 100889306Salfred } 100989306Salfred fdrop(fp, td); 101083221Smarcel 101183221Smarcel fcntl_args.cmd = F_SETOWN; 101283221Smarcel fcntl_args.arg = args->arg; 101383366Sjulian return (fcntl(td, &fcntl_args)); 101483221Smarcel } 101583221Smarcel 101683221Smarcel return (EINVAL); 101783221Smarcel} 101883221Smarcel 101983221Smarcelint 102083366Sjulianlinux_fcntl(struct thread *td, struct linux_fcntl_args *args) 102183221Smarcel{ 102283221Smarcel struct linux_fcntl64_args args64; 102383221Smarcel struct fcntl_args fcntl_args; 102483221Smarcel struct l_flock linux_flock; 102583221Smarcel struct flock *bsd_flock; 102683221Smarcel int error; 102783221Smarcel caddr_t sg; 102883221Smarcel 102983221Smarcel sg = stackgap_init(); 103083221Smarcel bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock)); 103183221Smarcel 103283221Smarcel#ifdef DEBUG 103383221Smarcel if (ldebug(fcntl)) 103483221Smarcel printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); 103583221Smarcel#endif 103683221Smarcel 103783221Smarcel switch (args->cmd) { 103883221Smarcel case LINUX_F_GETLK: 103983221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 104083221Smarcel sizeof(linux_flock)); 104183221Smarcel if (error) 104283221Smarcel return (error); 104383221Smarcel linux_to_bsd_flock(&linux_flock, bsd_flock); 104483221Smarcel fcntl_args.fd = args->fd; 104583221Smarcel fcntl_args.cmd = F_GETLK; 104683221Smarcel fcntl_args.arg = (long)bsd_flock; 104783366Sjulian error = fcntl(td, &fcntl_args); 104883221Smarcel if (error) 104983221Smarcel return (error); 105083221Smarcel bsd_to_linux_flock(bsd_flock, &linux_flock); 105183221Smarcel return (copyout(&linux_flock, (caddr_t)args->arg, 105283221Smarcel sizeof(linux_flock))); 105383221Smarcel 105483221Smarcel case LINUX_F_SETLK: 105583221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 105683221Smarcel sizeof(linux_flock)); 105783221Smarcel if (error) 105883221Smarcel return (error); 105983221Smarcel linux_to_bsd_flock(&linux_flock, bsd_flock); 106083221Smarcel fcntl_args.fd = args->fd; 106183221Smarcel fcntl_args.cmd = F_SETLK; 106283221Smarcel fcntl_args.arg = (long)bsd_flock; 106383366Sjulian return (fcntl(td, &fcntl_args)); 106483221Smarcel 106583221Smarcel case LINUX_F_SETLKW: 106683221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 106783221Smarcel sizeof(linux_flock)); 106883221Smarcel if (error) 106983221Smarcel return (error); 107083221Smarcel linux_to_bsd_flock(&linux_flock, bsd_flock); 107183221Smarcel fcntl_args.fd = args->fd; 107283221Smarcel fcntl_args.cmd = F_SETLKW; 107383221Smarcel fcntl_args.arg = (long)bsd_flock; 107483366Sjulian return (fcntl(td, &fcntl_args)); 107583221Smarcel } 107683221Smarcel 107783221Smarcel args64.fd = args->fd; 107883221Smarcel args64.cmd = args->cmd; 107983221Smarcel args64.arg = args->arg; 108083366Sjulian return (fcntl_common(td, &args64)); 108183221Smarcel} 108283221Smarcel 108383221Smarcel#if defined(__i386__) 108483221Smarcelint 108583366Sjulianlinux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) 108683221Smarcel{ 108783221Smarcel struct fcntl_args fcntl_args; 108883221Smarcel struct l_flock64 linux_flock; 108983221Smarcel struct flock *bsd_flock; 109083221Smarcel int error; 109183221Smarcel caddr_t sg; 109283221Smarcel 109383221Smarcel sg = stackgap_init(); 109483221Smarcel bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock)); 109583221Smarcel 109683221Smarcel#ifdef DEBUG 109783221Smarcel if (ldebug(fcntl64)) 109883221Smarcel printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd); 109983221Smarcel#endif 110083221Smarcel 110183221Smarcel switch (args->cmd) { 110283221Smarcel case LINUX_F_GETLK: 110399687Srobert case LINUX_F_GETLK64: 110483221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 110583221Smarcel sizeof(linux_flock)); 110683221Smarcel if (error) 110783221Smarcel return (error); 110883221Smarcel linux_to_bsd_flock64(&linux_flock, bsd_flock); 110983221Smarcel fcntl_args.fd = args->fd; 111083221Smarcel fcntl_args.cmd = F_GETLK; 111183221Smarcel fcntl_args.arg = (long)bsd_flock; 111283366Sjulian error = fcntl(td, &fcntl_args); 111383221Smarcel if (error) 111483221Smarcel return (error); 111583221Smarcel bsd_to_linux_flock64(bsd_flock, &linux_flock); 111683221Smarcel return (copyout(&linux_flock, (caddr_t)args->arg, 111783221Smarcel sizeof(linux_flock))); 111883221Smarcel 111983221Smarcel case LINUX_F_SETLK: 112099687Srobert case LINUX_F_SETLK64: 112183221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 112283221Smarcel sizeof(linux_flock)); 112383221Smarcel if (error) 112483221Smarcel return (error); 112583221Smarcel linux_to_bsd_flock64(&linux_flock, bsd_flock); 112683221Smarcel fcntl_args.fd = args->fd; 112783221Smarcel fcntl_args.cmd = F_SETLK; 112883221Smarcel fcntl_args.arg = (long)bsd_flock; 112983366Sjulian return (fcntl(td, &fcntl_args)); 113083221Smarcel 113183221Smarcel case LINUX_F_SETLKW: 113299687Srobert case LINUX_F_SETLKW64: 113383221Smarcel error = copyin((caddr_t)args->arg, &linux_flock, 113483221Smarcel sizeof(linux_flock)); 113583221Smarcel if (error) 113683221Smarcel return (error); 113783221Smarcel linux_to_bsd_flock64(&linux_flock, bsd_flock); 113883221Smarcel fcntl_args.fd = args->fd; 113983221Smarcel fcntl_args.cmd = F_SETLKW; 114083221Smarcel fcntl_args.arg = (long)bsd_flock; 114183366Sjulian return (fcntl(td, &fcntl_args)); 114283221Smarcel } 114383221Smarcel 114483366Sjulian return (fcntl_common(td, args)); 114583221Smarcel} 114683221Smarcel#endif /* __i386__ */ 114785022Smarcel 114885022Smarcelint 114985022Smarcellinux_chown(struct thread *td, struct linux_chown_args *args) 115085022Smarcel{ 115185022Smarcel struct chown_args bsd; 115285022Smarcel caddr_t sg; 115385022Smarcel 115485022Smarcel sg = stackgap_init(); 115585022Smarcel CHECKALTEXIST(td, &sg, args->path); 115685022Smarcel 115785022Smarcel#ifdef DEBUG 115885022Smarcel if (ldebug(chown)) 115985022Smarcel printf(ARGS(chown, "%s, %d, %d"), args->path, args->uid, 116085022Smarcel args->gid); 116185022Smarcel#endif 116285022Smarcel 116385022Smarcel bsd.path = args->path; 116485022Smarcel bsd.uid = args->uid; 116585022Smarcel bsd.gid = args->gid; 116685022Smarcel return (chown(td, &bsd)); 116785022Smarcel} 116885022Smarcel 116985022Smarcelint 117085022Smarcellinux_lchown(struct thread *td, struct linux_lchown_args *args) 117185022Smarcel{ 117285022Smarcel struct lchown_args bsd; 117385022Smarcel caddr_t sg; 117485022Smarcel 117585022Smarcel sg = stackgap_init(); 117685022Smarcel CHECKALTEXIST(td, &sg, args->path); 117785022Smarcel 117885022Smarcel#ifdef DEBUG 117985022Smarcel if (ldebug(lchown)) 118085022Smarcel printf(ARGS(lchown, "%s, %d, %d"), args->path, args->uid, 118185022Smarcel args->gid); 118285022Smarcel#endif 118385022Smarcel 118485022Smarcel bsd.path = args->path; 118585022Smarcel bsd.uid = args->uid; 118685022Smarcel bsd.gid = args->gid; 118785022Smarcel return (lchown(td, &bsd)); 118885022Smarcel} 1189