linux_file.c revision 14331
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 *
2814331Speter *  $Id: linux_file.c,v 1.5 1995/12/15 03:06:50 peter Exp $
299313Ssos */
309313Ssos
319313Ssos#include <sys/param.h>
329313Ssos#include <sys/systm.h>
3312458Sbde#include <sys/sysproto.h>
349313Ssos#include <sys/fcntl.h>
359313Ssos#include <sys/file.h>
369313Ssos#include <sys/filedesc.h>
379313Ssos#include <sys/proc.h>
389313Ssos#include <sys/ioctl.h>
399313Ssos#include <sys/stat.h>
409313Ssos#include <sys/vnode.h>
419313Ssos#include <sys/malloc.h>
429313Ssos#include <sys/exec.h>
439313Ssos#include <sys/dirent.h>
4414331Speter#include <sys/sysproto.h>
4514331Speter#include <sys/conf.h>
4614331Speter#include <sys/tty.h>
4712458Sbde
489313Ssos#include <ufs/ufs/dir.h>
499313Ssos
5012458Sbde#include <i386/linux/linux.h>
5114331Speter#include <i386/linux/linux_proto.h>
5214331Speter#include <i386/linux/linux_util.h>
539313Ssos
549313Ssosint
559313Ssoslinux_creat(struct proc *p, struct linux_creat_args *args, int *retval)
569313Ssos{
5712858Speter    struct open_args /* {
589313Ssos	char *path;
599313Ssos	int flags;
609313Ssos	int mode;
6112858Speter    } */ bsd_open_args;
6214331Speter    caddr_t sg;
639313Ssos
6414331Speter    sg = stackgap_init();
6514331Speter    CHECKALTCREAT(p, &sg, args->path);
6614331Speter
679313Ssos#ifdef DEBUG
689313Ssos    printf("Linux-emul(%d): creat(%s, %d)\n",
699313Ssos	   p->p_pid, args->path, args->mode);
709313Ssos#endif
719313Ssos    bsd_open_args.path = args->path;
729313Ssos    bsd_open_args.mode = args->mode;
739313Ssos    bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC;
749313Ssos    return open(p, &bsd_open_args, retval);
759313Ssos}
769313Ssos
779313Ssosint
789313Ssoslinux_open(struct proc *p, struct linux_open_args *args, int *retval)
799313Ssos{
8012858Speter    struct open_args /* {
819313Ssos	char *path;
829313Ssos	int flags;
839313Ssos	int mode;
8412858Speter    } */ bsd_open_args;
859313Ssos    int error;
8614331Speter    caddr_t sg;
8714331Speter
8814331Speter    sg = stackgap_init();
899313Ssos
9014331Speter    if (args->flags & LINUX_O_CREAT)
9114331Speter	CHECKALTCREAT(p, &sg, args->path);
9214331Speter    else
9314331Speter	CHECKALTEXIST(p, &sg, args->path);
9414331Speter
959313Ssos#ifdef DEBUG
969313Ssos    printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n",
979313Ssos	   p->p_pid, args->path, args->flags, args->mode);
989313Ssos#endif
999313Ssos    bsd_open_args.flags = 0;
1009313Ssos    if (args->flags & LINUX_O_RDONLY)
1019313Ssos	bsd_open_args.flags |= O_RDONLY;
1029313Ssos    if (args->flags & LINUX_O_WRONLY)
1039313Ssos	bsd_open_args.flags |= O_WRONLY;
1049313Ssos    if (args->flags & LINUX_O_RDWR)
1059313Ssos	bsd_open_args.flags |= O_RDWR;
1069313Ssos    if (args->flags & LINUX_O_NDELAY)
1079313Ssos	bsd_open_args.flags |= O_NONBLOCK;
1089313Ssos    if (args->flags & LINUX_O_APPEND)
1099313Ssos	bsd_open_args.flags |= O_APPEND;
1109313Ssos    if (args->flags & LINUX_O_SYNC)
1119313Ssos	bsd_open_args.flags |= O_FSYNC;
1129313Ssos    if (args->flags & LINUX_O_NONBLOCK)
1139313Ssos	bsd_open_args.flags |= O_NONBLOCK;
1149313Ssos    if (args->flags & LINUX_FASYNC)
1159313Ssos	bsd_open_args.flags |= O_ASYNC;
1169313Ssos    if (args->flags & LINUX_O_CREAT)
1179313Ssos	bsd_open_args.flags |= O_CREAT;
1189313Ssos    if (args->flags & LINUX_O_TRUNC)
1199313Ssos	bsd_open_args.flags |= O_TRUNC;
1209313Ssos    if (args->flags & LINUX_O_EXCL)
1219313Ssos	bsd_open_args.flags |= O_EXCL;
1229313Ssos    if (args->flags & LINUX_O_NOCTTY)
1239313Ssos	bsd_open_args.flags |= O_NOCTTY;
1249313Ssos    bsd_open_args.path = args->path;
1259313Ssos    bsd_open_args.mode = args->mode;
1269313Ssos
1279313Ssos    error = open(p, &bsd_open_args, retval);
1289313Ssos    if (!error && !(bsd_open_args.flags & O_NOCTTY) &&
1299313Ssos	SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
1309313Ssos	struct filedesc *fdp = p->p_fd;
1319313Ssos	struct file *fp = fdp->fd_ofiles[*retval];
1329313Ssos
1339313Ssos	if (fp->f_type == DTYPE_VNODE)
1349313Ssos	    (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p);
1359313Ssos    }
13614331Speter#ifdef DEBUG
13714331Speter    printf("Linux-emul(%d): open returns error %d\n",
13814331Speter	   p->p_pid, error);
13914331Speter#endif
1409313Ssos    return error;
1419313Ssos}
1429313Ssos
1439313Ssosstruct linux_flock {
1449313Ssos    short l_type;
1459313Ssos    short l_whence;
1469313Ssos    linux_off_t l_start;
1479313Ssos    linux_off_t l_len;
1489313Ssos    linux_pid_t l_pid;
1499313Ssos};
1509313Ssos
1519313Ssosstatic void
1529313Ssoslinux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock)
1539313Ssos{
1549313Ssos    switch (linux_flock->l_type) {
1559313Ssos    case LINUX_F_RDLCK:
1569313Ssos	bsd_flock->l_type = F_RDLCK;
1579313Ssos	break;
1589313Ssos    case LINUX_F_WRLCK:
1599313Ssos	bsd_flock->l_type = F_WRLCK;
1609313Ssos	break;
1619313Ssos    case LINUX_F_UNLCK:
1629313Ssos	bsd_flock->l_type = F_UNLCK;
1639313Ssos	break;
1649313Ssos    }
1659313Ssos    bsd_flock->l_whence = linux_flock->l_whence;
1669313Ssos    bsd_flock->l_start = (off_t)linux_flock->l_start;
1679313Ssos    bsd_flock->l_len = (off_t)linux_flock->l_len;
1689313Ssos    bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
1699313Ssos}
1709313Ssos
1719313Ssosstatic void
1729313Ssosbsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock)
1739313Ssos{
1749313Ssos    switch (bsd_flock->l_type) {
1759313Ssos    case F_RDLCK:
1769313Ssos	linux_flock->l_type = LINUX_F_RDLCK;
1779313Ssos	break;
1789313Ssos    case F_WRLCK:
1799313Ssos	linux_flock->l_type = LINUX_F_WRLCK;
1809313Ssos	break;
1819313Ssos    case F_UNLCK:
1829313Ssos	linux_flock->l_type = LINUX_F_UNLCK;
1839313Ssos	break;
1849313Ssos    }
1859313Ssos    linux_flock->l_whence = bsd_flock->l_whence;
1869313Ssos    linux_flock->l_start = (linux_off_t)bsd_flock->l_start;
1879313Ssos    linux_flock->l_len = (linux_off_t)bsd_flock->l_len;
1889313Ssos    linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid;
1899313Ssos}
1909313Ssos
1919313Ssosint
1929313Ssoslinux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval)
1939313Ssos{
1949313Ssos    int error, result;
19512858Speter    struct fcntl_args /* {
1969313Ssos	int fd;
1979313Ssos	int cmd;
1989313Ssos	int arg;
19912858Speter    } */ fcntl_args;
2009313Ssos    struct linux_flock linux_flock;
20114331Speter    struct flock *bsd_flock;
20214331Speter    struct filedesc *fdp;
20314331Speter    struct file *fp;
20414331Speter    struct vnode *vp;
20514331Speter    struct vattr va;
20614331Speter    long pgid;
20714331Speter    struct pgrp *pgrp;
20814331Speter    struct tty *tp, *(*d_tty) __P((dev_t));
20914331Speter    caddr_t sg;
2109313Ssos
21114331Speter    sg = stackgap_init();
21214331Speter    bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(struct flock));
21314331Speter    d_tty = NULL;
21414331Speter
2159313Ssos#ifdef DEBUG
2169313Ssos    printf("Linux-emul(%d): fcntl(%d, %08x, *)\n",
2179313Ssos	   p->p_pid, args->fd, args->cmd);
2189313Ssos#endif
2199313Ssos    fcntl_args.fd = args->fd;
2209313Ssos    fcntl_args.arg = 0;
2219313Ssos
2229313Ssos    switch (args->cmd) {
2239313Ssos    case LINUX_F_DUPFD:
2249313Ssos	fcntl_args.cmd = F_DUPFD;
2259313Ssos	return fcntl(p, &fcntl_args, retval);
2269313Ssos
2279313Ssos    case LINUX_F_GETFD:
2289313Ssos	fcntl_args.cmd = F_GETFD;
2299313Ssos	return fcntl(p, &fcntl_args, retval);
2309313Ssos
2319313Ssos    case LINUX_F_SETFD:
2329313Ssos	fcntl_args.cmd = F_SETFD;
2339313Ssos	return fcntl(p, &fcntl_args, retval);
2349313Ssos
2359313Ssos    case LINUX_F_GETFL:
2369313Ssos	fcntl_args.cmd = F_GETFL;
2379313Ssos	error = fcntl(p, &fcntl_args, &result);
2389313Ssos	*retval = 0;
2399313Ssos	if (result & O_RDONLY) *retval |= LINUX_O_RDONLY;
2409313Ssos	if (result & O_WRONLY) *retval |= LINUX_O_WRONLY;
2419313Ssos	if (result & O_RDWR) *retval |= LINUX_O_RDWR;
2429313Ssos	if (result & O_NDELAY) *retval |= LINUX_O_NONBLOCK;
2439313Ssos	if (result & O_APPEND) *retval |= LINUX_O_APPEND;
2449313Ssos	if (result & O_FSYNC) *retval |= LINUX_O_SYNC;
2459313Ssos	return error;
2469313Ssos
2479313Ssos    case LINUX_F_SETFL:
2489313Ssos	if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK;
2499313Ssos	if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND;
2509313Ssos	if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC;
2519313Ssos	fcntl_args.cmd = F_SETFL;
2529313Ssos	return fcntl(p, &fcntl_args, retval);
2539313Ssos
2549313Ssos    case LINUX_F_GETLK:
2559313Ssos	if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
2569313Ssos		   	    sizeof(struct linux_flock))))
2579313Ssos	    return error;
2589313Ssos	linux_to_bsd_flock(&linux_flock, bsd_flock);
2599313Ssos	fcntl_args.cmd = F_GETLK;
2609313Ssos	fcntl_args.arg = (int)bsd_flock;
2619313Ssos	if (error = fcntl(p, &fcntl_args, retval))
2629313Ssos	    return error;
2639313Ssos	bsd_to_linux_flock(bsd_flock, &linux_flock);
2649313Ssos	return copyout((caddr_t)&linux_flock, (caddr_t)args->arg,
2659313Ssos		       sizeof(struct linux_flock));
2669313Ssos
2679313Ssos    case LINUX_F_SETLK:
2689313Ssos	if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
2699313Ssos		   	    sizeof(struct linux_flock))))
2709313Ssos	    return error;
2719313Ssos	linux_to_bsd_flock(&linux_flock, bsd_flock);
2729313Ssos	fcntl_args.cmd = F_SETLK;
2739313Ssos	fcntl_args.arg = (int)bsd_flock;
2749313Ssos	return fcntl(p, &fcntl_args, retval);
2759313Ssos
2769313Ssos    case LINUX_F_SETLKW:
2779313Ssos	if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
2789313Ssos		   	    sizeof(struct linux_flock))))
2799313Ssos	    return error;
2809313Ssos	linux_to_bsd_flock(&linux_flock, bsd_flock);
2819313Ssos	fcntl_args.cmd = F_SETLKW;
2829313Ssos	fcntl_args.arg = (int)bsd_flock;
2839313Ssos	return fcntl(p, &fcntl_args, retval);
2849313Ssos
2859313Ssos    case LINUX_F_SETOWN:
28614331Speter    case LINUX_F_GETOWN:
28714331Speter	/*
28814331Speter	 * We need to route around the normal fcntl() for these calls,
28914331Speter	 * since it uses TIOC{G,S}PGRP, which is too restrictive for
29014331Speter	 * Linux F_{G,S}ETOWN semantics. For sockets, this problem
29114331Speter	 * does not exist.
29214331Speter	 */
29314331Speter	fdp = p->p_fd;
29414331Speter	if ((u_int)args->fd >= fdp->fd_nfiles ||
29514331Speter		(fp = fdp->fd_ofiles[args->fd]) == NULL)
29614331Speter	    return EBADF;
29714331Speter	if (fp->f_type == DTYPE_SOCKET) {
29814331Speter	    fcntl_args.cmd = args->cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
29914331Speter	    return fcntl(p, &fcntl_args, retval);
30014331Speter	}
30114331Speter	vp = (struct vnode *)fp->f_data;
30214331Speter	if (vp->v_type != VCHR)
30314331Speter	    return EINVAL;
30414331Speter	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
30514331Speter	    return error;
3069313Ssos
30714331Speter	d_tty = cdevsw[major(va.va_rdev)]->d_devtotty;
30814331Speter	if (!d_tty || (!(tp = (*d_tty)(va.va_rdev))))
30914331Speter	    return EINVAL;
31014331Speter	if (args->cmd == LINUX_F_GETOWN) {
31114331Speter	    retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
31214331Speter	    return 0;
31314331Speter	}
31414331Speter	if ((long)args->arg <= 0) {
31514331Speter	    pgid = -(long)args->arg;
31614331Speter	} else {
31714331Speter	    struct proc *p1 = pfind((long)args->arg);
31814331Speter	    if (p1 == 0)
31914331Speter		return (ESRCH);
32014331Speter	    pgid = (long)p1->p_pgrp->pg_id;
32114331Speter	}
32214331Speter	pgrp = pgfind(pgid);
32314331Speter	if (pgrp == NULL || pgrp->pg_session != p->p_session)
32414331Speter	    return EPERM;
32514331Speter	tp->t_pgrp = pgrp;
32614331Speter	return 0;
3279313Ssos    }
3289313Ssos    return EINVAL;
3299313Ssos}
3309313Ssos
3319313Ssosint
3329313Ssoslinux_lseek(struct proc *p, struct linux_lseek_args *args, int *retval)
3339313Ssos{
3349313Ssos
33512858Speter    struct lseek_args /* {
33612858Speter	int fd;
3379313Ssos	int pad;
33812858Speter	off_t offset;
3399313Ssos	int whence;
34012858Speter    } */ tmp_args;
3419313Ssos    int error;
3429313Ssos
3439313Ssos#ifdef DEBUG
3449313Ssos    printf("Linux-emul(%d): lseek(%d, %d, %d)\n",
3459313Ssos	   p->p_pid, args->fdes, args->off, args->whence);
3469313Ssos#endif
34712858Speter    tmp_args.fd = args->fdes;
34812858Speter    tmp_args.offset = (off_t)args->off;
3499313Ssos    tmp_args.whence = args->whence;
35012858Speter    error = lseek(p, &tmp_args, retval);
3519313Ssos    return error;
3529313Ssos}
3539313Ssos
35414331Speterint
35514331Speterlinux_llseek(struct proc *p, struct linux_llseek_args *args, int *retval)
35614331Speter{
35714331Speter	struct lseek_args bsd_args;
35814331Speter	int error;
35914331Speter	off_t off;
36014331Speter
36114331Speter#ifdef DEBUG
36214331Speter        printf("Linux-emul(%d): llseek(%d, %d:%d, %d)\n",
36314331Speter	   p->p_pid, args->fd, args->ohigh, args->olow, args->whence);
36414331Speter#endif
36514331Speter	off = (args->olow) | (((off_t) args->ohigh) << 32);
36614331Speter
36714331Speter	bsd_args.fd = args->fd;
36814331Speter	bsd_args.offset = off;
36914331Speter	bsd_args.whence = args->whence;
37014331Speter
37114331Speter	if ((error = lseek(p, &bsd_args, retval)))
37214331Speter		return error;
37314331Speter
37414331Speter	if ((error = copyout(retval, (caddr_t)args->res, sizeof (off_t))))
37514331Speter		return error;
37614331Speter
37714331Speter	retval[0] = 0;
37814331Speter	return 0;
37914331Speter}
38014331Speter
38114331Speter
3829313Ssosstruct linux_dirent {
3839313Ssos    long dino;
3849313Ssos    linux_off_t doff;
3859313Ssos    unsigned short dreclen;
3869313Ssos    char dname[LINUX_NAME_MAX + 1];
3879313Ssos};
3889313Ssos
3899313Ssos#define LINUX_RECLEN(de,namlen) \
3909313Ssos    ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1))
3919313Ssos
3929313Ssosint
3939313Ssoslinux_readdir(struct proc *p, struct linux_readdir_args *args, int *retval)
3949313Ssos{
39514331Speter	struct linux_getdents_args lda;
39614331Speter
39714331Speter	lda.fd = args->fd;
39814331Speter	lda.dent = args->dent;
39914331Speter	lda.count = 1;
40014331Speter	return linux_getdents(p, &lda, retval);
40114331Speter}
40214331Speter
40314331Speterint
40414331Speterlinux_getdents(struct proc *p, struct linux_getdents_args *args, int *retval)
40514331Speter{
4069313Ssos    register struct dirent *bdp;
4079313Ssos    struct vnode *vp;
4089313Ssos    caddr_t inp, buf;		/* BSD-format */
4099313Ssos    int len, reclen;		/* BSD-format */
4109313Ssos    caddr_t outp;		/* Linux-format */
4119313Ssos    int resid, linuxreclen=0;	/* Linux-format */
4129313Ssos    struct file *fp;
4139313Ssos    struct uio auio;
4149313Ssos    struct iovec aiov;
4159313Ssos    struct vattr va;
4169313Ssos    off_t off;
4179313Ssos    struct linux_dirent linux_dirent;
41810355Sswallace    int buflen, error, eofflag, nbytes, justone, blockoff;
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;
44911418Sswallace    blockoff = off % DIRBLKSIZ;
45011418Sswallace    buflen = max(DIRBLKSIZ, nbytes + blockoff);
45111418Sswallace    buflen = min(buflen, MAXBSIZE);
4529313Ssos    buf = malloc(buflen, M_TEMP, M_WAITOK);
4539313Ssos    VOP_LOCK(vp);
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;
46310355Sswallace    auio.uio_offset = off - (off_t)blockoff;
4649313Ssos
46512458Sbde    error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (int *) NULL,
46612458Sbde			(u_int **) NULL);
46710355Sswallace    if (error) {
4689313Ssos	goto out;
46914331Speter    }
4709313Ssos
4719313Ssos    inp = buf;
47210355Sswallace    inp += blockoff;
4739313Ssos    outp = (caddr_t) args->dent;
4749313Ssos    resid = nbytes;
47510355Sswallace    if ((len = buflen - auio.uio_resid - blockoff) == 0) {
4769313Ssos	goto eof;
47714331Speter    }
4789313Ssos
4799313Ssos    while (len > 0) {
48010355Sswallace	bdp = (struct dirent *) inp;
48110355Sswallace	reclen = bdp->d_reclen;
48210355Sswallace	if (reclen & 3) {
48310355Sswallace	    printf("linux_readdir: reclen=%d\n", reclen);
48410355Sswallace	    error = EFAULT;
48510355Sswallace	    goto out;
48610355Sswallace	}
48710355Sswallace
4889313Ssos	if (bdp->d_fileno == 0) {
4899313Ssos	    inp += reclen;
49011418Sswallace	    off += reclen;
49110355Sswallace	    len -= reclen;
4929313Ssos	    continue;
4939313Ssos	}
4949313Ssos	linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
4959313Ssos	if (reclen > len || resid < linuxreclen) {
4969313Ssos	    outp++;
4979313Ssos	    break;
4989313Ssos	}
4999313Ssos	linux_dirent.dino = (long) bdp->d_fileno;
5009313Ssos	linux_dirent.doff = (linux_off_t) linuxreclen;
5019313Ssos	linux_dirent.dreclen = (u_short) bdp->d_namlen;
5029313Ssos	strcpy(linux_dirent.dname, bdp->d_name);
50310355Sswallace	if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) {
5049313Ssos	    goto out;
50514331Speter	}
5069313Ssos	inp += reclen;
50711418Sswallace	off += reclen;
5089313Ssos	outp += linuxreclen;
5099313Ssos	resid -= linuxreclen;
5109313Ssos	len -= reclen;
5119313Ssos	if (justone)
5129313Ssos	    break;
5139313Ssos    }
5149313Ssos
5159313Ssos    if (outp == (caddr_t) args->dent)
5169313Ssos	goto again;
5179313Ssos    fp->f_offset = off;
5189313Ssos
5199313Ssos    if (justone)
5209313Ssos	nbytes = resid + linuxreclen;
52110355Sswallace
5229313Ssoseof:
5239313Ssos    *retval = nbytes - resid;
5249313Ssosout:
5259313Ssos    VOP_UNLOCK(vp);
5269313Ssos    free(buf, M_TEMP);
5279313Ssos    return error;
5289313Ssos}
52914331Speter
53014331Speter/*
53114331Speter * These exist mainly for hooks for doing /compat/linux translation.
53214331Speter */
53314331Speter
53414331Speterint
53514331Speterlinux_access(struct proc *p, struct linux_access_args *args, int *retval)
53614331Speter{
53714331Speter	struct access_args bsd;
53814331Speter	caddr_t sg;
53914331Speter
54014331Speter	sg = stackgap_init();
54114331Speter	CHECKALTEXIST(p, &sg, args->path);
54214331Speter
54314331Speter#ifdef DEBUG
54414331Speter        printf("Linux-emul(%d): access(%s, %d)\n",
54514331Speter	    p->p_pid, args->path, args->flags);
54614331Speter#endif
54714331Speter	bsd.path = args->path;
54814331Speter	bsd.flags = args->flags;
54914331Speter
55014331Speter	return access(p, &bsd, retval);
55114331Speter}
55214331Speter
55314331Speterint
55414331Speterlinux_unlink(struct proc *p, struct linux_unlink_args *args, int *retval)
55514331Speter{
55614331Speter	struct unlink_args bsd;
55714331Speter	caddr_t sg;
55814331Speter
55914331Speter	sg = stackgap_init();
56014331Speter	CHECKALTEXIST(p, &sg, args->path);
56114331Speter
56214331Speter#ifdef DEBUG
56314331Speter	printf("Linux-emul(%d): unlink(%s)\n",
56414331Speter	   p->p_pid, args->path);
56514331Speter#endif
56614331Speter	bsd.path = args->path;
56714331Speter
56814331Speter	return unlink(p, &bsd, retval);
56914331Speter}
57014331Speter
57114331Speterint
57214331Speterlinux_chdir(struct proc *p, struct linux_chdir_args *args, int *retval)
57314331Speter{
57414331Speter	struct chdir_args bsd;
57514331Speter	caddr_t sg;
57614331Speter
57714331Speter	sg = stackgap_init();
57814331Speter	CHECKALTEXIST(p, &sg, args->path);
57914331Speter
58014331Speter#ifdef DEBUG
58114331Speter	printf("Linux-emul(%d): chdir(%s)\n",
58214331Speter	   p->p_pid, args->path);
58314331Speter#endif
58414331Speter	bsd.path = args->path;
58514331Speter
58614331Speter	return chdir(p, &bsd, retval);
58714331Speter}
58814331Speter
58914331Speterint
59014331Speterlinux_chmod(struct proc *p, struct linux_chmod_args *args, int *retval)
59114331Speter{
59214331Speter	struct chmod_args bsd;
59314331Speter	caddr_t sg;
59414331Speter
59514331Speter	sg = stackgap_init();
59614331Speter	CHECKALTEXIST(p, &sg, args->path);
59714331Speter
59814331Speter#ifdef DEBUG
59914331Speter        printf("Linux-emul(%d): chmod(%s, %d)\n",
60014331Speter	    p->p_pid, args->path, args->mode);
60114331Speter#endif
60214331Speter	bsd.path = args->path;
60314331Speter	bsd.mode = args->mode;
60414331Speter
60514331Speter	return chmod(p, &bsd, retval);
60614331Speter}
60714331Speter
60814331Speterint
60914331Speterlinux_chown(struct proc *p, struct linux_chown_args *args, int *retval)
61014331Speter{
61114331Speter	struct chown_args bsd;
61214331Speter	caddr_t sg;
61314331Speter
61414331Speter	sg = stackgap_init();
61514331Speter	CHECKALTEXIST(p, &sg, args->path);
61614331Speter
61714331Speter#ifdef DEBUG
61814331Speter        printf("Linux-emul(%d): chown(%s, %d, %d)\n",
61914331Speter	    p->p_pid, args->path, args->uid, args->gid);
62014331Speter#endif
62114331Speter	bsd.path = args->path;
62214331Speter	/* XXX size casts here */
62314331Speter	bsd.uid = args->uid;
62414331Speter	bsd.gid = args->gid;
62514331Speter
62614331Speter	return chown(p, &bsd, retval);
62714331Speter}
62814331Speter
62914331Speterint
63014331Speterlinux_mkdir(struct proc *p, struct linux_mkdir_args *args, int *retval)
63114331Speter{
63214331Speter	struct mkdir_args bsd;
63314331Speter	caddr_t sg;
63414331Speter
63514331Speter	sg = stackgap_init();
63614331Speter	CHECKALTCREAT(p, &sg, args->path);
63714331Speter
63814331Speter#ifdef DEBUG
63914331Speter        printf("Linux-emul(%d): mkdir(%s, %d)\n",
64014331Speter	    p->p_pid, args->path, args->mode);
64114331Speter#endif
64214331Speter	bsd.path = args->path;
64314331Speter	bsd.mode = args->mode;
64414331Speter
64514331Speter	return mkdir(p, &bsd, retval);
64614331Speter}
64714331Speter
64814331Speterint
64914331Speterlinux_rmdir(struct proc *p, struct linux_rmdir_args *args, int *retval)
65014331Speter{
65114331Speter	struct rmdir_args bsd;
65214331Speter	caddr_t sg;
65314331Speter
65414331Speter	sg = stackgap_init();
65514331Speter	CHECKALTEXIST(p, &sg, args->path);
65614331Speter
65714331Speter#ifdef DEBUG
65814331Speter        printf("Linux-emul(%d): rmdir(%s)\n",
65914331Speter	    p->p_pid, args->path);
66014331Speter#endif
66114331Speter	bsd.path = args->path;
66214331Speter
66314331Speter	return rmdir(p, &bsd, retval);
66414331Speter}
66514331Speter
66614331Speterint
66714331Speterlinux_rename(struct proc *p, struct linux_rename_args *args, int *retval)
66814331Speter{
66914331Speter	struct rename_args bsd;
67014331Speter	caddr_t sg;
67114331Speter
67214331Speter	sg = stackgap_init();
67314331Speter	CHECKALTEXIST(p, &sg, args->from);
67414331Speter	CHECKALTCREAT(p, &sg, args->to);
67514331Speter
67614331Speter#ifdef DEBUG
67714331Speter        printf("Linux-emul(%d): rename(%s, %s)\n",
67814331Speter	    p->p_pid, args->from, args->to);
67914331Speter#endif
68014331Speter	bsd.from = args->from;
68114331Speter	bsd.to = args->to;
68214331Speter
68314331Speter	return rename(p, &bsd, retval);
68414331Speter}
68514331Speter
68614331Speterint
68714331Speterlinux_symlink(struct proc *p, struct linux_symlink_args *args, int *retval)
68814331Speter{
68914331Speter	struct symlink_args bsd;
69014331Speter	caddr_t sg;
69114331Speter
69214331Speter	sg = stackgap_init();
69314331Speter	CHECKALTEXIST(p, &sg, args->path);
69414331Speter	CHECKALTCREAT(p, &sg, args->to);
69514331Speter
69614331Speter#ifdef DEBUG
69714331Speter        printf("Linux-emul(%d): symlink(%s, %s)\n",
69814331Speter	    p->p_pid, args->path, args->to);
69914331Speter#endif
70014331Speter	bsd.path = args->path;
70114331Speter	bsd.link = args->to;
70214331Speter
70314331Speter	return symlink(p, &bsd, retval);
70414331Speter}
70514331Speter
70614331Speterint
70714331Speterlinux_execve(struct proc *p, struct linux_execve_args *args, int *retval)
70814331Speter{
70914331Speter	struct execve_args bsd;
71014331Speter	caddr_t sg;
71114331Speter
71214331Speter	sg = stackgap_init();
71314331Speter	CHECKALTEXIST(p, &sg, args->path);
71414331Speter
71514331Speter#ifdef DEBUG
71614331Speter        printf("Linux-emul(%d): execve(%s)\n",
71714331Speter	    p->p_pid, args->path);
71814331Speter#endif
71914331Speter	bsd.fname = args->path;
72014331Speter	bsd.argv = args->argp;
72114331Speter	bsd.envv = args->envp;
72214331Speter
72314331Speter	return execve(p, &bsd, retval);
72414331Speter}
72514331Speter
72614331Speterint
72714331Speterlinux_readlink(struct proc *p, struct linux_readlink_args *args, int *retval)
72814331Speter{
72914331Speter	struct readlink_args bsd;
73014331Speter	caddr_t sg;
73114331Speter
73214331Speter	sg = stackgap_init();
73314331Speter	CHECKALTEXIST(p, &sg, args->name);
73414331Speter
73514331Speter#ifdef DEBUG
73614331Speter        printf("Linux-emul(%d): readlink(%s, 0x%x, %d)\n",
73714331Speter	    p->p_pid, args->name, args->buf, args->count);
73814331Speter#endif
73914331Speter	bsd.path = args->name;
74014331Speter	bsd.buf = args->buf;
74114331Speter	bsd.count = args->count;
74214331Speter
74314331Speter	return readlink(p, &bsd, retval);
74414331Speter}
74514331Speter
74614331Speterint
74714331Speterlinux_truncate(struct proc *p, struct linux_truncate_args *args, int *retval)
74814331Speter{
74914331Speter	struct otruncate_args bsd;
75014331Speter	caddr_t sg;
75114331Speter
75214331Speter	sg = stackgap_init();
75314331Speter	CHECKALTEXIST(p, &sg, args->path);
75414331Speter
75514331Speter#ifdef DEBUG
75614331Speter        printf("Linux-emul(%d): truncate(%s)\n",
75714331Speter	    p->p_pid, args->path);
75814331Speter#endif
75914331Speter	bsd.path = args->path;
76014331Speter
76114331Speter	return otruncate(p, &bsd, retval);
76214331Speter}
76314331Speter
764