linux_file.c revision 31784
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 * 2831784Seivind * $Id: linux_file.c,v 1.16 1997/12/05 19:55:37 bde Exp $ 299313Ssos */ 309313Ssos 3131784Seivind#include "opt_compat.h" 3231784Seivind 339313Ssos#include <sys/param.h> 349313Ssos#include <sys/systm.h> 3512458Sbde#include <sys/sysproto.h> 369313Ssos#include <sys/fcntl.h> 379313Ssos#include <sys/file.h> 389313Ssos#include <sys/filedesc.h> 3931561Sbde#include <sys/lock.h> 409313Ssos#include <sys/proc.h> 419313Ssos#include <sys/vnode.h> 429313Ssos#include <sys/malloc.h> 439313Ssos#include <sys/dirent.h> 4414331Speter#include <sys/conf.h> 4514331Speter#include <sys/tty.h> 4612458Sbde 4712458Sbde#include <i386/linux/linux.h> 4814331Speter#include <i386/linux/linux_proto.h> 4914331Speter#include <i386/linux/linux_util.h> 509313Ssos 519313Ssosint 5230994Sphklinux_creat(struct proc *p, struct linux_creat_args *args) 539313Ssos{ 5412858Speter struct open_args /* { 559313Ssos char *path; 569313Ssos int flags; 579313Ssos int mode; 5812858Speter } */ bsd_open_args; 5914331Speter caddr_t sg; 609313Ssos 6114331Speter sg = stackgap_init(); 6214331Speter CHECKALTCREAT(p, &sg, args->path); 6314331Speter 649313Ssos#ifdef DEBUG 659313Ssos printf("Linux-emul(%d): creat(%s, %d)\n", 669313Ssos p->p_pid, args->path, args->mode); 679313Ssos#endif 689313Ssos bsd_open_args.path = args->path; 699313Ssos bsd_open_args.mode = args->mode; 709313Ssos bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC; 7130994Sphk return open(p, &bsd_open_args); 729313Ssos} 739313Ssos 749313Ssosint 7530994Sphklinux_open(struct proc *p, struct linux_open_args *args) 769313Ssos{ 7712858Speter struct open_args /* { 789313Ssos char *path; 799313Ssos int flags; 809313Ssos int mode; 8112858Speter } */ bsd_open_args; 829313Ssos int error; 8314331Speter caddr_t sg; 8414331Speter 8514331Speter sg = stackgap_init(); 869313Ssos 8714331Speter if (args->flags & LINUX_O_CREAT) 8814331Speter CHECKALTCREAT(p, &sg, args->path); 8914331Speter else 9014331Speter CHECKALTEXIST(p, &sg, args->path); 9114331Speter 929313Ssos#ifdef DEBUG 939313Ssos printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n", 949313Ssos p->p_pid, args->path, args->flags, args->mode); 959313Ssos#endif 969313Ssos bsd_open_args.flags = 0; 979313Ssos if (args->flags & LINUX_O_RDONLY) 989313Ssos bsd_open_args.flags |= O_RDONLY; 999313Ssos if (args->flags & LINUX_O_WRONLY) 1009313Ssos bsd_open_args.flags |= O_WRONLY; 1019313Ssos if (args->flags & LINUX_O_RDWR) 1029313Ssos bsd_open_args.flags |= O_RDWR; 1039313Ssos if (args->flags & LINUX_O_NDELAY) 1049313Ssos bsd_open_args.flags |= O_NONBLOCK; 1059313Ssos if (args->flags & LINUX_O_APPEND) 1069313Ssos bsd_open_args.flags |= O_APPEND; 1079313Ssos if (args->flags & LINUX_O_SYNC) 1089313Ssos bsd_open_args.flags |= O_FSYNC; 1099313Ssos if (args->flags & LINUX_O_NONBLOCK) 1109313Ssos bsd_open_args.flags |= O_NONBLOCK; 1119313Ssos if (args->flags & LINUX_FASYNC) 1129313Ssos bsd_open_args.flags |= O_ASYNC; 1139313Ssos if (args->flags & LINUX_O_CREAT) 1149313Ssos bsd_open_args.flags |= O_CREAT; 1159313Ssos if (args->flags & LINUX_O_TRUNC) 1169313Ssos bsd_open_args.flags |= O_TRUNC; 1179313Ssos if (args->flags & LINUX_O_EXCL) 1189313Ssos bsd_open_args.flags |= O_EXCL; 1199313Ssos if (args->flags & LINUX_O_NOCTTY) 1209313Ssos bsd_open_args.flags |= O_NOCTTY; 1219313Ssos bsd_open_args.path = args->path; 1229313Ssos bsd_open_args.mode = args->mode; 1239313Ssos 12430994Sphk error = open(p, &bsd_open_args); 1259313Ssos if (!error && !(bsd_open_args.flags & O_NOCTTY) && 1269313Ssos SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 1279313Ssos struct filedesc *fdp = p->p_fd; 12830994Sphk struct file *fp = fdp->fd_ofiles[p->p_retval[0]]; 1299313Ssos 1309313Ssos if (fp->f_type == DTYPE_VNODE) 1319313Ssos (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p); 1329313Ssos } 13314331Speter#ifdef DEBUG 13414331Speter printf("Linux-emul(%d): open returns error %d\n", 13514331Speter p->p_pid, error); 13614331Speter#endif 1379313Ssos return error; 1389313Ssos} 1399313Ssos 1409313Ssosstruct linux_flock { 1419313Ssos short l_type; 1429313Ssos short l_whence; 1439313Ssos linux_off_t l_start; 1449313Ssos linux_off_t l_len; 1459313Ssos linux_pid_t l_pid; 1469313Ssos}; 1479313Ssos 1489313Ssosstatic void 1499313Ssoslinux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock) 1509313Ssos{ 1519313Ssos switch (linux_flock->l_type) { 1529313Ssos case LINUX_F_RDLCK: 1539313Ssos bsd_flock->l_type = F_RDLCK; 1549313Ssos break; 1559313Ssos case LINUX_F_WRLCK: 1569313Ssos bsd_flock->l_type = F_WRLCK; 1579313Ssos break; 1589313Ssos case LINUX_F_UNLCK: 1599313Ssos bsd_flock->l_type = F_UNLCK; 1609313Ssos break; 1619313Ssos } 1629313Ssos bsd_flock->l_whence = linux_flock->l_whence; 1639313Ssos bsd_flock->l_start = (off_t)linux_flock->l_start; 1649313Ssos bsd_flock->l_len = (off_t)linux_flock->l_len; 1659313Ssos bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 1669313Ssos} 1679313Ssos 1689313Ssosstatic void 1699313Ssosbsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock) 1709313Ssos{ 1719313Ssos switch (bsd_flock->l_type) { 1729313Ssos case F_RDLCK: 1739313Ssos linux_flock->l_type = LINUX_F_RDLCK; 1749313Ssos break; 1759313Ssos case F_WRLCK: 1769313Ssos linux_flock->l_type = LINUX_F_WRLCK; 1779313Ssos break; 1789313Ssos case F_UNLCK: 1799313Ssos linux_flock->l_type = LINUX_F_UNLCK; 1809313Ssos break; 1819313Ssos } 1829313Ssos linux_flock->l_whence = bsd_flock->l_whence; 1839313Ssos linux_flock->l_start = (linux_off_t)bsd_flock->l_start; 1849313Ssos linux_flock->l_len = (linux_off_t)bsd_flock->l_len; 1859313Ssos linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid; 1869313Ssos} 1879313Ssos 1889313Ssosint 18930994Sphklinux_fcntl(struct proc *p, struct linux_fcntl_args *args) 1909313Ssos{ 1919313Ssos int error, result; 19212858Speter struct fcntl_args /* { 1939313Ssos int fd; 1949313Ssos int cmd; 1959313Ssos int arg; 19612858Speter } */ fcntl_args; 1979313Ssos struct linux_flock linux_flock; 19814331Speter struct flock *bsd_flock; 19914331Speter struct filedesc *fdp; 20014331Speter struct file *fp; 20114331Speter struct vnode *vp; 20214331Speter struct vattr va; 20314331Speter long pgid; 20414331Speter struct pgrp *pgrp; 20514331Speter struct tty *tp, *(*d_tty) __P((dev_t)); 20614331Speter caddr_t sg; 2079313Ssos 20814331Speter sg = stackgap_init(); 20914331Speter bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(struct flock)); 21014331Speter d_tty = NULL; 21114331Speter 2129313Ssos#ifdef DEBUG 2139313Ssos printf("Linux-emul(%d): fcntl(%d, %08x, *)\n", 2149313Ssos p->p_pid, args->fd, args->cmd); 2159313Ssos#endif 2169313Ssos fcntl_args.fd = args->fd; 2179313Ssos fcntl_args.arg = 0; 2189313Ssos 2199313Ssos switch (args->cmd) { 2209313Ssos case LINUX_F_DUPFD: 2219313Ssos fcntl_args.cmd = F_DUPFD; 22230994Sphk return fcntl(p, &fcntl_args); 2239313Ssos 2249313Ssos case LINUX_F_GETFD: 2259313Ssos fcntl_args.cmd = F_GETFD; 22630994Sphk return fcntl(p, &fcntl_args); 2279313Ssos 2289313Ssos case LINUX_F_SETFD: 2299313Ssos fcntl_args.cmd = F_SETFD; 23030994Sphk return fcntl(p, &fcntl_args); 2319313Ssos 2329313Ssos case LINUX_F_GETFL: 2339313Ssos fcntl_args.cmd = F_GETFL; 23430994Sphk error = fcntl(p, &fcntl_args); 23530994Sphk result = p->p_retval[0]; 23630994Sphk p->p_retval[0] = 0; 23730994Sphk if (result & O_RDONLY) p->p_retval[0] |= LINUX_O_RDONLY; 23830994Sphk if (result & O_WRONLY) p->p_retval[0] |= LINUX_O_WRONLY; 23930994Sphk if (result & O_RDWR) p->p_retval[0] |= LINUX_O_RDWR; 24030994Sphk if (result & O_NDELAY) p->p_retval[0] |= LINUX_O_NONBLOCK; 24130994Sphk if (result & O_APPEND) p->p_retval[0] |= LINUX_O_APPEND; 24230994Sphk if (result & O_FSYNC) p->p_retval[0] |= LINUX_O_SYNC; 2439313Ssos return error; 2449313Ssos 2459313Ssos case LINUX_F_SETFL: 2469313Ssos if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK; 2479313Ssos if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND; 2489313Ssos if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC; 2499313Ssos fcntl_args.cmd = F_SETFL; 25030994Sphk return fcntl(p, &fcntl_args); 2519313Ssos 2529313Ssos case LINUX_F_GETLK: 2539313Ssos if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 2549313Ssos sizeof(struct linux_flock)))) 2559313Ssos return error; 2569313Ssos linux_to_bsd_flock(&linux_flock, bsd_flock); 2579313Ssos fcntl_args.cmd = F_GETLK; 2589313Ssos fcntl_args.arg = (int)bsd_flock; 25930994Sphk if (error = fcntl(p, &fcntl_args)) 2609313Ssos return error; 2619313Ssos bsd_to_linux_flock(bsd_flock, &linux_flock); 2629313Ssos return copyout((caddr_t)&linux_flock, (caddr_t)args->arg, 2639313Ssos sizeof(struct linux_flock)); 2649313Ssos 2659313Ssos case LINUX_F_SETLK: 2669313Ssos if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 2679313Ssos sizeof(struct linux_flock)))) 2689313Ssos return error; 2699313Ssos linux_to_bsd_flock(&linux_flock, bsd_flock); 2709313Ssos fcntl_args.cmd = F_SETLK; 2719313Ssos fcntl_args.arg = (int)bsd_flock; 27230994Sphk return fcntl(p, &fcntl_args); 2739313Ssos 2749313Ssos case LINUX_F_SETLKW: 2759313Ssos if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 2769313Ssos sizeof(struct linux_flock)))) 2779313Ssos return error; 2789313Ssos linux_to_bsd_flock(&linux_flock, bsd_flock); 2799313Ssos fcntl_args.cmd = F_SETLKW; 2809313Ssos fcntl_args.arg = (int)bsd_flock; 28130994Sphk return fcntl(p, &fcntl_args); 2829313Ssos 2839313Ssos case LINUX_F_SETOWN: 28414331Speter case LINUX_F_GETOWN: 28514331Speter /* 28614331Speter * We need to route around the normal fcntl() for these calls, 28714331Speter * since it uses TIOC{G,S}PGRP, which is too restrictive for 28814331Speter * Linux F_{G,S}ETOWN semantics. For sockets, this problem 28914331Speter * does not exist. 29014331Speter */ 29114331Speter fdp = p->p_fd; 29214331Speter if ((u_int)args->fd >= fdp->fd_nfiles || 29314331Speter (fp = fdp->fd_ofiles[args->fd]) == NULL) 29414331Speter return EBADF; 29514331Speter if (fp->f_type == DTYPE_SOCKET) { 29614331Speter fcntl_args.cmd = args->cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN; 29730994Sphk return fcntl(p, &fcntl_args); 29814331Speter } 29914331Speter vp = (struct vnode *)fp->f_data; 30014331Speter if (vp->v_type != VCHR) 30114331Speter return EINVAL; 30214331Speter if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) 30314331Speter return error; 3049313Ssos 30514331Speter d_tty = cdevsw[major(va.va_rdev)]->d_devtotty; 30614331Speter if (!d_tty || (!(tp = (*d_tty)(va.va_rdev)))) 30714331Speter return EINVAL; 30814331Speter if (args->cmd == LINUX_F_GETOWN) { 30930994Sphk p->p_retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 31014331Speter return 0; 31114331Speter } 31214331Speter if ((long)args->arg <= 0) { 31314331Speter pgid = -(long)args->arg; 31414331Speter } else { 31514331Speter struct proc *p1 = pfind((long)args->arg); 31614331Speter if (p1 == 0) 31714331Speter return (ESRCH); 31814331Speter pgid = (long)p1->p_pgrp->pg_id; 31914331Speter } 32014331Speter pgrp = pgfind(pgid); 32114331Speter if (pgrp == NULL || pgrp->pg_session != p->p_session) 32214331Speter return EPERM; 32314331Speter tp->t_pgrp = pgrp; 32414331Speter return 0; 3259313Ssos } 3269313Ssos return EINVAL; 3279313Ssos} 3289313Ssos 3299313Ssosint 33030994Sphklinux_lseek(struct proc *p, struct linux_lseek_args *args) 3319313Ssos{ 3329313Ssos 33312858Speter struct lseek_args /* { 33412858Speter int fd; 3359313Ssos int pad; 33612858Speter off_t offset; 3379313Ssos int whence; 33812858Speter } */ tmp_args; 3399313Ssos int error; 3409313Ssos 3419313Ssos#ifdef DEBUG 3429313Ssos printf("Linux-emul(%d): lseek(%d, %d, %d)\n", 3439313Ssos p->p_pid, args->fdes, args->off, args->whence); 3449313Ssos#endif 34512858Speter tmp_args.fd = args->fdes; 34612858Speter tmp_args.offset = (off_t)args->off; 3479313Ssos tmp_args.whence = args->whence; 34830994Sphk error = lseek(p, &tmp_args); 3499313Ssos return error; 3509313Ssos} 3519313Ssos 35214331Speterint 35330994Sphklinux_llseek(struct proc *p, struct linux_llseek_args *args) 35414331Speter{ 35514331Speter struct lseek_args bsd_args; 35614331Speter int error; 35714331Speter off_t off; 35814331Speter 35914331Speter#ifdef DEBUG 36014331Speter printf("Linux-emul(%d): llseek(%d, %d:%d, %d)\n", 36114331Speter p->p_pid, args->fd, args->ohigh, args->olow, args->whence); 36214331Speter#endif 36314331Speter off = (args->olow) | (((off_t) args->ohigh) << 32); 36414331Speter 36514331Speter bsd_args.fd = args->fd; 36614331Speter bsd_args.offset = off; 36714331Speter bsd_args.whence = args->whence; 36814331Speter 36930994Sphk if ((error = lseek(p, &bsd_args))) 37014331Speter return error; 37114331Speter 37230994Sphk if ((error = copyout(p->p_retval, (caddr_t)args->res, sizeof (off_t)))) 37314331Speter return error; 37414331Speter 37530994Sphk p->p_retval[0] = 0; 37614331Speter return 0; 37714331Speter} 37814331Speter 37914331Speter 3809313Ssosstruct linux_dirent { 3819313Ssos long dino; 3829313Ssos linux_off_t doff; 3839313Ssos unsigned short dreclen; 3849313Ssos char dname[LINUX_NAME_MAX + 1]; 3859313Ssos}; 3869313Ssos 3879313Ssos#define LINUX_RECLEN(de,namlen) \ 3889313Ssos ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1)) 3899313Ssos 3909313Ssosint 39130994Sphklinux_readdir(struct proc *p, struct linux_readdir_args *args) 3929313Ssos{ 39314331Speter struct linux_getdents_args lda; 39414331Speter 39514331Speter lda.fd = args->fd; 39614331Speter lda.dent = args->dent; 39714331Speter lda.count = 1; 39830994Sphk return linux_getdents(p, &lda); 39914331Speter} 40014331Speter 40114331Speterint 40230994Sphklinux_getdents(struct proc *p, struct linux_getdents_args *args) 40314331Speter{ 4049313Ssos register struct dirent *bdp; 4059313Ssos struct vnode *vp; 4069313Ssos caddr_t inp, buf; /* BSD-format */ 4079313Ssos int len, reclen; /* BSD-format */ 4089313Ssos caddr_t outp; /* Linux-format */ 4099313Ssos int resid, linuxreclen=0; /* Linux-format */ 4109313Ssos struct file *fp; 4119313Ssos struct uio auio; 4129313Ssos struct iovec aiov; 4139313Ssos struct vattr va; 4149313Ssos off_t off; 4159313Ssos struct linux_dirent linux_dirent; 41624654Sdfr int buflen, error, eofflag, nbytes, justone; 41724654Sdfr u_long *cookies = NULL, *cookiep; 41824654Sdfr int ncookies; 4199313Ssos 4209313Ssos#ifdef DEBUG 42114331Speter printf("Linux-emul(%d): getdents(%d, *, %d)\n", 4229313Ssos p->p_pid, args->fd, args->count); 4239313Ssos#endif 42410355Sswallace if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) { 4259313Ssos return (error); 42614331Speter } 4279313Ssos 4289313Ssos if ((fp->f_flag & FREAD) == 0) 4299313Ssos return (EBADF); 4309313Ssos 4319313Ssos vp = (struct vnode *) fp->f_data; 4329313Ssos 4339313Ssos if (vp->v_type != VDIR) 4349313Ssos return (EINVAL); 4359313Ssos 43610355Sswallace if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) { 4379313Ssos return error; 43811418Sswallace } 4399313Ssos 4409313Ssos nbytes = args->count; 4419313Ssos if (nbytes == 1) { 4429313Ssos nbytes = sizeof (struct linux_dirent); 4439313Ssos justone = 1; 4449313Ssos } 4459313Ssos else 4469313Ssos justone = 0; 4479313Ssos 44810355Sswallace off = fp->f_offset; 44924672Sdfr#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ 45024654Sdfr buflen = max(DIRBLKSIZ, nbytes); 45111418Sswallace buflen = min(buflen, MAXBSIZE); 4529313Ssos buf = malloc(buflen, M_TEMP, M_WAITOK); 45322521Sdyson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 4549313Ssosagain: 4559313Ssos aiov.iov_base = buf; 4569313Ssos aiov.iov_len = buflen; 4579313Ssos auio.uio_iov = &aiov; 4589313Ssos auio.uio_iovcnt = 1; 4599313Ssos auio.uio_rw = UIO_READ; 4609313Ssos auio.uio_segflg = UIO_SYSSPACE; 4619313Ssos auio.uio_procp = p; 4629313Ssos auio.uio_resid = buflen; 46324654Sdfr auio.uio_offset = off; 4649313Ssos 46524654Sdfr if (cookies) { 46624654Sdfr free(cookies, M_TEMP); 46724654Sdfr cookies = NULL; 46824654Sdfr } 46924654Sdfr 47024654Sdfr error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies); 47110355Sswallace if (error) { 4729313Ssos goto out; 47314331Speter } 4749313Ssos 4759313Ssos inp = buf; 4769313Ssos outp = (caddr_t) args->dent; 4779313Ssos resid = nbytes; 47824654Sdfr if ((len = buflen - auio.uio_resid) <= 0) { 4799313Ssos goto eof; 48014331Speter } 4819313Ssos 48224654Sdfr cookiep = cookies; 48324654Sdfr 48424654Sdfr if (cookies) { 48524654Sdfr /* 48624654Sdfr * When using cookies, the vfs has the option of reading from 48724654Sdfr * a different offset than that supplied (UFS truncates the 48824654Sdfr * offset to a block boundary to make sure that it never reads 48924654Sdfr * partway through a directory entry, even if the directory 49024654Sdfr * has been compacted). 49124654Sdfr */ 49224654Sdfr while (len > 0 && ncookies > 0 && *cookiep <= off) { 49324654Sdfr bdp = (struct dirent *) inp; 49424654Sdfr len -= bdp->d_reclen; 49524654Sdfr inp += bdp->d_reclen; 49624654Sdfr cookiep++; 49724654Sdfr ncookies--; 49824654Sdfr } 49924654Sdfr } 50024654Sdfr 5019313Ssos while (len > 0) { 50224654Sdfr if (cookiep && ncookies == 0) 50324654Sdfr break; 50410355Sswallace bdp = (struct dirent *) inp; 50510355Sswallace reclen = bdp->d_reclen; 50610355Sswallace if (reclen & 3) { 50710355Sswallace printf("linux_readdir: reclen=%d\n", reclen); 50810355Sswallace error = EFAULT; 50910355Sswallace goto out; 51010355Sswallace } 51110355Sswallace 5129313Ssos if (bdp->d_fileno == 0) { 5139313Ssos inp += reclen; 51424654Sdfr if (cookiep) { 51524654Sdfr off = *cookiep++; 51624654Sdfr ncookies--; 51724654Sdfr } else 51824654Sdfr off += reclen; 51910355Sswallace len -= reclen; 5209313Ssos continue; 5219313Ssos } 5229313Ssos linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 5239313Ssos if (reclen > len || resid < linuxreclen) { 5249313Ssos outp++; 5259313Ssos break; 5269313Ssos } 5279313Ssos linux_dirent.dino = (long) bdp->d_fileno; 52814465Speter if (justone) { 52914465Speter /* 53014465Speter * old linux-style readdir usage. 53114465Speter */ 53214465Speter linux_dirent.doff = (linux_off_t) linuxreclen; 53314465Speter linux_dirent.dreclen = (u_short) bdp->d_namlen; 53414465Speter } else { 53514465Speter linux_dirent.doff = (linux_off_t) off; 53614465Speter linux_dirent.dreclen = (u_short) linuxreclen; 53714465Speter } 5389313Ssos strcpy(linux_dirent.dname, bdp->d_name); 53910355Sswallace if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) { 5409313Ssos goto out; 54114331Speter } 5429313Ssos inp += reclen; 54324654Sdfr if (cookiep) { 54424654Sdfr off = *cookiep++; 54524654Sdfr ncookies--; 54624654Sdfr } else 54724654Sdfr off += reclen; 5489313Ssos outp += linuxreclen; 5499313Ssos resid -= linuxreclen; 5509313Ssos len -= reclen; 5519313Ssos if (justone) 5529313Ssos break; 5539313Ssos } 5549313Ssos 5559313Ssos if (outp == (caddr_t) args->dent) 5569313Ssos goto again; 5579313Ssos fp->f_offset = off; 5589313Ssos 5599313Ssos if (justone) 5609313Ssos nbytes = resid + linuxreclen; 56110355Sswallace 5629313Ssoseof: 56330994Sphk p->p_retval[0] = nbytes - resid; 5649313Ssosout: 56524654Sdfr if (cookies) 56624654Sdfr free(cookies, M_TEMP); 56722543Smpp VOP_UNLOCK(vp, 0, p); 5689313Ssos free(buf, M_TEMP); 5699313Ssos return error; 5709313Ssos} 57114331Speter 57214331Speter/* 57314331Speter * These exist mainly for hooks for doing /compat/linux translation. 57414331Speter */ 57514331Speter 57614331Speterint 57730994Sphklinux_access(struct proc *p, struct linux_access_args *args) 57814331Speter{ 57914331Speter struct access_args bsd; 58014331Speter caddr_t sg; 58114331Speter 58214331Speter sg = stackgap_init(); 58314331Speter CHECKALTEXIST(p, &sg, args->path); 58414331Speter 58514331Speter#ifdef DEBUG 58614331Speter printf("Linux-emul(%d): access(%s, %d)\n", 58714331Speter p->p_pid, args->path, args->flags); 58814331Speter#endif 58914331Speter bsd.path = args->path; 59014331Speter bsd.flags = args->flags; 59114331Speter 59230994Sphk return access(p, &bsd); 59314331Speter} 59414331Speter 59514331Speterint 59630994Sphklinux_unlink(struct proc *p, struct linux_unlink_args *args) 59714331Speter{ 59814331Speter struct unlink_args bsd; 59914331Speter caddr_t sg; 60014331Speter 60114331Speter sg = stackgap_init(); 60214331Speter CHECKALTEXIST(p, &sg, args->path); 60314331Speter 60414331Speter#ifdef DEBUG 60514331Speter printf("Linux-emul(%d): unlink(%s)\n", 60614331Speter p->p_pid, args->path); 60714331Speter#endif 60814331Speter bsd.path = args->path; 60914331Speter 61030994Sphk return unlink(p, &bsd); 61114331Speter} 61214331Speter 61314331Speterint 61430994Sphklinux_chdir(struct proc *p, struct linux_chdir_args *args) 61514331Speter{ 61614331Speter struct chdir_args bsd; 61714331Speter caddr_t sg; 61814331Speter 61914331Speter sg = stackgap_init(); 62014331Speter CHECKALTEXIST(p, &sg, args->path); 62114331Speter 62214331Speter#ifdef DEBUG 62314331Speter printf("Linux-emul(%d): chdir(%s)\n", 62414331Speter p->p_pid, args->path); 62514331Speter#endif 62614331Speter bsd.path = args->path; 62714331Speter 62830994Sphk return chdir(p, &bsd); 62914331Speter} 63014331Speter 63114331Speterint 63230994Sphklinux_chmod(struct proc *p, struct linux_chmod_args *args) 63314331Speter{ 63414331Speter struct chmod_args bsd; 63514331Speter caddr_t sg; 63614331Speter 63714331Speter sg = stackgap_init(); 63814331Speter CHECKALTEXIST(p, &sg, args->path); 63914331Speter 64014331Speter#ifdef DEBUG 64114331Speter printf("Linux-emul(%d): chmod(%s, %d)\n", 64214331Speter p->p_pid, args->path, args->mode); 64314331Speter#endif 64414331Speter bsd.path = args->path; 64514331Speter bsd.mode = args->mode; 64614331Speter 64730994Sphk return chmod(p, &bsd); 64814331Speter} 64914331Speter 65014331Speterint 65130994Sphklinux_chown(struct proc *p, struct linux_chown_args *args) 65214331Speter{ 65314331Speter struct chown_args bsd; 65414331Speter caddr_t sg; 65514331Speter 65614331Speter sg = stackgap_init(); 65714331Speter CHECKALTEXIST(p, &sg, args->path); 65814331Speter 65914331Speter#ifdef DEBUG 66014331Speter printf("Linux-emul(%d): chown(%s, %d, %d)\n", 66114331Speter p->p_pid, args->path, args->uid, args->gid); 66214331Speter#endif 66314331Speter bsd.path = args->path; 66414331Speter /* XXX size casts here */ 66514331Speter bsd.uid = args->uid; 66614331Speter bsd.gid = args->gid; 66714331Speter 66830994Sphk return chown(p, &bsd); 66914331Speter} 67014331Speter 67114331Speterint 67230994Sphklinux_mkdir(struct proc *p, struct linux_mkdir_args *args) 67314331Speter{ 67414331Speter struct mkdir_args bsd; 67514331Speter caddr_t sg; 67614331Speter 67714331Speter sg = stackgap_init(); 67814331Speter CHECKALTCREAT(p, &sg, args->path); 67914331Speter 68014331Speter#ifdef DEBUG 68114331Speter printf("Linux-emul(%d): mkdir(%s, %d)\n", 68214331Speter p->p_pid, args->path, args->mode); 68314331Speter#endif 68414331Speter bsd.path = args->path; 68514331Speter bsd.mode = args->mode; 68614331Speter 68730994Sphk return mkdir(p, &bsd); 68814331Speter} 68914331Speter 69014331Speterint 69130994Sphklinux_rmdir(struct proc *p, struct linux_rmdir_args *args) 69214331Speter{ 69314331Speter struct rmdir_args bsd; 69414331Speter caddr_t sg; 69514331Speter 69614331Speter sg = stackgap_init(); 69714331Speter CHECKALTEXIST(p, &sg, args->path); 69814331Speter 69914331Speter#ifdef DEBUG 70014331Speter printf("Linux-emul(%d): rmdir(%s)\n", 70114331Speter p->p_pid, args->path); 70214331Speter#endif 70314331Speter bsd.path = args->path; 70414331Speter 70530994Sphk return rmdir(p, &bsd); 70614331Speter} 70714331Speter 70814331Speterint 70930994Sphklinux_rename(struct proc *p, struct linux_rename_args *args) 71014331Speter{ 71114331Speter struct rename_args bsd; 71214331Speter caddr_t sg; 71314331Speter 71414331Speter sg = stackgap_init(); 71514331Speter CHECKALTEXIST(p, &sg, args->from); 71614331Speter CHECKALTCREAT(p, &sg, args->to); 71714331Speter 71814331Speter#ifdef DEBUG 71914331Speter printf("Linux-emul(%d): rename(%s, %s)\n", 72014331Speter p->p_pid, args->from, args->to); 72114331Speter#endif 72214331Speter bsd.from = args->from; 72314331Speter bsd.to = args->to; 72414331Speter 72530994Sphk return rename(p, &bsd); 72614331Speter} 72714331Speter 72814331Speterint 72930994Sphklinux_symlink(struct proc *p, struct linux_symlink_args *args) 73014331Speter{ 73114331Speter struct symlink_args bsd; 73214331Speter caddr_t sg; 73314331Speter 73414331Speter sg = stackgap_init(); 73514331Speter CHECKALTEXIST(p, &sg, args->path); 73614331Speter CHECKALTCREAT(p, &sg, args->to); 73714331Speter 73814331Speter#ifdef DEBUG 73914331Speter printf("Linux-emul(%d): symlink(%s, %s)\n", 74014331Speter p->p_pid, args->path, args->to); 74114331Speter#endif 74214331Speter bsd.path = args->path; 74314331Speter bsd.link = args->to; 74414331Speter 74530994Sphk return symlink(p, &bsd); 74614331Speter} 74714331Speter 74814331Speterint 74930994Sphklinux_execve(struct proc *p, struct linux_execve_args *args) 75014331Speter{ 75114331Speter struct execve_args bsd; 75214331Speter caddr_t sg; 75314331Speter 75414331Speter sg = stackgap_init(); 75514331Speter CHECKALTEXIST(p, &sg, args->path); 75614331Speter 75714331Speter#ifdef DEBUG 75814331Speter printf("Linux-emul(%d): execve(%s)\n", 75914331Speter p->p_pid, args->path); 76014331Speter#endif 76114331Speter bsd.fname = args->path; 76214331Speter bsd.argv = args->argp; 76314331Speter bsd.envv = args->envp; 76414331Speter 76530994Sphk return execve(p, &bsd); 76614331Speter} 76714331Speter 76814331Speterint 76930994Sphklinux_readlink(struct proc *p, struct linux_readlink_args *args) 77014331Speter{ 77114331Speter struct readlink_args bsd; 77214331Speter caddr_t sg; 77314331Speter 77414331Speter sg = stackgap_init(); 77514331Speter CHECKALTEXIST(p, &sg, args->name); 77614331Speter 77714331Speter#ifdef DEBUG 77814331Speter printf("Linux-emul(%d): readlink(%s, 0x%x, %d)\n", 77914331Speter p->p_pid, args->name, args->buf, args->count); 78014331Speter#endif 78114331Speter bsd.path = args->name; 78214331Speter bsd.buf = args->buf; 78314331Speter bsd.count = args->count; 78414331Speter 78530994Sphk return readlink(p, &bsd); 78614331Speter} 78714331Speter 78814331Speterint 78930994Sphklinux_truncate(struct proc *p, struct linux_truncate_args *args) 79014331Speter{ 79114331Speter struct otruncate_args bsd; 79214331Speter caddr_t sg; 79314331Speter 79414331Speter sg = stackgap_init(); 79514331Speter CHECKALTEXIST(p, &sg, args->path); 79614331Speter 79714331Speter#ifdef DEBUG 79814331Speter printf("Linux-emul(%d): truncate(%s)\n", 79914331Speter p->p_pid, args->path); 80014331Speter#endif 80114331Speter bsd.path = args->path; 80214331Speter 80330994Sphk return otruncate(p, &bsd); 80414331Speter} 80514331Speter 806