linux_file.c revision 89319
19313Ssos/*-
29313Ssos * Copyright (c) 1994-1995 S�ren Schmidt
39313Ssos * All rights reserved.
49313Ssos *
59313Ssos * Redistribution and use in source and binary forms, with or without
69313Ssos * modification, are permitted provided that the following conditions
79313Ssos * are met:
89313Ssos * 1. Redistributions of source code must retain the above copyright
99313Ssos *    notice, this list of conditions and the following disclaimer
109313Ssos *    in this position and unchanged.
119313Ssos * 2. Redistributions in binary form must reproduce the above copyright
129313Ssos *    notice, this list of conditions and the following disclaimer in the
139313Ssos *    documentation and/or other materials provided with the distribution.
149313Ssos * 3. The name of the author may not be used to endorse or promote products
159313Ssos *    derived from this software withough specific prior written permission
169313Ssos *
179313Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
189313Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
199313Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
209313Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
219313Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
229313Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239313Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249313Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259313Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
269313Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279313Ssos *
2850477Speter * $FreeBSD: head/sys/compat/linux/linux_file.c 89319 2002-01-14 00:13:45Z alfred $
299313Ssos */
309313Ssos
3131784Seivind#include "opt_compat.h"
3231784Seivind
339313Ssos#include <sys/param.h>
349313Ssos#include <sys/systm.h>
3576166Smarkm#include <sys/conf.h>
3676166Smarkm#include <sys/dirent.h>
379313Ssos#include <sys/fcntl.h>
389313Ssos#include <sys/file.h>
399313Ssos#include <sys/filedesc.h>
4031561Sbde#include <sys/lock.h>
419313Ssos#include <sys/malloc.h>
4272538Sjlemon#include <sys/mount.h>
4376166Smarkm#include <sys/mutex.h>
4476166Smarkm#include <sys/proc.h>
4576166Smarkm#include <sys/sysproto.h>
4614331Speter#include <sys/tty.h>
4776166Smarkm#include <sys/vnode.h>
4812458Sbde
4972538Sjlemon#include <ufs/ufs/extattr.h>
5072538Sjlemon#include <ufs/ufs/quota.h>
5172538Sjlemon#include <ufs/ufs/ufsmount.h>
5272538Sjlemon
5364905Smarcel#include <machine/../linux/linux.h>
5468583Smarcel#include <machine/../linux/linux_proto.h>
5564905Smarcel#include <compat/linux/linux_util.h>
569313Ssos
5768201Sobrien#ifndef __alpha__
589313Ssosint
5983366Sjulianlinux_creat(struct thread *td, struct linux_creat_args *args)
609313Ssos{
6112858Speter    struct open_args /* {
629313Ssos	char *path;
639313Ssos	int flags;
649313Ssos	int mode;
6512858Speter    } */ bsd_open_args;
6614331Speter    caddr_t sg;
679313Ssos
6814331Speter    sg = stackgap_init();
6983366Sjulian    CHECKALTCREAT(td, &sg, args->path);
7014331Speter
719313Ssos#ifdef DEBUG
7272543Sjlemon	if (ldebug(creat))
7372543Sjlemon		printf(ARGS(creat, "%s, %d"), args->path, args->mode);
749313Ssos#endif
759313Ssos    bsd_open_args.path = args->path;
769313Ssos    bsd_open_args.mode = args->mode;
779313Ssos    bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC;
7883366Sjulian    return open(td, &bsd_open_args);
799313Ssos}
8068201Sobrien#endif /*!__alpha__*/
819313Ssos
829313Ssosint
8383366Sjulianlinux_open(struct thread *td, struct linux_open_args *args)
849313Ssos{
8512858Speter    struct open_args /* {
869313Ssos	char *path;
879313Ssos	int flags;
889313Ssos	int mode;
8912858Speter    } */ bsd_open_args;
9083382Sjhb    struct proc *p = td->td_proc;
919313Ssos    int error;
9214331Speter    caddr_t sg;
9314331Speter
9414331Speter    sg = stackgap_init();
959313Ssos
9614331Speter    if (args->flags & LINUX_O_CREAT)
9783366Sjulian	CHECKALTCREAT(td, &sg, args->path);
9814331Speter    else
9983366Sjulian	CHECKALTEXIST(td, &sg, args->path);
10014331Speter
1019313Ssos#ifdef DEBUG
10272543Sjlemon	if (ldebug(open))
10372543Sjlemon		printf(ARGS(open, "%s, 0x%x, 0x%x"),
10472543Sjlemon		    args->path, args->flags, args->mode);
1059313Ssos#endif
1069313Ssos    bsd_open_args.flags = 0;
1079313Ssos    if (args->flags & LINUX_O_RDONLY)
1089313Ssos	bsd_open_args.flags |= O_RDONLY;
1099313Ssos    if (args->flags & LINUX_O_WRONLY)
1109313Ssos	bsd_open_args.flags |= O_WRONLY;
1119313Ssos    if (args->flags & LINUX_O_RDWR)
1129313Ssos	bsd_open_args.flags |= O_RDWR;
1139313Ssos    if (args->flags & LINUX_O_NDELAY)
1149313Ssos	bsd_open_args.flags |= O_NONBLOCK;
1159313Ssos    if (args->flags & LINUX_O_APPEND)
1169313Ssos	bsd_open_args.flags |= O_APPEND;
1179313Ssos    if (args->flags & LINUX_O_SYNC)
1189313Ssos	bsd_open_args.flags |= O_FSYNC;
1199313Ssos    if (args->flags & LINUX_O_NONBLOCK)
1209313Ssos	bsd_open_args.flags |= O_NONBLOCK;
1219313Ssos    if (args->flags & LINUX_FASYNC)
1229313Ssos	bsd_open_args.flags |= O_ASYNC;
1239313Ssos    if (args->flags & LINUX_O_CREAT)
1249313Ssos	bsd_open_args.flags |= O_CREAT;
1259313Ssos    if (args->flags & LINUX_O_TRUNC)
1269313Ssos	bsd_open_args.flags |= O_TRUNC;
1279313Ssos    if (args->flags & LINUX_O_EXCL)
1289313Ssos	bsd_open_args.flags |= O_EXCL;
1299313Ssos    if (args->flags & LINUX_O_NOCTTY)
1309313Ssos	bsd_open_args.flags |= O_NOCTTY;
1319313Ssos    bsd_open_args.path = args->path;
1329313Ssos    bsd_open_args.mode = args->mode;
1339313Ssos
13483366Sjulian    error = open(td, &bsd_open_args);
13570061Sjhb    PROC_LOCK(p);
1369313Ssos    if (!error && !(bsd_open_args.flags & O_NOCTTY) &&
1379313Ssos	SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
13889306Salfred	struct file *fp;
1399313Ssos
14089319Salfred	error = fget(td, td->td_retval[0], &fp);
14170061Sjhb	PROC_UNLOCK(p);
14289319Salfred	if (!error) {
14389319Salfred		if (fp->f_type == DTYPE_VNODE)
14489319Salfred			fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td);
14589319Salfred	    fdrop(fp, td);
14689319Salfred	}
14770061Sjhb    } else
14870061Sjhb	PROC_UNLOCK(p);
14914331Speter#ifdef DEBUG
15072543Sjlemon	if (ldebug(open))
15172543Sjlemon		printf(LMSG("open returns error %d"), error);
15214331Speter#endif
1539313Ssos    return error;
1549313Ssos}
1559313Ssos
1569313Ssosint
15783366Sjulianlinux_lseek(struct thread *td, struct linux_lseek_args *args)
1589313Ssos{
1599313Ssos
16012858Speter    struct lseek_args /* {
16112858Speter	int fd;
1629313Ssos	int pad;
16312858Speter	off_t offset;
1649313Ssos	int whence;
16512858Speter    } */ tmp_args;
1669313Ssos    int error;
1679313Ssos
1689313Ssos#ifdef DEBUG
16972543Sjlemon	if (ldebug(lseek))
17072543Sjlemon		printf(ARGS(lseek, "%d, %ld, %d"),
17183221Smarcel		    args->fdes, (long)args->off, args->whence);
1729313Ssos#endif
17312858Speter    tmp_args.fd = args->fdes;
17412858Speter    tmp_args.offset = (off_t)args->off;
1759313Ssos    tmp_args.whence = args->whence;
17683366Sjulian    error = lseek(td, &tmp_args);
1779313Ssos    return error;
1789313Ssos}
1799313Ssos
18068201Sobrien#ifndef __alpha__
18114331Speterint
18283366Sjulianlinux_llseek(struct thread *td, struct linux_llseek_args *args)
18314331Speter{
18414331Speter	struct lseek_args bsd_args;
18514331Speter	int error;
18614331Speter	off_t off;
18714331Speter
18814331Speter#ifdef DEBUG
18972543Sjlemon	if (ldebug(llseek))
19072543Sjlemon		printf(ARGS(llseek, "%d, %d:%d, %d"),
19172543Sjlemon		    args->fd, args->ohigh, args->olow, args->whence);
19214331Speter#endif
19314331Speter	off = (args->olow) | (((off_t) args->ohigh) << 32);
19414331Speter
19514331Speter	bsd_args.fd = args->fd;
19614331Speter	bsd_args.offset = off;
19714331Speter	bsd_args.whence = args->whence;
19814331Speter
19983366Sjulian	if ((error = lseek(td, &bsd_args)))
20014331Speter		return error;
20114331Speter
20283366Sjulian	if ((error = copyout(td->td_retval, (caddr_t)args->res, sizeof (off_t))))
20314331Speter		return error;
20414331Speter
20583366Sjulian	td->td_retval[0] = 0;
20614331Speter	return 0;
20714331Speter}
20868201Sobrien#endif /*!__alpha__*/
20914331Speter
21068201Sobrien#ifndef __alpha__
2119313Ssosint
21283366Sjulianlinux_readdir(struct thread *td, struct linux_readdir_args *args)
2139313Ssos{
21414331Speter	struct linux_getdents_args lda;
21514331Speter
21614331Speter	lda.fd = args->fd;
21714331Speter	lda.dent = args->dent;
21814331Speter	lda.count = 1;
21983366Sjulian	return linux_getdents(td, &lda);
22014331Speter}
22168201Sobrien#endif /*!__alpha__*/
22214331Speter
22383221Smarcel/*
22483221Smarcel * Note that linux_getdents(2) and linux_getdents64(2) have the same
22583221Smarcel * arguments. They only differ in the definition of struct dirent they
22683221Smarcel * operate on. We use this to common the code, with the exception of
22783221Smarcel * accessing struct dirent. Note that linux_readdir(2) is implemented
22883221Smarcel * by means of linux_getdents(2). In this case we never operate on
22983221Smarcel * struct dirent64 and thus don't need to handle it...
23083221Smarcel */
23183221Smarcel
23283221Smarcelstruct l_dirent {
23383221Smarcel	l_long		d_ino;
23483221Smarcel	l_off_t		d_off;
23583221Smarcel	l_ushort	d_reclen;
23683221Smarcel	char		d_name[LINUX_NAME_MAX + 1];
23783221Smarcel};
23883221Smarcel
23983221Smarcelstruct l_dirent64 {
24083221Smarcel	uint64_t	d_ino;
24183221Smarcel	int64_t		d_off;
24283221Smarcel	l_ushort	d_reclen;
24383221Smarcel	u_char		d_type;
24483221Smarcel	char		d_name[LINUX_NAME_MAX + 1];
24583221Smarcel};
24683221Smarcel
24783221Smarcel#define LINUX_RECLEN(de,namlen) \
24883221Smarcel    ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1))
24983221Smarcel
25083221Smarcel#define	LINUX_DIRBLKSIZ		512
25183221Smarcel
25283221Smarcelstatic int
25383366Sjuliangetdents_common(struct thread *td, struct linux_getdents64_args *args,
25483221Smarcel    int is64bit)
25514331Speter{
25683221Smarcel	register struct dirent *bdp;
25783221Smarcel	struct vnode *vp;
25883221Smarcel	caddr_t inp, buf;		/* BSD-format */
25983221Smarcel	int len, reclen;		/* BSD-format */
26083221Smarcel	caddr_t outp;			/* Linux-format */
26183221Smarcel	int resid, linuxreclen=0;	/* Linux-format */
26283221Smarcel	struct file *fp;
26383221Smarcel	struct uio auio;
26483221Smarcel	struct iovec aiov;
26583221Smarcel	struct vattr va;
26683221Smarcel	off_t off;
26783221Smarcel	struct l_dirent linux_dirent;
26883221Smarcel	struct l_dirent64 linux_dirent64;
26983221Smarcel	int buflen, error, eofflag, nbytes, justone;
27083221Smarcel	u_long *cookies = NULL, *cookiep;
27183221Smarcel	int ncookies;
2729313Ssos
27383366Sjulian	if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0)
27483221Smarcel		return (error);
2759313Ssos
27689306Salfred	if ((fp->f_flag & FREAD) == 0) {
27789306Salfred		fdrop(fp, td);
27883221Smarcel		return (EBADF);
27989306Salfred	}
2809313Ssos
28183221Smarcel	vp = (struct vnode *) fp->f_data;
28289306Salfred	if (vp->v_type != VDIR) {
28389306Salfred		fdrop(fp, td);
28483221Smarcel		return (EINVAL);
28589306Salfred	}
2869313Ssos
28789306Salfred	if ((error = VOP_GETATTR(vp, &va, td->td_proc->p_ucred, td))) {
28889306Salfred		fdrop(fp, td);
28983221Smarcel		return (error);
29089306Salfred	}
2919313Ssos
29283221Smarcel	nbytes = args->count;
29383221Smarcel	if (nbytes == 1) {
29483221Smarcel		/* readdir(2) case. Always struct dirent. */
29589306Salfred		if (is64bit) {
29689306Salfred			fdrop(fp, td);
29783221Smarcel			return (EINVAL);
29889306Salfred		}
29983221Smarcel		nbytes = sizeof(linux_dirent);
30083221Smarcel		justone = 1;
30183221Smarcel	} else
30283221Smarcel		justone = 0;
3039313Ssos
30483221Smarcel	off = fp->f_offset;
3059313Ssos
30683221Smarcel	buflen = max(LINUX_DIRBLKSIZ, nbytes);
30783221Smarcel	buflen = min(buflen, MAXBSIZE);
30883221Smarcel	buf = malloc(buflen, M_TEMP, M_WAITOK);
30983366Sjulian	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
31083221Smarcel
3119313Ssosagain:
31283221Smarcel	aiov.iov_base = buf;
31383221Smarcel	aiov.iov_len = buflen;
31483221Smarcel	auio.uio_iov = &aiov;
31583221Smarcel	auio.uio_iovcnt = 1;
31683221Smarcel	auio.uio_rw = UIO_READ;
31783221Smarcel	auio.uio_segflg = UIO_SYSSPACE;
31883366Sjulian	auio.uio_td = td;
31983221Smarcel	auio.uio_resid = buflen;
32083221Smarcel	auio.uio_offset = off;
3219313Ssos
32283221Smarcel	if (cookies) {
32383221Smarcel		free(cookies, M_TEMP);
32483221Smarcel		cookies = NULL;
32583221Smarcel	}
32624654Sdfr
32783221Smarcel	if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
32883221Smarcel		 &cookies)))
32983221Smarcel		goto out;
3309313Ssos
33183221Smarcel	inp = buf;
33283221Smarcel	outp = (caddr_t)args->dirent;
33383221Smarcel	resid = nbytes;
33483221Smarcel	if ((len = buflen - auio.uio_resid) <= 0)
33583221Smarcel		goto eof;
3369313Ssos
33783221Smarcel	cookiep = cookies;
33824654Sdfr
33983221Smarcel	if (cookies) {
34083221Smarcel		/*
34183221Smarcel		 * When using cookies, the vfs has the option of reading from
34283221Smarcel		 * a different offset than that supplied (UFS truncates the
34383221Smarcel		 * offset to a block boundary to make sure that it never reads
34483221Smarcel		 * partway through a directory entry, even if the directory
34583221Smarcel		 * has been compacted).
34683221Smarcel		 */
34783221Smarcel		while (len > 0 && ncookies > 0 && *cookiep <= off) {
34883221Smarcel			bdp = (struct dirent *) inp;
34983221Smarcel			len -= bdp->d_reclen;
35083221Smarcel			inp += bdp->d_reclen;
35183221Smarcel			cookiep++;
35283221Smarcel			ncookies--;
35383221Smarcel		}
35424654Sdfr	}
35524654Sdfr
35683221Smarcel	while (len > 0) {
35783221Smarcel		if (cookiep && ncookies == 0)
35883221Smarcel			break;
35983221Smarcel		bdp = (struct dirent *) inp;
36083221Smarcel		reclen = bdp->d_reclen;
36183221Smarcel		if (reclen & 3) {
36283221Smarcel			error = EFAULT;
36383221Smarcel			goto out;
36483221Smarcel		}
36583221Smarcel
36683221Smarcel		if (bdp->d_fileno == 0) {
36783221Smarcel			inp += reclen;
36883221Smarcel			if (cookiep) {
36983221Smarcel				off = *cookiep++;
37083221Smarcel				ncookies--;
37183221Smarcel			} else
37283221Smarcel				off += reclen;
37383221Smarcel
37483221Smarcel			len -= reclen;
37583221Smarcel			continue;
37683221Smarcel		}
37783221Smarcel
37883221Smarcel		linuxreclen = (is64bit)
37983221Smarcel		    ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen)
38083221Smarcel		    : LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
38183221Smarcel
38283221Smarcel		if (reclen > len || resid < linuxreclen) {
38383221Smarcel			outp++;
38483221Smarcel			break;
38583221Smarcel		}
38683221Smarcel
38783221Smarcel		if (justone) {
38883221Smarcel			/* readdir(2) case. */
38983221Smarcel			linux_dirent.d_ino = (l_long)bdp->d_fileno;
39083221Smarcel			linux_dirent.d_off = (l_off_t)linuxreclen;
39183221Smarcel			linux_dirent.d_reclen = (l_ushort)bdp->d_namlen;
39283221Smarcel			strcpy(linux_dirent.d_name, bdp->d_name);
39383221Smarcel			error = copyout(&linux_dirent, outp, linuxreclen);
39483221Smarcel		} else {
39583221Smarcel			if (is64bit) {
39683221Smarcel				linux_dirent64.d_ino = bdp->d_fileno;
39783221Smarcel				linux_dirent64.d_off = (cookiep)
39883221Smarcel				    ? (l_off_t)*cookiep
39983221Smarcel				    : (l_off_t)(off + reclen);
40083221Smarcel				linux_dirent64.d_reclen =
40183221Smarcel				    (l_ushort)linuxreclen;
40283221Smarcel				linux_dirent64.d_type = bdp->d_type;
40383221Smarcel				strcpy(linux_dirent64.d_name, bdp->d_name);
40483221Smarcel				error = copyout(&linux_dirent64, outp,
40583221Smarcel				    linuxreclen);
40683221Smarcel			} else {
40783221Smarcel				linux_dirent.d_ino = bdp->d_fileno;
40883221Smarcel				linux_dirent.d_off = (cookiep)
40983221Smarcel				    ? (l_off_t)*cookiep
41083221Smarcel				    : (l_off_t)(off + reclen);
41183221Smarcel				linux_dirent.d_reclen = (l_ushort)linuxreclen;
41283221Smarcel				strcpy(linux_dirent.d_name, bdp->d_name);
41383221Smarcel				error = copyout(&linux_dirent, outp,
41483221Smarcel				    linuxreclen);
41583221Smarcel			}
41683221Smarcel		}
41783221Smarcel		if (error)
41883221Smarcel			goto out;
41983221Smarcel
42083221Smarcel		inp += reclen;
42183221Smarcel		if (cookiep) {
42283221Smarcel			off = *cookiep++;
42383221Smarcel			ncookies--;
42483221Smarcel		} else
42583221Smarcel			off += reclen;
42683221Smarcel
42783221Smarcel		outp += linuxreclen;
42883221Smarcel		resid -= linuxreclen;
42983221Smarcel		len -= reclen;
43083221Smarcel		if (justone)
43183221Smarcel			break;
43210355Sswallace	}
4339313Ssos
43483221Smarcel	if (outp == (caddr_t)args->dirent)
43583221Smarcel		goto again;
4369313Ssos
43783221Smarcel	fp->f_offset = off;
43883221Smarcel	if (justone)
43983221Smarcel		nbytes = resid + linuxreclen;
44010355Sswallace
4419313Ssoseof:
44283366Sjulian	td->td_retval[0] = nbytes - resid;
44383221Smarcel
4449313Ssosout:
44583221Smarcel	if (cookies)
44683221Smarcel		free(cookies, M_TEMP);
44783221Smarcel
44883366Sjulian	VOP_UNLOCK(vp, 0, td);
44989306Salfred	fdrop(fp, td);
45083221Smarcel	free(buf, M_TEMP);
45183221Smarcel	return (error);
4529313Ssos}
45314331Speter
45483221Smarcelint
45583366Sjulianlinux_getdents(struct thread *td, struct linux_getdents_args *args)
45683221Smarcel{
45783221Smarcel
45883221Smarcel#ifdef DEBUG
45983221Smarcel	if (ldebug(getdents))
46083221Smarcel		printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count);
46183221Smarcel#endif
46283221Smarcel
46383366Sjulian	return (getdents_common(td, (struct linux_getdents64_args*)args, 0));
46483221Smarcel}
46583221Smarcel
46683221Smarcelint
46783366Sjulianlinux_getdents64(struct thread *td, struct linux_getdents64_args *args)
46883221Smarcel{
46983221Smarcel
47083221Smarcel#ifdef DEBUG
47183221Smarcel	if (ldebug(getdents64))
47283221Smarcel		printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count);
47383221Smarcel#endif
47483221Smarcel
47583366Sjulian	return (getdents_common(td, args, 1));
47683221Smarcel}
47783221Smarcel
47814331Speter/*
47914331Speter * These exist mainly for hooks for doing /compat/linux translation.
48014331Speter */
48114331Speter
48214331Speterint
48383366Sjulianlinux_access(struct thread *td, struct linux_access_args *args)
48414331Speter{
48514331Speter	struct access_args bsd;
48614331Speter	caddr_t sg;
48714331Speter
48814331Speter	sg = stackgap_init();
48983366Sjulian	CHECKALTEXIST(td, &sg, args->path);
49014331Speter
49114331Speter#ifdef DEBUG
49272543Sjlemon	if (ldebug(access))
49372543Sjlemon		printf(ARGS(access, "%s, %d"), args->path, args->flags);
49414331Speter#endif
49514331Speter	bsd.path = args->path;
49614331Speter	bsd.flags = args->flags;
49714331Speter
49883366Sjulian	return access(td, &bsd);
49914331Speter}
50014331Speter
50114331Speterint
50283366Sjulianlinux_unlink(struct thread *td, struct linux_unlink_args *args)
50314331Speter{
50414331Speter	struct unlink_args bsd;
50514331Speter	caddr_t sg;
50614331Speter
50714331Speter	sg = stackgap_init();
50883366Sjulian	CHECKALTEXIST(td, &sg, args->path);
50914331Speter
51014331Speter#ifdef DEBUG
51172543Sjlemon	if (ldebug(unlink))
51272543Sjlemon		printf(ARGS(unlink, "%s"), args->path);
51314331Speter#endif
51414331Speter	bsd.path = args->path;
51514331Speter
51683366Sjulian	return unlink(td, &bsd);
51714331Speter}
51814331Speter
51914331Speterint
52083366Sjulianlinux_chdir(struct thread *td, struct linux_chdir_args *args)
52114331Speter{
52214331Speter	struct chdir_args bsd;
52314331Speter	caddr_t sg;
52414331Speter
52514331Speter	sg = stackgap_init();
52683366Sjulian	CHECKALTEXIST(td, &sg, args->path);
52714331Speter
52814331Speter#ifdef DEBUG
52972543Sjlemon	if (ldebug(chdir))
53072543Sjlemon		printf(ARGS(chdir, "%s"), args->path);
53114331Speter#endif
53214331Speter	bsd.path = args->path;
53314331Speter
53483366Sjulian	return chdir(td, &bsd);
53514331Speter}
53614331Speter
53714331Speterint
53883366Sjulianlinux_chmod(struct thread *td, struct linux_chmod_args *args)
53914331Speter{
54014331Speter	struct chmod_args bsd;
54114331Speter	caddr_t sg;
54214331Speter
54314331Speter	sg = stackgap_init();
54483366Sjulian	CHECKALTEXIST(td, &sg, args->path);
54514331Speter
54614331Speter#ifdef DEBUG
54772543Sjlemon	if (ldebug(chmod))
54872543Sjlemon		printf(ARGS(chmod, "%s, %d"), args->path, args->mode);
54914331Speter#endif
55014331Speter	bsd.path = args->path;
55114331Speter	bsd.mode = args->mode;
55214331Speter
55383366Sjulian	return chmod(td, &bsd);
55414331Speter}
55514331Speter
55614331Speterint
55783366Sjulianlinux_mkdir(struct thread *td, struct linux_mkdir_args *args)
55814331Speter{
55914331Speter	struct mkdir_args bsd;
56014331Speter	caddr_t sg;
56114331Speter
56214331Speter	sg = stackgap_init();
56383366Sjulian	CHECKALTCREAT(td, &sg, args->path);
56414331Speter
56514331Speter#ifdef DEBUG
56672543Sjlemon	if (ldebug(mkdir))
56772543Sjlemon		printf(ARGS(mkdir, "%s, %d"), args->path, args->mode);
56814331Speter#endif
56914331Speter	bsd.path = args->path;
57014331Speter	bsd.mode = args->mode;
57114331Speter
57283366Sjulian	return mkdir(td, &bsd);
57314331Speter}
57414331Speter
57514331Speterint
57683366Sjulianlinux_rmdir(struct thread *td, struct linux_rmdir_args *args)
57714331Speter{
57814331Speter	struct rmdir_args bsd;
57914331Speter	caddr_t sg;
58014331Speter
58114331Speter	sg = stackgap_init();
58283366Sjulian	CHECKALTEXIST(td, &sg, args->path);
58314331Speter
58414331Speter#ifdef DEBUG
58572543Sjlemon	if (ldebug(rmdir))
58672543Sjlemon		printf(ARGS(rmdir, "%s"), args->path);
58714331Speter#endif
58814331Speter	bsd.path = args->path;
58914331Speter
59083366Sjulian	return rmdir(td, &bsd);
59114331Speter}
59214331Speter
59314331Speterint
59483366Sjulianlinux_rename(struct thread *td, struct linux_rename_args *args)
59514331Speter{
59614331Speter	struct rename_args bsd;
59714331Speter	caddr_t sg;
59814331Speter
59914331Speter	sg = stackgap_init();
60083366Sjulian	CHECKALTEXIST(td, &sg, args->from);
60183366Sjulian	CHECKALTCREAT(td, &sg, args->to);
60214331Speter
60314331Speter#ifdef DEBUG
60472543Sjlemon	if (ldebug(rename))
60572543Sjlemon		printf(ARGS(rename, "%s, %s"), args->from, args->to);
60614331Speter#endif
60714331Speter	bsd.from = args->from;
60814331Speter	bsd.to = args->to;
60914331Speter
61083366Sjulian	return rename(td, &bsd);
61114331Speter}
61214331Speter
61314331Speterint
61483366Sjulianlinux_symlink(struct thread *td, struct linux_symlink_args *args)
61514331Speter{
61614331Speter	struct symlink_args bsd;
61714331Speter	caddr_t sg;
61814331Speter
61914331Speter	sg = stackgap_init();
62083366Sjulian	CHECKALTEXIST(td, &sg, args->path);
62183366Sjulian	CHECKALTCREAT(td, &sg, args->to);
62214331Speter
62314331Speter#ifdef DEBUG
62472543Sjlemon	if (ldebug(symlink))
62572543Sjlemon		printf(ARGS(symlink, "%s, %s"), args->path, args->to);
62614331Speter#endif
62714331Speter	bsd.path = args->path;
62814331Speter	bsd.link = args->to;
62914331Speter
63083366Sjulian	return symlink(td, &bsd);
63114331Speter}
63214331Speter
63314331Speterint
63483366Sjulianlinux_readlink(struct thread *td, struct linux_readlink_args *args)
63514331Speter{
63614331Speter	struct readlink_args bsd;
63714331Speter	caddr_t sg;
63814331Speter
63914331Speter	sg = stackgap_init();
64083366Sjulian	CHECKALTEXIST(td, &sg, args->name);
64114331Speter
64214331Speter#ifdef DEBUG
64372543Sjlemon	if (ldebug(readlink))
64472543Sjlemon		printf(ARGS(readlink, "%s, %p, %d"),
64572543Sjlemon		    args->name, (void *)args->buf, args->count);
64614331Speter#endif
64714331Speter	bsd.path = args->name;
64814331Speter	bsd.buf = args->buf;
64914331Speter	bsd.count = args->count;
65014331Speter
65183366Sjulian	return readlink(td, &bsd);
65214331Speter}
65314331Speter
65414331Speterint
65583366Sjulianlinux_truncate(struct thread *td, struct linux_truncate_args *args)
65614331Speter{
65742499Seivind	struct truncate_args bsd;
65814331Speter	caddr_t sg;
65914331Speter
66014331Speter	sg = stackgap_init();
66183366Sjulian	CHECKALTEXIST(td, &sg, args->path);
66214331Speter
66314331Speter#ifdef DEBUG
66472543Sjlemon	if (ldebug(truncate))
66583221Smarcel		printf(ARGS(truncate, "%s, %ld"), args->path,
66683221Smarcel		    (long)args->length);
66714331Speter#endif
66814331Speter	bsd.path = args->path;
66932265Sjmb	bsd.length = args->length;
67014331Speter
67183366Sjulian	return truncate(td, &bsd);
67214331Speter}
67314331Speter
67449662Smarcelint
67583366Sjulianlinux_link(struct thread *td, struct linux_link_args *args)
67649662Smarcel{
67749662Smarcel    struct link_args bsd;
67849662Smarcel    caddr_t sg;
67949662Smarcel
68049662Smarcel    sg = stackgap_init();
68183366Sjulian    CHECKALTEXIST(td, &sg, args->path);
68283366Sjulian    CHECKALTCREAT(td, &sg, args->to);
68349662Smarcel
68449662Smarcel#ifdef DEBUG
68572543Sjlemon	if (ldebug(link))
68672543Sjlemon		printf(ARGS(link, "%s, %s"), args->path, args->to);
68749662Smarcel#endif
68849662Smarcel
68949662Smarcel    bsd.path = args->path;
69049662Smarcel    bsd.link = args->to;
69149662Smarcel
69283366Sjulian    return link(td, &bsd);
69349662Smarcel}
69449788Smarcel
69568201Sobrien#ifndef __alpha__
69653713Smarcelint
69783366Sjulianlinux_fdatasync(td, uap)
69883366Sjulian	struct thread *td;
69953713Smarcel	struct linux_fdatasync_args *uap;
70053713Smarcel{
70153713Smarcel	struct fsync_args bsd;
70253713Smarcel
70353713Smarcel	bsd.fd = uap->fd;
70483366Sjulian	return fsync(td, &bsd);
70553713Smarcel}
70668201Sobrien#endif /*!__alpha__*/
70763285Smarcel
70863285Smarcelint
70983366Sjulianlinux_pread(td, uap)
71083366Sjulian	struct thread *td;
71163285Smarcel	struct linux_pread_args *uap;
71263285Smarcel{
71363285Smarcel	struct pread_args bsd;
71463285Smarcel
71563285Smarcel	bsd.fd = uap->fd;
71663285Smarcel	bsd.buf = uap->buf;
71763285Smarcel	bsd.nbyte = uap->nbyte;
71863285Smarcel	bsd.offset = uap->offset;
71983366Sjulian	return pread(td, &bsd);
72063285Smarcel}
72163285Smarcel
72263285Smarcelint
72383366Sjulianlinux_pwrite(td, uap)
72483366Sjulian	struct thread *td;
72563285Smarcel	struct linux_pwrite_args *uap;
72663285Smarcel{
72763285Smarcel	struct pwrite_args bsd;
72863285Smarcel
72963285Smarcel	bsd.fd = uap->fd;
73063285Smarcel	bsd.buf = uap->buf;
73163285Smarcel	bsd.nbyte = uap->nbyte;
73263285Smarcel	bsd.offset = uap->offset;
73383366Sjulian	return pwrite(td, &bsd);
73463285Smarcel}
73572538Sjlemon
73672538Sjlemonint
73783366Sjulianlinux_mount(struct thread *td, struct linux_mount_args *args)
73872538Sjlemon{
73972538Sjlemon	struct ufs_args ufs;
74072538Sjlemon        char fstypename[MFSNAMELEN];
74172538Sjlemon        char mntonname[MNAMELEN], mntfromname[MNAMELEN];
74273286Sadrian	int error;
74373286Sadrian	int fsflags;
74473286Sadrian	const char *fstype;
74573286Sadrian	void *fsdata;
74672538Sjlemon
74773286Sadrian        error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1,
74873286Sadrian	    NULL);
74972538Sjlemon	if (error)
75072538Sjlemon                return (error);
75172538Sjlemon        error = copyinstr(args->specialfile, mntfromname, MFSNAMELEN - 1, NULL);
75272538Sjlemon	if (error)
75372538Sjlemon                return (error);
75472538Sjlemon        error = copyinstr(args->dir, mntonname, MFSNAMELEN - 1, NULL);
75572538Sjlemon	if (error)
75672538Sjlemon                return (error);
75772538Sjlemon
75872538Sjlemon#ifdef DEBUG
75972538Sjlemon	if (ldebug(mount))
76072538Sjlemon		printf(ARGS(mount, "%s, %s, %s"),
76172538Sjlemon		    fstypename, mntfromname, mntonname);
76272538Sjlemon#endif
76372538Sjlemon
76472538Sjlemon	if (strcmp(fstypename, "ext2") == 0) {
76573286Sadrian		fstype = "ext2fs";
76673286Sadrian		fsdata = &ufs;
76772538Sjlemon		ufs.fspec = mntfromname;
76872538Sjlemon#define DEFAULT_ROOTID		-2
76972538Sjlemon		ufs.export.ex_root = DEFAULT_ROOTID;
77072538Sjlemon		ufs.export.ex_flags =
77172538Sjlemon		    args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0;
77272538Sjlemon	} else if (strcmp(fstypename, "proc") == 0) {
77373286Sadrian		fstype = "linprocfs";
77473286Sadrian		fsdata = NULL;
77572538Sjlemon	} else {
77672538Sjlemon		return (ENODEV);
77772538Sjlemon	}
77872538Sjlemon
77973286Sadrian	fsflags = 0;
78072538Sjlemon
78172538Sjlemon	if ((args->rwflag & 0xffff0000) == 0xc0ed0000) {
78272538Sjlemon		/*
78372538Sjlemon		 * Linux SYNC flag is not included; the closest equivalent
78472538Sjlemon		 * FreeBSD has is !ASYNC, which is our default.
78572538Sjlemon		 */
78672538Sjlemon		if (args->rwflag & LINUX_MS_RDONLY)
78773286Sadrian			fsflags |= MNT_RDONLY;
78872538Sjlemon		if (args->rwflag & LINUX_MS_NOSUID)
78973286Sadrian			fsflags |= MNT_NOSUID;
79072538Sjlemon		if (args->rwflag & LINUX_MS_NODEV)
79173286Sadrian			fsflags |= MNT_NODEV;
79272538Sjlemon		if (args->rwflag & LINUX_MS_NOEXEC)
79373286Sadrian			fsflags |= MNT_NOEXEC;
79472538Sjlemon		if (args->rwflag & LINUX_MS_REMOUNT)
79573286Sadrian			fsflags |= MNT_UPDATE;
79672538Sjlemon	}
79772538Sjlemon
79883366Sjulian	return (vfs_mount(td, fstype, mntonname, fsflags, fsdata));
79972538Sjlemon}
80072538Sjlemon
80172538Sjlemonint
80283366Sjulianlinux_oldumount(struct thread *td, struct linux_oldumount_args *args)
80372538Sjlemon{
80483221Smarcel	struct linux_umount_args args2;
80572538Sjlemon
80672538Sjlemon	args2.path = args->path;
80772538Sjlemon	args2.flags = 0;
80883366Sjulian	return (linux_umount(td, &args2));
80972538Sjlemon}
81072538Sjlemon
81172538Sjlemonint
81283366Sjulianlinux_umount(struct thread *td, struct linux_umount_args *args)
81372538Sjlemon{
81472538Sjlemon	struct unmount_args bsd;
81572538Sjlemon
81672538Sjlemon	bsd.path = args->path;
81772538Sjlemon	bsd.flags = args->flags;	/* XXX correct? */
81883366Sjulian	return (unmount(td, &bsd));
81972538Sjlemon}
82083221Smarcel
82183221Smarcel/*
82283221Smarcel * fcntl family of syscalls
82383221Smarcel */
82483221Smarcel
82583221Smarcelstruct l_flock {
82683221Smarcel	l_short		l_type;
82783221Smarcel	l_short		l_whence;
82883221Smarcel	l_off_t		l_start;
82983221Smarcel	l_off_t		l_len;
83083221Smarcel	l_pid_t		l_pid;
83183221Smarcel};
83283221Smarcel
83383221Smarcelstatic void
83483221Smarcellinux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock)
83583221Smarcel{
83683221Smarcel	switch (linux_flock->l_type) {
83783221Smarcel	case LINUX_F_RDLCK:
83883221Smarcel		bsd_flock->l_type = F_RDLCK;
83983221Smarcel		break;
84083221Smarcel	case LINUX_F_WRLCK:
84183221Smarcel		bsd_flock->l_type = F_WRLCK;
84283221Smarcel		break;
84383221Smarcel	case LINUX_F_UNLCK:
84483221Smarcel		bsd_flock->l_type = F_UNLCK;
84583221Smarcel		break;
84683221Smarcel	default:
84783221Smarcel		bsd_flock->l_type = -1;
84883221Smarcel		break;
84983221Smarcel	}
85083221Smarcel	bsd_flock->l_whence = linux_flock->l_whence;
85183221Smarcel	bsd_flock->l_start = (off_t)linux_flock->l_start;
85283221Smarcel	bsd_flock->l_len = (off_t)linux_flock->l_len;
85383221Smarcel	bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
85483221Smarcel}
85583221Smarcel
85683221Smarcelstatic void
85783221Smarcelbsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock)
85883221Smarcel{
85983221Smarcel	switch (bsd_flock->l_type) {
86083221Smarcel	case F_RDLCK:
86183221Smarcel		linux_flock->l_type = LINUX_F_RDLCK;
86283221Smarcel		break;
86383221Smarcel	case F_WRLCK:
86483221Smarcel		linux_flock->l_type = LINUX_F_WRLCK;
86583221Smarcel		break;
86683221Smarcel	case F_UNLCK:
86783221Smarcel		linux_flock->l_type = LINUX_F_UNLCK;
86883221Smarcel		break;
86983221Smarcel	}
87083221Smarcel	linux_flock->l_whence = bsd_flock->l_whence;
87183221Smarcel	linux_flock->l_start = (l_off_t)bsd_flock->l_start;
87283221Smarcel	linux_flock->l_len = (l_off_t)bsd_flock->l_len;
87383221Smarcel	linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
87483221Smarcel}
87583221Smarcel
87683221Smarcel#if defined(__i386__)
87783221Smarcelstruct l_flock64 {
87883221Smarcel	l_short		l_type;
87983221Smarcel	l_short		l_whence;
88083221Smarcel	l_loff_t	l_start;
88183221Smarcel	l_loff_t	l_len;
88283221Smarcel	l_pid_t		l_pid;
88383221Smarcel};
88483221Smarcel
88583221Smarcelstatic void
88683221Smarcellinux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock)
88783221Smarcel{
88883221Smarcel	switch (linux_flock->l_type) {
88983221Smarcel	case LINUX_F_RDLCK:
89083221Smarcel		bsd_flock->l_type = F_RDLCK;
89183221Smarcel		break;
89283221Smarcel	case LINUX_F_WRLCK:
89383221Smarcel		bsd_flock->l_type = F_WRLCK;
89483221Smarcel		break;
89583221Smarcel	case LINUX_F_UNLCK:
89683221Smarcel		bsd_flock->l_type = F_UNLCK;
89783221Smarcel		break;
89883221Smarcel	default:
89983221Smarcel		bsd_flock->l_type = -1;
90083221Smarcel		break;
90183221Smarcel	}
90283221Smarcel	bsd_flock->l_whence = linux_flock->l_whence;
90383221Smarcel	bsd_flock->l_start = (off_t)linux_flock->l_start;
90483221Smarcel	bsd_flock->l_len = (off_t)linux_flock->l_len;
90583221Smarcel	bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
90683221Smarcel}
90783221Smarcel
90883221Smarcelstatic void
90983221Smarcelbsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock)
91083221Smarcel{
91183221Smarcel	switch (bsd_flock->l_type) {
91283221Smarcel	case F_RDLCK:
91383221Smarcel		linux_flock->l_type = LINUX_F_RDLCK;
91483221Smarcel		break;
91583221Smarcel	case F_WRLCK:
91683221Smarcel		linux_flock->l_type = LINUX_F_WRLCK;
91783221Smarcel		break;
91883221Smarcel	case F_UNLCK:
91983221Smarcel		linux_flock->l_type = LINUX_F_UNLCK;
92083221Smarcel		break;
92183221Smarcel	}
92283221Smarcel	linux_flock->l_whence = bsd_flock->l_whence;
92383221Smarcel	linux_flock->l_start = (l_loff_t)bsd_flock->l_start;
92483221Smarcel	linux_flock->l_len = (l_loff_t)bsd_flock->l_len;
92583221Smarcel	linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
92683221Smarcel}
92783221Smarcel#endif /* __i386__ */
92883221Smarcel
92983221Smarcel#if defined(__alpha__)
93083221Smarcel#define	linux_fcntl64_args	linux_fcntl_args
93183221Smarcel#endif
93283221Smarcel
93383221Smarcelstatic int
93483366Sjulianfcntl_common(struct thread *td, struct linux_fcntl64_args *args)
93583221Smarcel{
93683221Smarcel	struct fcntl_args fcntl_args;
93783221Smarcel	struct file *fp;
93883221Smarcel	int error, result;
93983221Smarcel
94083221Smarcel	fcntl_args.fd = args->fd;
94183221Smarcel
94283221Smarcel	switch (args->cmd) {
94383221Smarcel	case LINUX_F_DUPFD:
94483221Smarcel		fcntl_args.cmd = F_DUPFD;
94583221Smarcel		fcntl_args.arg = args->arg;
94683366Sjulian		return (fcntl(td, &fcntl_args));
94783221Smarcel
94883221Smarcel	case LINUX_F_GETFD:
94983221Smarcel		fcntl_args.cmd = F_GETFD;
95083366Sjulian		return (fcntl(td, &fcntl_args));
95183221Smarcel
95283221Smarcel	case LINUX_F_SETFD:
95383221Smarcel		fcntl_args.cmd = F_SETFD;
95483221Smarcel		fcntl_args.arg = args->arg;
95583366Sjulian		return (fcntl(td, &fcntl_args));
95683221Smarcel
95783221Smarcel	case LINUX_F_GETFL:
95883221Smarcel		fcntl_args.cmd = F_GETFL;
95983366Sjulian		error = fcntl(td, &fcntl_args);
96083366Sjulian		result = td->td_retval[0];
96183366Sjulian		td->td_retval[0] = 0;
96283221Smarcel		if (result & O_RDONLY)
96383366Sjulian			td->td_retval[0] |= LINUX_O_RDONLY;
96483221Smarcel		if (result & O_WRONLY)
96583366Sjulian			td->td_retval[0] |= LINUX_O_WRONLY;
96683221Smarcel		if (result & O_RDWR)
96783366Sjulian			td->td_retval[0] |= LINUX_O_RDWR;
96883221Smarcel		if (result & O_NDELAY)
96983366Sjulian			td->td_retval[0] |= LINUX_O_NONBLOCK;
97083221Smarcel		if (result & O_APPEND)
97183366Sjulian			td->td_retval[0] |= LINUX_O_APPEND;
97283221Smarcel		if (result & O_FSYNC)
97383366Sjulian			td->td_retval[0] |= LINUX_O_SYNC;
97483221Smarcel		if (result & O_ASYNC)
97583366Sjulian			td->td_retval[0] |= LINUX_FASYNC;
97683221Smarcel		return (error);
97783221Smarcel
97883221Smarcel	case LINUX_F_SETFL:
97983221Smarcel		fcntl_args.arg = 0;
98083221Smarcel		if (args->arg & LINUX_O_NDELAY)
98183221Smarcel			fcntl_args.arg |= O_NONBLOCK;
98283221Smarcel		if (args->arg & LINUX_O_APPEND)
98383221Smarcel			fcntl_args.arg |= O_APPEND;
98483221Smarcel		if (args->arg & LINUX_O_SYNC)
98583221Smarcel			fcntl_args.arg |= O_FSYNC;
98683221Smarcel		if (args->arg & LINUX_FASYNC)
98783221Smarcel			fcntl_args.arg |= O_ASYNC;
98883221Smarcel		fcntl_args.cmd = F_SETFL;
98983366Sjulian		return (fcntl(td, &fcntl_args));
99083221Smarcel
99183221Smarcel	case LINUX_F_GETOWN:
99283221Smarcel		fcntl_args.cmd = F_GETOWN;
99383366Sjulian		return (fcntl(td, &fcntl_args));
99483221Smarcel
99583221Smarcel	case LINUX_F_SETOWN:
99683221Smarcel		/*
99783221Smarcel		 * XXX some Linux applications depend on F_SETOWN having no
99883221Smarcel		 * significant effect for pipes (SIGIO is not delivered for
99983221Smarcel		 * pipes under Linux-2.2.35 at least).
100083221Smarcel		 */
100189319Salfred		error = fget(td, args->fd, &fp);
100289319Salfred		if (error)
100389319Salfred			return (error);
100489306Salfred		if (fp->f_type == DTYPE_PIPE) {
100589306Salfred			fdrop(fp, td);
100683221Smarcel			return (EINVAL);
100789306Salfred		}
100889306Salfred		fdrop(fp, td);
100983221Smarcel
101083221Smarcel		fcntl_args.cmd = F_SETOWN;
101183221Smarcel		fcntl_args.arg = args->arg;
101283366Sjulian		return (fcntl(td, &fcntl_args));
101383221Smarcel	}
101483221Smarcel
101583221Smarcel	return (EINVAL);
101683221Smarcel}
101783221Smarcel
101883221Smarcelint
101983366Sjulianlinux_fcntl(struct thread *td, struct linux_fcntl_args *args)
102083221Smarcel{
102183221Smarcel	struct linux_fcntl64_args args64;
102283221Smarcel	struct fcntl_args fcntl_args;
102383221Smarcel	struct l_flock linux_flock;
102483221Smarcel	struct flock *bsd_flock;
102583221Smarcel	int error;
102683221Smarcel	caddr_t sg;
102783221Smarcel
102883221Smarcel	sg = stackgap_init();
102983221Smarcel	bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock));
103083221Smarcel
103183221Smarcel#ifdef DEBUG
103283221Smarcel	if (ldebug(fcntl))
103383221Smarcel		printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd);
103483221Smarcel#endif
103583221Smarcel
103683221Smarcel	switch (args->cmd) {
103783221Smarcel	case LINUX_F_GETLK:
103883221Smarcel		error = copyin((caddr_t)args->arg, &linux_flock,
103983221Smarcel		    sizeof(linux_flock));
104083221Smarcel		if (error)
104183221Smarcel			return (error);
104283221Smarcel		linux_to_bsd_flock(&linux_flock, bsd_flock);
104383221Smarcel		fcntl_args.fd = args->fd;
104483221Smarcel		fcntl_args.cmd = F_GETLK;
104583221Smarcel		fcntl_args.arg = (long)bsd_flock;
104683366Sjulian		error = fcntl(td, &fcntl_args);
104783221Smarcel		if (error)
104883221Smarcel			return (error);
104983221Smarcel		bsd_to_linux_flock(bsd_flock, &linux_flock);
105083221Smarcel		return (copyout(&linux_flock, (caddr_t)args->arg,
105183221Smarcel		    sizeof(linux_flock)));
105283221Smarcel
105383221Smarcel	case LINUX_F_SETLK:
105483221Smarcel		error = copyin((caddr_t)args->arg, &linux_flock,
105583221Smarcel		    sizeof(linux_flock));
105683221Smarcel		if (error)
105783221Smarcel			return (error);
105883221Smarcel		linux_to_bsd_flock(&linux_flock, bsd_flock);
105983221Smarcel		fcntl_args.fd = args->fd;
106083221Smarcel		fcntl_args.cmd = F_SETLK;
106183221Smarcel		fcntl_args.arg = (long)bsd_flock;
106283366Sjulian		return (fcntl(td, &fcntl_args));
106383221Smarcel
106483221Smarcel	case LINUX_F_SETLKW:
106583221Smarcel		error = copyin((caddr_t)args->arg, &linux_flock,
106683221Smarcel		    sizeof(linux_flock));
106783221Smarcel		if (error)
106883221Smarcel			return (error);
106983221Smarcel		linux_to_bsd_flock(&linux_flock, bsd_flock);
107083221Smarcel		fcntl_args.fd = args->fd;
107183221Smarcel		fcntl_args.cmd = F_SETLKW;
107283221Smarcel		fcntl_args.arg = (long)bsd_flock;
107383366Sjulian		return (fcntl(td, &fcntl_args));
107483221Smarcel	}
107583221Smarcel
107683221Smarcel	args64.fd = args->fd;
107783221Smarcel	args64.cmd = args->cmd;
107883221Smarcel	args64.arg = args->arg;
107983366Sjulian	return (fcntl_common(td, &args64));
108083221Smarcel}
108183221Smarcel
108283221Smarcel#if defined(__i386__)
108383221Smarcelint
108483366Sjulianlinux_fcntl64(struct thread *td, struct linux_fcntl64_args *args)
108583221Smarcel{
108683221Smarcel	struct fcntl_args fcntl_args;
108783221Smarcel	struct l_flock64 linux_flock;
108883221Smarcel	struct flock *bsd_flock;
108983221Smarcel	int error;
109083221Smarcel	caddr_t sg;
109183221Smarcel
109283221Smarcel	sg = stackgap_init();
109383221Smarcel	bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock));
109483221Smarcel
109583221Smarcel#ifdef DEBUG
109683221Smarcel	if (ldebug(fcntl64))
109783221Smarcel		printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd);
109883221Smarcel#endif
109983221Smarcel
110083221Smarcel	switch (args->cmd) {
110183221Smarcel	case LINUX_F_GETLK:
110283221Smarcel		error = copyin((caddr_t)args->arg, &linux_flock,
110383221Smarcel		    sizeof(linux_flock));
110483221Smarcel		if (error)
110583221Smarcel			return (error);
110683221Smarcel		linux_to_bsd_flock64(&linux_flock, bsd_flock);
110783221Smarcel		fcntl_args.fd = args->fd;
110883221Smarcel		fcntl_args.cmd = F_GETLK;
110983221Smarcel		fcntl_args.arg = (long)bsd_flock;
111083366Sjulian		error = fcntl(td, &fcntl_args);
111183221Smarcel		if (error)
111283221Smarcel			return (error);
111383221Smarcel		bsd_to_linux_flock64(bsd_flock, &linux_flock);
111483221Smarcel		return (copyout(&linux_flock, (caddr_t)args->arg,
111583221Smarcel		    sizeof(linux_flock)));
111683221Smarcel
111783221Smarcel	case LINUX_F_SETLK:
111883221Smarcel		error = copyin((caddr_t)args->arg, &linux_flock,
111983221Smarcel		    sizeof(linux_flock));
112083221Smarcel		if (error)
112183221Smarcel			return (error);
112283221Smarcel		linux_to_bsd_flock64(&linux_flock, bsd_flock);
112383221Smarcel		fcntl_args.fd = args->fd;
112483221Smarcel		fcntl_args.cmd = F_SETLK;
112583221Smarcel		fcntl_args.arg = (long)bsd_flock;
112683366Sjulian		return (fcntl(td, &fcntl_args));
112783221Smarcel
112883221Smarcel	case LINUX_F_SETLKW:
112983221Smarcel		error = copyin((caddr_t)args->arg, &linux_flock,
113083221Smarcel		    sizeof(linux_flock));
113183221Smarcel		if (error)
113283221Smarcel			return (error);
113383221Smarcel		linux_to_bsd_flock64(&linux_flock, bsd_flock);
113483221Smarcel		fcntl_args.fd = args->fd;
113583221Smarcel		fcntl_args.cmd = F_SETLKW;
113683221Smarcel		fcntl_args.arg = (long)bsd_flock;
113783366Sjulian		return (fcntl(td, &fcntl_args));
113883221Smarcel	}
113983221Smarcel
114083366Sjulian	return (fcntl_common(td, args));
114183221Smarcel}
114283221Smarcel#endif /* __i386__ */
114385022Smarcel
114485022Smarcelint
114585022Smarcellinux_chown(struct thread *td, struct linux_chown_args *args)
114685022Smarcel{
114785022Smarcel	struct chown_args bsd;
114885022Smarcel	caddr_t sg;
114985022Smarcel
115085022Smarcel	sg = stackgap_init();
115185022Smarcel	CHECKALTEXIST(td, &sg, args->path);
115285022Smarcel
115385022Smarcel#ifdef DEBUG
115485022Smarcel	if (ldebug(chown))
115585022Smarcel		printf(ARGS(chown, "%s, %d, %d"), args->path, args->uid,
115685022Smarcel		    args->gid);
115785022Smarcel#endif
115885022Smarcel
115985022Smarcel	bsd.path = args->path;
116085022Smarcel	bsd.uid = args->uid;
116185022Smarcel	bsd.gid = args->gid;
116285022Smarcel	return (chown(td, &bsd));
116385022Smarcel}
116485022Smarcel
116585022Smarcelint
116685022Smarcellinux_lchown(struct thread *td, struct linux_lchown_args *args)
116785022Smarcel{
116885022Smarcel	struct lchown_args bsd;
116985022Smarcel	caddr_t sg;
117085022Smarcel
117185022Smarcel	sg = stackgap_init();
117285022Smarcel	CHECKALTEXIST(td, &sg, args->path);
117385022Smarcel
117485022Smarcel#ifdef DEBUG
117585022Smarcel	if (ldebug(lchown))
117685022Smarcel		printf(ARGS(lchown, "%s, %d, %d"), args->path, args->uid,
117785022Smarcel		    args->gid);
117885022Smarcel#endif
117985022Smarcel
118085022Smarcel	bsd.path = args->path;
118185022Smarcel	bsd.uid = args->uid;
118285022Smarcel	bsd.gid = args->gid;
118385022Smarcel	return (lchown(td, &bsd));
118485022Smarcel}
1185