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