linux_file.c revision 85022
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 85022 2001-10-16 06:15:36Z marcel $
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)) {
1389313Ssos	struct filedesc *fdp = p->p_fd;
13983366Sjulian	struct file *fp = fdp->fd_ofiles[td->td_retval[0]];
1409313Ssos
14170061Sjhb	PROC_UNLOCK(p);
1429313Ssos	if (fp->f_type == DTYPE_VNODE)
14383366Sjulian	    fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td);
14470061Sjhb    } else
14570061Sjhb	PROC_UNLOCK(p);
14614331Speter#ifdef DEBUG
14772543Sjlemon	if (ldebug(open))
14872543Sjlemon		printf(LMSG("open returns error %d"), error);
14914331Speter#endif
1509313Ssos    return error;
1519313Ssos}
1529313Ssos
1539313Ssosint
15483366Sjulianlinux_lseek(struct thread *td, struct linux_lseek_args *args)
1559313Ssos{
1569313Ssos
15712858Speter    struct lseek_args /* {
15812858Speter	int fd;
1599313Ssos	int pad;
16012858Speter	off_t offset;
1619313Ssos	int whence;
16212858Speter    } */ tmp_args;
1639313Ssos    int error;
1649313Ssos
1659313Ssos#ifdef DEBUG
16672543Sjlemon	if (ldebug(lseek))
16772543Sjlemon		printf(ARGS(lseek, "%d, %ld, %d"),
16883221Smarcel		    args->fdes, (long)args->off, args->whence);
1699313Ssos#endif
17012858Speter    tmp_args.fd = args->fdes;
17112858Speter    tmp_args.offset = (off_t)args->off;
1729313Ssos    tmp_args.whence = args->whence;
17383366Sjulian    error = lseek(td, &tmp_args);
1749313Ssos    return error;
1759313Ssos}
1769313Ssos
17768201Sobrien#ifndef __alpha__
17814331Speterint
17983366Sjulianlinux_llseek(struct thread *td, struct linux_llseek_args *args)
18014331Speter{
18114331Speter	struct lseek_args bsd_args;
18214331Speter	int error;
18314331Speter	off_t off;
18414331Speter
18514331Speter#ifdef DEBUG
18672543Sjlemon	if (ldebug(llseek))
18772543Sjlemon		printf(ARGS(llseek, "%d, %d:%d, %d"),
18872543Sjlemon		    args->fd, args->ohigh, args->olow, args->whence);
18914331Speter#endif
19014331Speter	off = (args->olow) | (((off_t) args->ohigh) << 32);
19114331Speter
19214331Speter	bsd_args.fd = args->fd;
19314331Speter	bsd_args.offset = off;
19414331Speter	bsd_args.whence = args->whence;
19514331Speter
19683366Sjulian	if ((error = lseek(td, &bsd_args)))
19714331Speter		return error;
19814331Speter
19983366Sjulian	if ((error = copyout(td->td_retval, (caddr_t)args->res, sizeof (off_t))))
20014331Speter		return error;
20114331Speter
20283366Sjulian	td->td_retval[0] = 0;
20314331Speter	return 0;
20414331Speter}
20568201Sobrien#endif /*!__alpha__*/
20614331Speter
20768201Sobrien#ifndef __alpha__
2089313Ssosint
20983366Sjulianlinux_readdir(struct thread *td, struct linux_readdir_args *args)
2109313Ssos{
21114331Speter	struct linux_getdents_args lda;
21214331Speter
21314331Speter	lda.fd = args->fd;
21414331Speter	lda.dent = args->dent;
21514331Speter	lda.count = 1;
21683366Sjulian	return linux_getdents(td, &lda);
21714331Speter}
21868201Sobrien#endif /*!__alpha__*/
21914331Speter
22083221Smarcel/*
22183221Smarcel * Note that linux_getdents(2) and linux_getdents64(2) have the same
22283221Smarcel * arguments. They only differ in the definition of struct dirent they
22383221Smarcel * operate on. We use this to common the code, with the exception of
22483221Smarcel * accessing struct dirent. Note that linux_readdir(2) is implemented
22583221Smarcel * by means of linux_getdents(2). In this case we never operate on
22683221Smarcel * struct dirent64 and thus don't need to handle it...
22783221Smarcel */
22883221Smarcel
22983221Smarcelstruct l_dirent {
23083221Smarcel	l_long		d_ino;
23183221Smarcel	l_off_t		d_off;
23283221Smarcel	l_ushort	d_reclen;
23383221Smarcel	char		d_name[LINUX_NAME_MAX + 1];
23483221Smarcel};
23583221Smarcel
23683221Smarcelstruct l_dirent64 {
23783221Smarcel	uint64_t	d_ino;
23883221Smarcel	int64_t		d_off;
23983221Smarcel	l_ushort	d_reclen;
24083221Smarcel	u_char		d_type;
24183221Smarcel	char		d_name[LINUX_NAME_MAX + 1];
24283221Smarcel};
24383221Smarcel
24483221Smarcel#define LINUX_RECLEN(de,namlen) \
24583221Smarcel    ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1))
24683221Smarcel
24783221Smarcel#define	LINUX_DIRBLKSIZ		512
24883221Smarcel
24983221Smarcelstatic int
25083366Sjuliangetdents_common(struct thread *td, struct linux_getdents64_args *args,
25183221Smarcel    int is64bit)
25214331Speter{
25383221Smarcel	register struct dirent *bdp;
25483221Smarcel	struct vnode *vp;
25583221Smarcel	caddr_t inp, buf;		/* BSD-format */
25683221Smarcel	int len, reclen;		/* BSD-format */
25783221Smarcel	caddr_t outp;			/* Linux-format */
25883221Smarcel	int resid, linuxreclen=0;	/* Linux-format */
25983221Smarcel	struct file *fp;
26083221Smarcel	struct uio auio;
26183221Smarcel	struct iovec aiov;
26283221Smarcel	struct vattr va;
26383221Smarcel	off_t off;
26483221Smarcel	struct l_dirent linux_dirent;
26583221Smarcel	struct l_dirent64 linux_dirent64;
26683221Smarcel	int buflen, error, eofflag, nbytes, justone;
26783221Smarcel	u_long *cookies = NULL, *cookiep;
26883221Smarcel	int ncookies;
2699313Ssos
27083366Sjulian	if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0)
27183221Smarcel		return (error);
2729313Ssos
27383221Smarcel	if ((fp->f_flag & FREAD) == 0)
27483221Smarcel		return (EBADF);
2759313Ssos
27683221Smarcel	vp = (struct vnode *) fp->f_data;
27783221Smarcel	if (vp->v_type != VDIR)
27883221Smarcel		return (EINVAL);
2799313Ssos
28083366Sjulian	if ((error = VOP_GETATTR(vp, &va, td->td_proc->p_ucred, td)))
28183221Smarcel		return (error);
2829313Ssos
28383221Smarcel	nbytes = args->count;
28483221Smarcel	if (nbytes == 1) {
28583221Smarcel		/* readdir(2) case. Always struct dirent. */
28683221Smarcel		if (is64bit)
28783221Smarcel			return (EINVAL);
28883221Smarcel		nbytes = sizeof(linux_dirent);
28983221Smarcel		justone = 1;
29083221Smarcel	} else
29183221Smarcel		justone = 0;
2929313Ssos
29383221Smarcel	off = fp->f_offset;
2949313Ssos
29583221Smarcel	buflen = max(LINUX_DIRBLKSIZ, nbytes);
29683221Smarcel	buflen = min(buflen, MAXBSIZE);
29783221Smarcel	buf = malloc(buflen, M_TEMP, M_WAITOK);
29883366Sjulian	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
29983221Smarcel
3009313Ssosagain:
30183221Smarcel	aiov.iov_base = buf;
30283221Smarcel	aiov.iov_len = buflen;
30383221Smarcel	auio.uio_iov = &aiov;
30483221Smarcel	auio.uio_iovcnt = 1;
30583221Smarcel	auio.uio_rw = UIO_READ;
30683221Smarcel	auio.uio_segflg = UIO_SYSSPACE;
30783366Sjulian	auio.uio_td = td;
30883221Smarcel	auio.uio_resid = buflen;
30983221Smarcel	auio.uio_offset = off;
3109313Ssos
31183221Smarcel	if (cookies) {
31283221Smarcel		free(cookies, M_TEMP);
31383221Smarcel		cookies = NULL;
31483221Smarcel	}
31524654Sdfr
31683221Smarcel	if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
31783221Smarcel		 &cookies)))
31883221Smarcel		goto out;
3199313Ssos
32083221Smarcel	inp = buf;
32183221Smarcel	outp = (caddr_t)args->dirent;
32283221Smarcel	resid = nbytes;
32383221Smarcel	if ((len = buflen - auio.uio_resid) <= 0)
32483221Smarcel		goto eof;
3259313Ssos
32683221Smarcel	cookiep = cookies;
32724654Sdfr
32883221Smarcel	if (cookies) {
32983221Smarcel		/*
33083221Smarcel		 * When using cookies, the vfs has the option of reading from
33183221Smarcel		 * a different offset than that supplied (UFS truncates the
33283221Smarcel		 * offset to a block boundary to make sure that it never reads
33383221Smarcel		 * partway through a directory entry, even if the directory
33483221Smarcel		 * has been compacted).
33583221Smarcel		 */
33683221Smarcel		while (len > 0 && ncookies > 0 && *cookiep <= off) {
33783221Smarcel			bdp = (struct dirent *) inp;
33883221Smarcel			len -= bdp->d_reclen;
33983221Smarcel			inp += bdp->d_reclen;
34083221Smarcel			cookiep++;
34183221Smarcel			ncookies--;
34283221Smarcel		}
34324654Sdfr	}
34424654Sdfr
34583221Smarcel	while (len > 0) {
34683221Smarcel		if (cookiep && ncookies == 0)
34783221Smarcel			break;
34883221Smarcel		bdp = (struct dirent *) inp;
34983221Smarcel		reclen = bdp->d_reclen;
35083221Smarcel		if (reclen & 3) {
35183221Smarcel			error = EFAULT;
35283221Smarcel			goto out;
35383221Smarcel		}
35483221Smarcel
35583221Smarcel		if (bdp->d_fileno == 0) {
35683221Smarcel			inp += reclen;
35783221Smarcel			if (cookiep) {
35883221Smarcel				off = *cookiep++;
35983221Smarcel				ncookies--;
36083221Smarcel			} else
36183221Smarcel				off += reclen;
36283221Smarcel
36383221Smarcel			len -= reclen;
36483221Smarcel			continue;
36583221Smarcel		}
36683221Smarcel
36783221Smarcel		linuxreclen = (is64bit)
36883221Smarcel		    ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen)
36983221Smarcel		    : LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
37083221Smarcel
37183221Smarcel		if (reclen > len || resid < linuxreclen) {
37283221Smarcel			outp++;
37383221Smarcel			break;
37483221Smarcel		}
37583221Smarcel
37683221Smarcel		if (justone) {
37783221Smarcel			/* readdir(2) case. */
37883221Smarcel			linux_dirent.d_ino = (l_long)bdp->d_fileno;
37983221Smarcel			linux_dirent.d_off = (l_off_t)linuxreclen;
38083221Smarcel			linux_dirent.d_reclen = (l_ushort)bdp->d_namlen;
38183221Smarcel			strcpy(linux_dirent.d_name, bdp->d_name);
38283221Smarcel			error = copyout(&linux_dirent, outp, linuxreclen);
38383221Smarcel		} else {
38483221Smarcel			if (is64bit) {
38583221Smarcel				linux_dirent64.d_ino = bdp->d_fileno;
38683221Smarcel				linux_dirent64.d_off = (cookiep)
38783221Smarcel				    ? (l_off_t)*cookiep
38883221Smarcel				    : (l_off_t)(off + reclen);
38983221Smarcel				linux_dirent64.d_reclen =
39083221Smarcel				    (l_ushort)linuxreclen;
39183221Smarcel				linux_dirent64.d_type = bdp->d_type;
39283221Smarcel				strcpy(linux_dirent64.d_name, bdp->d_name);
39383221Smarcel				error = copyout(&linux_dirent64, outp,
39483221Smarcel				    linuxreclen);
39583221Smarcel			} else {
39683221Smarcel				linux_dirent.d_ino = bdp->d_fileno;
39783221Smarcel				linux_dirent.d_off = (cookiep)
39883221Smarcel				    ? (l_off_t)*cookiep
39983221Smarcel				    : (l_off_t)(off + reclen);
40083221Smarcel				linux_dirent.d_reclen = (l_ushort)linuxreclen;
40183221Smarcel				strcpy(linux_dirent.d_name, bdp->d_name);
40283221Smarcel				error = copyout(&linux_dirent, outp,
40383221Smarcel				    linuxreclen);
40483221Smarcel			}
40583221Smarcel		}
40683221Smarcel		if (error)
40783221Smarcel			goto out;
40883221Smarcel
40983221Smarcel		inp += reclen;
41083221Smarcel		if (cookiep) {
41183221Smarcel			off = *cookiep++;
41283221Smarcel			ncookies--;
41383221Smarcel		} else
41483221Smarcel			off += reclen;
41583221Smarcel
41683221Smarcel		outp += linuxreclen;
41783221Smarcel		resid -= linuxreclen;
41883221Smarcel		len -= reclen;
41983221Smarcel		if (justone)
42083221Smarcel			break;
42110355Sswallace	}
4229313Ssos
42383221Smarcel	if (outp == (caddr_t)args->dirent)
42483221Smarcel		goto again;
4259313Ssos
42683221Smarcel	fp->f_offset = off;
42783221Smarcel	if (justone)
42883221Smarcel		nbytes = resid + linuxreclen;
42910355Sswallace
4309313Ssoseof:
43183366Sjulian	td->td_retval[0] = nbytes - resid;
43283221Smarcel
4339313Ssosout:
43483221Smarcel	if (cookies)
43583221Smarcel		free(cookies, M_TEMP);
43683221Smarcel
43783366Sjulian	VOP_UNLOCK(vp, 0, td);
43883221Smarcel	free(buf, M_TEMP);
43983221Smarcel	return (error);
4409313Ssos}
44114331Speter
44283221Smarcelint
44383366Sjulianlinux_getdents(struct thread *td, struct linux_getdents_args *args)
44483221Smarcel{
44583221Smarcel
44683221Smarcel#ifdef DEBUG
44783221Smarcel	if (ldebug(getdents))
44883221Smarcel		printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count);
44983221Smarcel#endif
45083221Smarcel
45183366Sjulian	return (getdents_common(td, (struct linux_getdents64_args*)args, 0));
45283221Smarcel}
45383221Smarcel
45483221Smarcelint
45583366Sjulianlinux_getdents64(struct thread *td, struct linux_getdents64_args *args)
45683221Smarcel{
45783221Smarcel
45883221Smarcel#ifdef DEBUG
45983221Smarcel	if (ldebug(getdents64))
46083221Smarcel		printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count);
46183221Smarcel#endif
46283221Smarcel
46383366Sjulian	return (getdents_common(td, args, 1));
46483221Smarcel}
46583221Smarcel
46614331Speter/*
46714331Speter * These exist mainly for hooks for doing /compat/linux translation.
46814331Speter */
46914331Speter
47014331Speterint
47183366Sjulianlinux_access(struct thread *td, struct linux_access_args *args)
47214331Speter{
47314331Speter	struct access_args bsd;
47414331Speter	caddr_t sg;
47514331Speter
47614331Speter	sg = stackgap_init();
47783366Sjulian	CHECKALTEXIST(td, &sg, args->path);
47814331Speter
47914331Speter#ifdef DEBUG
48072543Sjlemon	if (ldebug(access))
48172543Sjlemon		printf(ARGS(access, "%s, %d"), args->path, args->flags);
48214331Speter#endif
48314331Speter	bsd.path = args->path;
48414331Speter	bsd.flags = args->flags;
48514331Speter
48683366Sjulian	return access(td, &bsd);
48714331Speter}
48814331Speter
48914331Speterint
49083366Sjulianlinux_unlink(struct thread *td, struct linux_unlink_args *args)
49114331Speter{
49214331Speter	struct unlink_args bsd;
49314331Speter	caddr_t sg;
49414331Speter
49514331Speter	sg = stackgap_init();
49683366Sjulian	CHECKALTEXIST(td, &sg, args->path);
49714331Speter
49814331Speter#ifdef DEBUG
49972543Sjlemon	if (ldebug(unlink))
50072543Sjlemon		printf(ARGS(unlink, "%s"), args->path);
50114331Speter#endif
50214331Speter	bsd.path = args->path;
50314331Speter
50483366Sjulian	return unlink(td, &bsd);
50514331Speter}
50614331Speter
50714331Speterint
50883366Sjulianlinux_chdir(struct thread *td, struct linux_chdir_args *args)
50914331Speter{
51014331Speter	struct chdir_args bsd;
51114331Speter	caddr_t sg;
51214331Speter
51314331Speter	sg = stackgap_init();
51483366Sjulian	CHECKALTEXIST(td, &sg, args->path);
51514331Speter
51614331Speter#ifdef DEBUG
51772543Sjlemon	if (ldebug(chdir))
51872543Sjlemon		printf(ARGS(chdir, "%s"), args->path);
51914331Speter#endif
52014331Speter	bsd.path = args->path;
52114331Speter
52283366Sjulian	return chdir(td, &bsd);
52314331Speter}
52414331Speter
52514331Speterint
52683366Sjulianlinux_chmod(struct thread *td, struct linux_chmod_args *args)
52714331Speter{
52814331Speter	struct chmod_args bsd;
52914331Speter	caddr_t sg;
53014331Speter
53114331Speter	sg = stackgap_init();
53283366Sjulian	CHECKALTEXIST(td, &sg, args->path);
53314331Speter
53414331Speter#ifdef DEBUG
53572543Sjlemon	if (ldebug(chmod))
53672543Sjlemon		printf(ARGS(chmod, "%s, %d"), args->path, args->mode);
53714331Speter#endif
53814331Speter	bsd.path = args->path;
53914331Speter	bsd.mode = args->mode;
54014331Speter
54183366Sjulian	return chmod(td, &bsd);
54214331Speter}
54314331Speter
54414331Speterint
54583366Sjulianlinux_mkdir(struct thread *td, struct linux_mkdir_args *args)
54614331Speter{
54714331Speter	struct mkdir_args bsd;
54814331Speter	caddr_t sg;
54914331Speter
55014331Speter	sg = stackgap_init();
55183366Sjulian	CHECKALTCREAT(td, &sg, args->path);
55214331Speter
55314331Speter#ifdef DEBUG
55472543Sjlemon	if (ldebug(mkdir))
55572543Sjlemon		printf(ARGS(mkdir, "%s, %d"), args->path, args->mode);
55614331Speter#endif
55714331Speter	bsd.path = args->path;
55814331Speter	bsd.mode = args->mode;
55914331Speter
56083366Sjulian	return mkdir(td, &bsd);
56114331Speter}
56214331Speter
56314331Speterint
56483366Sjulianlinux_rmdir(struct thread *td, struct linux_rmdir_args *args)
56514331Speter{
56614331Speter	struct rmdir_args bsd;
56714331Speter	caddr_t sg;
56814331Speter
56914331Speter	sg = stackgap_init();
57083366Sjulian	CHECKALTEXIST(td, &sg, args->path);
57114331Speter
57214331Speter#ifdef DEBUG
57372543Sjlemon	if (ldebug(rmdir))
57472543Sjlemon		printf(ARGS(rmdir, "%s"), args->path);
57514331Speter#endif
57614331Speter	bsd.path = args->path;
57714331Speter
57883366Sjulian	return rmdir(td, &bsd);
57914331Speter}
58014331Speter
58114331Speterint
58283366Sjulianlinux_rename(struct thread *td, struct linux_rename_args *args)
58314331Speter{
58414331Speter	struct rename_args bsd;
58514331Speter	caddr_t sg;
58614331Speter
58714331Speter	sg = stackgap_init();
58883366Sjulian	CHECKALTEXIST(td, &sg, args->from);
58983366Sjulian	CHECKALTCREAT(td, &sg, args->to);
59014331Speter
59114331Speter#ifdef DEBUG
59272543Sjlemon	if (ldebug(rename))
59372543Sjlemon		printf(ARGS(rename, "%s, %s"), args->from, args->to);
59414331Speter#endif
59514331Speter	bsd.from = args->from;
59614331Speter	bsd.to = args->to;
59714331Speter
59883366Sjulian	return rename(td, &bsd);
59914331Speter}
60014331Speter
60114331Speterint
60283366Sjulianlinux_symlink(struct thread *td, struct linux_symlink_args *args)
60314331Speter{
60414331Speter	struct symlink_args bsd;
60514331Speter	caddr_t sg;
60614331Speter
60714331Speter	sg = stackgap_init();
60883366Sjulian	CHECKALTEXIST(td, &sg, args->path);
60983366Sjulian	CHECKALTCREAT(td, &sg, args->to);
61014331Speter
61114331Speter#ifdef DEBUG
61272543Sjlemon	if (ldebug(symlink))
61372543Sjlemon		printf(ARGS(symlink, "%s, %s"), args->path, args->to);
61414331Speter#endif
61514331Speter	bsd.path = args->path;
61614331Speter	bsd.link = args->to;
61714331Speter
61883366Sjulian	return symlink(td, &bsd);
61914331Speter}
62014331Speter
62114331Speterint
62283366Sjulianlinux_readlink(struct thread *td, struct linux_readlink_args *args)
62314331Speter{
62414331Speter	struct readlink_args bsd;
62514331Speter	caddr_t sg;
62614331Speter
62714331Speter	sg = stackgap_init();
62883366Sjulian	CHECKALTEXIST(td, &sg, args->name);
62914331Speter
63014331Speter#ifdef DEBUG
63172543Sjlemon	if (ldebug(readlink))
63272543Sjlemon		printf(ARGS(readlink, "%s, %p, %d"),
63372543Sjlemon		    args->name, (void *)args->buf, args->count);
63414331Speter#endif
63514331Speter	bsd.path = args->name;
63614331Speter	bsd.buf = args->buf;
63714331Speter	bsd.count = args->count;
63814331Speter
63983366Sjulian	return readlink(td, &bsd);
64014331Speter}
64114331Speter
64214331Speterint
64383366Sjulianlinux_truncate(struct thread *td, struct linux_truncate_args *args)
64414331Speter{
64542499Seivind	struct truncate_args bsd;
64614331Speter	caddr_t sg;
64714331Speter
64814331Speter	sg = stackgap_init();
64983366Sjulian	CHECKALTEXIST(td, &sg, args->path);
65014331Speter
65114331Speter#ifdef DEBUG
65272543Sjlemon	if (ldebug(truncate))
65383221Smarcel		printf(ARGS(truncate, "%s, %ld"), args->path,
65483221Smarcel		    (long)args->length);
65514331Speter#endif
65614331Speter	bsd.path = args->path;
65732265Sjmb	bsd.length = args->length;
65814331Speter
65983366Sjulian	return truncate(td, &bsd);
66014331Speter}
66114331Speter
66249662Smarcelint
66383366Sjulianlinux_link(struct thread *td, struct linux_link_args *args)
66449662Smarcel{
66549662Smarcel    struct link_args bsd;
66649662Smarcel    caddr_t sg;
66749662Smarcel
66849662Smarcel    sg = stackgap_init();
66983366Sjulian    CHECKALTEXIST(td, &sg, args->path);
67083366Sjulian    CHECKALTCREAT(td, &sg, args->to);
67149662Smarcel
67249662Smarcel#ifdef DEBUG
67372543Sjlemon	if (ldebug(link))
67472543Sjlemon		printf(ARGS(link, "%s, %s"), args->path, args->to);
67549662Smarcel#endif
67649662Smarcel
67749662Smarcel    bsd.path = args->path;
67849662Smarcel    bsd.link = args->to;
67949662Smarcel
68083366Sjulian    return link(td, &bsd);
68149662Smarcel}
68249788Smarcel
68368201Sobrien#ifndef __alpha__
68453713Smarcelint
68583366Sjulianlinux_fdatasync(td, uap)
68683366Sjulian	struct thread *td;
68753713Smarcel	struct linux_fdatasync_args *uap;
68853713Smarcel{
68953713Smarcel	struct fsync_args bsd;
69053713Smarcel
69153713Smarcel	bsd.fd = uap->fd;
69283366Sjulian	return fsync(td, &bsd);
69353713Smarcel}
69468201Sobrien#endif /*!__alpha__*/
69563285Smarcel
69663285Smarcelint
69783366Sjulianlinux_pread(td, uap)
69883366Sjulian	struct thread *td;
69963285Smarcel	struct linux_pread_args *uap;
70063285Smarcel{
70163285Smarcel	struct pread_args bsd;
70263285Smarcel
70363285Smarcel	bsd.fd = uap->fd;
70463285Smarcel	bsd.buf = uap->buf;
70563285Smarcel	bsd.nbyte = uap->nbyte;
70663285Smarcel	bsd.offset = uap->offset;
70783366Sjulian	return pread(td, &bsd);
70863285Smarcel}
70963285Smarcel
71063285Smarcelint
71183366Sjulianlinux_pwrite(td, uap)
71283366Sjulian	struct thread *td;
71363285Smarcel	struct linux_pwrite_args *uap;
71463285Smarcel{
71563285Smarcel	struct pwrite_args bsd;
71663285Smarcel
71763285Smarcel	bsd.fd = uap->fd;
71863285Smarcel	bsd.buf = uap->buf;
71963285Smarcel	bsd.nbyte = uap->nbyte;
72063285Smarcel	bsd.offset = uap->offset;
72183366Sjulian	return pwrite(td, &bsd);
72263285Smarcel}
72372538Sjlemon
72472538Sjlemonint
72583366Sjulianlinux_mount(struct thread *td, struct linux_mount_args *args)
72672538Sjlemon{
72772538Sjlemon	struct ufs_args ufs;
72872538Sjlemon        char fstypename[MFSNAMELEN];
72972538Sjlemon        char mntonname[MNAMELEN], mntfromname[MNAMELEN];
73073286Sadrian	int error;
73173286Sadrian	int fsflags;
73273286Sadrian	const char *fstype;
73373286Sadrian	void *fsdata;
73472538Sjlemon
73573286Sadrian        error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1,
73673286Sadrian	    NULL);
73772538Sjlemon	if (error)
73872538Sjlemon                return (error);
73972538Sjlemon        error = copyinstr(args->specialfile, mntfromname, MFSNAMELEN - 1, NULL);
74072538Sjlemon	if (error)
74172538Sjlemon                return (error);
74272538Sjlemon        error = copyinstr(args->dir, mntonname, MFSNAMELEN - 1, NULL);
74372538Sjlemon	if (error)
74472538Sjlemon                return (error);
74572538Sjlemon
74672538Sjlemon#ifdef DEBUG
74772538Sjlemon	if (ldebug(mount))
74872538Sjlemon		printf(ARGS(mount, "%s, %s, %s"),
74972538Sjlemon		    fstypename, mntfromname, mntonname);
75072538Sjlemon#endif
75172538Sjlemon
75272538Sjlemon	if (strcmp(fstypename, "ext2") == 0) {
75373286Sadrian		fstype = "ext2fs";
75473286Sadrian		fsdata = &ufs;
75572538Sjlemon		ufs.fspec = mntfromname;
75672538Sjlemon#define DEFAULT_ROOTID		-2
75772538Sjlemon		ufs.export.ex_root = DEFAULT_ROOTID;
75872538Sjlemon		ufs.export.ex_flags =
75972538Sjlemon		    args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0;
76072538Sjlemon	} else if (strcmp(fstypename, "proc") == 0) {
76173286Sadrian		fstype = "linprocfs";
76273286Sadrian		fsdata = NULL;
76372538Sjlemon	} else {
76472538Sjlemon		return (ENODEV);
76572538Sjlemon	}
76672538Sjlemon
76773286Sadrian	fsflags = 0;
76872538Sjlemon
76972538Sjlemon	if ((args->rwflag & 0xffff0000) == 0xc0ed0000) {
77072538Sjlemon		/*
77172538Sjlemon		 * Linux SYNC flag is not included; the closest equivalent
77272538Sjlemon		 * FreeBSD has is !ASYNC, which is our default.
77372538Sjlemon		 */
77472538Sjlemon		if (args->rwflag & LINUX_MS_RDONLY)
77573286Sadrian			fsflags |= MNT_RDONLY;
77672538Sjlemon		if (args->rwflag & LINUX_MS_NOSUID)
77773286Sadrian			fsflags |= MNT_NOSUID;
77872538Sjlemon		if (args->rwflag & LINUX_MS_NODEV)
77973286Sadrian			fsflags |= MNT_NODEV;
78072538Sjlemon		if (args->rwflag & LINUX_MS_NOEXEC)
78173286Sadrian			fsflags |= MNT_NOEXEC;
78272538Sjlemon		if (args->rwflag & LINUX_MS_REMOUNT)
78373286Sadrian			fsflags |= MNT_UPDATE;
78472538Sjlemon	}
78572538Sjlemon
78683366Sjulian	return (vfs_mount(td, fstype, mntonname, fsflags, fsdata));
78772538Sjlemon}
78872538Sjlemon
78972538Sjlemonint
79083366Sjulianlinux_oldumount(struct thread *td, struct linux_oldumount_args *args)
79172538Sjlemon{
79283221Smarcel	struct linux_umount_args args2;
79372538Sjlemon
79472538Sjlemon	args2.path = args->path;
79572538Sjlemon	args2.flags = 0;
79683366Sjulian	return (linux_umount(td, &args2));
79772538Sjlemon}
79872538Sjlemon
79972538Sjlemonint
80083366Sjulianlinux_umount(struct thread *td, struct linux_umount_args *args)
80172538Sjlemon{
80272538Sjlemon	struct unmount_args bsd;
80372538Sjlemon
80472538Sjlemon	bsd.path = args->path;
80572538Sjlemon	bsd.flags = args->flags;	/* XXX correct? */
80683366Sjulian	return (unmount(td, &bsd));
80772538Sjlemon}
80883221Smarcel
80983221Smarcel/*
81083221Smarcel * fcntl family of syscalls
81183221Smarcel */
81283221Smarcel
81383221Smarcelstruct l_flock {
81483221Smarcel	l_short		l_type;
81583221Smarcel	l_short		l_whence;
81683221Smarcel	l_off_t		l_start;
81783221Smarcel	l_off_t		l_len;
81883221Smarcel	l_pid_t		l_pid;
81983221Smarcel};
82083221Smarcel
82183221Smarcelstatic void
82283221Smarcellinux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock)
82383221Smarcel{
82483221Smarcel	switch (linux_flock->l_type) {
82583221Smarcel	case LINUX_F_RDLCK:
82683221Smarcel		bsd_flock->l_type = F_RDLCK;
82783221Smarcel		break;
82883221Smarcel	case LINUX_F_WRLCK:
82983221Smarcel		bsd_flock->l_type = F_WRLCK;
83083221Smarcel		break;
83183221Smarcel	case LINUX_F_UNLCK:
83283221Smarcel		bsd_flock->l_type = F_UNLCK;
83383221Smarcel		break;
83483221Smarcel	default:
83583221Smarcel		bsd_flock->l_type = -1;
83683221Smarcel		break;
83783221Smarcel	}
83883221Smarcel	bsd_flock->l_whence = linux_flock->l_whence;
83983221Smarcel	bsd_flock->l_start = (off_t)linux_flock->l_start;
84083221Smarcel	bsd_flock->l_len = (off_t)linux_flock->l_len;
84183221Smarcel	bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
84283221Smarcel}
84383221Smarcel
84483221Smarcelstatic void
84583221Smarcelbsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock)
84683221Smarcel{
84783221Smarcel	switch (bsd_flock->l_type) {
84883221Smarcel	case F_RDLCK:
84983221Smarcel		linux_flock->l_type = LINUX_F_RDLCK;
85083221Smarcel		break;
85183221Smarcel	case F_WRLCK:
85283221Smarcel		linux_flock->l_type = LINUX_F_WRLCK;
85383221Smarcel		break;
85483221Smarcel	case F_UNLCK:
85583221Smarcel		linux_flock->l_type = LINUX_F_UNLCK;
85683221Smarcel		break;
85783221Smarcel	}
85883221Smarcel	linux_flock->l_whence = bsd_flock->l_whence;
85983221Smarcel	linux_flock->l_start = (l_off_t)bsd_flock->l_start;
86083221Smarcel	linux_flock->l_len = (l_off_t)bsd_flock->l_len;
86183221Smarcel	linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
86283221Smarcel}
86383221Smarcel
86483221Smarcel#if defined(__i386__)
86583221Smarcelstruct l_flock64 {
86683221Smarcel	l_short		l_type;
86783221Smarcel	l_short		l_whence;
86883221Smarcel	l_loff_t	l_start;
86983221Smarcel	l_loff_t	l_len;
87083221Smarcel	l_pid_t		l_pid;
87183221Smarcel};
87283221Smarcel
87383221Smarcelstatic void
87483221Smarcellinux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock)
87583221Smarcel{
87683221Smarcel	switch (linux_flock->l_type) {
87783221Smarcel	case LINUX_F_RDLCK:
87883221Smarcel		bsd_flock->l_type = F_RDLCK;
87983221Smarcel		break;
88083221Smarcel	case LINUX_F_WRLCK:
88183221Smarcel		bsd_flock->l_type = F_WRLCK;
88283221Smarcel		break;
88383221Smarcel	case LINUX_F_UNLCK:
88483221Smarcel		bsd_flock->l_type = F_UNLCK;
88583221Smarcel		break;
88683221Smarcel	default:
88783221Smarcel		bsd_flock->l_type = -1;
88883221Smarcel		break;
88983221Smarcel	}
89083221Smarcel	bsd_flock->l_whence = linux_flock->l_whence;
89183221Smarcel	bsd_flock->l_start = (off_t)linux_flock->l_start;
89283221Smarcel	bsd_flock->l_len = (off_t)linux_flock->l_len;
89383221Smarcel	bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
89483221Smarcel}
89583221Smarcel
89683221Smarcelstatic void
89783221Smarcelbsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock)
89883221Smarcel{
89983221Smarcel	switch (bsd_flock->l_type) {
90083221Smarcel	case F_RDLCK:
90183221Smarcel		linux_flock->l_type = LINUX_F_RDLCK;
90283221Smarcel		break;
90383221Smarcel	case F_WRLCK:
90483221Smarcel		linux_flock->l_type = LINUX_F_WRLCK;
90583221Smarcel		break;
90683221Smarcel	case F_UNLCK:
90783221Smarcel		linux_flock->l_type = LINUX_F_UNLCK;
90883221Smarcel		break;
90983221Smarcel	}
91083221Smarcel	linux_flock->l_whence = bsd_flock->l_whence;
91183221Smarcel	linux_flock->l_start = (l_loff_t)bsd_flock->l_start;
91283221Smarcel	linux_flock->l_len = (l_loff_t)bsd_flock->l_len;
91383221Smarcel	linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
91483221Smarcel}
91583221Smarcel#endif /* __i386__ */
91683221Smarcel
91783221Smarcel#if defined(__alpha__)
91883221Smarcel#define	linux_fcntl64_args	linux_fcntl_args
91983221Smarcel#endif
92083221Smarcel
92183221Smarcelstatic int
92283366Sjulianfcntl_common(struct thread *td, struct linux_fcntl64_args *args)
92383221Smarcel{
92483221Smarcel	struct fcntl_args fcntl_args;
92583221Smarcel	struct filedesc *fdp;
92683221Smarcel	struct file *fp;
92783221Smarcel	int error, result;
92883221Smarcel
92983221Smarcel	fcntl_args.fd = args->fd;
93083221Smarcel
93183221Smarcel	switch (args->cmd) {
93283221Smarcel	case LINUX_F_DUPFD:
93383221Smarcel		fcntl_args.cmd = F_DUPFD;
93483221Smarcel		fcntl_args.arg = args->arg;
93583366Sjulian		return (fcntl(td, &fcntl_args));
93683221Smarcel
93783221Smarcel	case LINUX_F_GETFD:
93883221Smarcel		fcntl_args.cmd = F_GETFD;
93983366Sjulian		return (fcntl(td, &fcntl_args));
94083221Smarcel
94183221Smarcel	case LINUX_F_SETFD:
94283221Smarcel		fcntl_args.cmd = F_SETFD;
94383221Smarcel		fcntl_args.arg = args->arg;
94483366Sjulian		return (fcntl(td, &fcntl_args));
94583221Smarcel
94683221Smarcel	case LINUX_F_GETFL:
94783221Smarcel		fcntl_args.cmd = F_GETFL;
94883366Sjulian		error = fcntl(td, &fcntl_args);
94983366Sjulian		result = td->td_retval[0];
95083366Sjulian		td->td_retval[0] = 0;
95183221Smarcel		if (result & O_RDONLY)
95283366Sjulian			td->td_retval[0] |= LINUX_O_RDONLY;
95383221Smarcel		if (result & O_WRONLY)
95483366Sjulian			td->td_retval[0] |= LINUX_O_WRONLY;
95583221Smarcel		if (result & O_RDWR)
95683366Sjulian			td->td_retval[0] |= LINUX_O_RDWR;
95783221Smarcel		if (result & O_NDELAY)
95883366Sjulian			td->td_retval[0] |= LINUX_O_NONBLOCK;
95983221Smarcel		if (result & O_APPEND)
96083366Sjulian			td->td_retval[0] |= LINUX_O_APPEND;
96183221Smarcel		if (result & O_FSYNC)
96283366Sjulian			td->td_retval[0] |= LINUX_O_SYNC;
96383221Smarcel		if (result & O_ASYNC)
96483366Sjulian			td->td_retval[0] |= LINUX_FASYNC;
96583221Smarcel		return (error);
96683221Smarcel
96783221Smarcel	case LINUX_F_SETFL:
96883221Smarcel		fcntl_args.arg = 0;
96983221Smarcel		if (args->arg & LINUX_O_NDELAY)
97083221Smarcel			fcntl_args.arg |= O_NONBLOCK;
97183221Smarcel		if (args->arg & LINUX_O_APPEND)
97283221Smarcel			fcntl_args.arg |= O_APPEND;
97383221Smarcel		if (args->arg & LINUX_O_SYNC)
97483221Smarcel			fcntl_args.arg |= O_FSYNC;
97583221Smarcel		if (args->arg & LINUX_FASYNC)
97683221Smarcel			fcntl_args.arg |= O_ASYNC;
97783221Smarcel		fcntl_args.cmd = F_SETFL;
97883366Sjulian		return (fcntl(td, &fcntl_args));
97983221Smarcel
98083221Smarcel	case LINUX_F_GETOWN:
98183221Smarcel		fcntl_args.cmd = F_GETOWN;
98283366Sjulian		return (fcntl(td, &fcntl_args));
98383221Smarcel
98483221Smarcel	case LINUX_F_SETOWN:
98583221Smarcel		/*
98683221Smarcel		 * XXX some Linux applications depend on F_SETOWN having no
98783221Smarcel		 * significant effect for pipes (SIGIO is not delivered for
98883221Smarcel		 * pipes under Linux-2.2.35 at least).
98983221Smarcel		 */
99083366Sjulian		fdp = td->td_proc->p_fd;
99183221Smarcel		if ((u_int)args->fd >= fdp->fd_nfiles ||
99283221Smarcel		    (fp = fdp->fd_ofiles[args->fd]) == NULL)
99383221Smarcel			return (EBADF);
99483221Smarcel		if (fp->f_type == DTYPE_PIPE)
99583221Smarcel			return (EINVAL);
99683221Smarcel
99783221Smarcel		fcntl_args.cmd = F_SETOWN;
99883221Smarcel		fcntl_args.arg = args->arg;
99983366Sjulian		return (fcntl(td, &fcntl_args));
100083221Smarcel	}
100183221Smarcel
100283221Smarcel	return (EINVAL);
100383221Smarcel}
100483221Smarcel
100583221Smarcelint
100683366Sjulianlinux_fcntl(struct thread *td, struct linux_fcntl_args *args)
100783221Smarcel{
100883221Smarcel	struct linux_fcntl64_args args64;
100983221Smarcel	struct fcntl_args fcntl_args;
101083221Smarcel	struct l_flock linux_flock;
101183221Smarcel	struct flock *bsd_flock;
101283221Smarcel	int error;
101383221Smarcel	caddr_t sg;
101483221Smarcel
101583221Smarcel	sg = stackgap_init();
101683221Smarcel	bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock));
101783221Smarcel
101883221Smarcel#ifdef DEBUG
101983221Smarcel	if (ldebug(fcntl))
102083221Smarcel		printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd);
102183221Smarcel#endif
102283221Smarcel
102383221Smarcel	switch (args->cmd) {
102483221Smarcel	case LINUX_F_GETLK:
102583221Smarcel		error = copyin((caddr_t)args->arg, &linux_flock,
102683221Smarcel		    sizeof(linux_flock));
102783221Smarcel		if (error)
102883221Smarcel			return (error);
102983221Smarcel		linux_to_bsd_flock(&linux_flock, bsd_flock);
103083221Smarcel		fcntl_args.fd = args->fd;
103183221Smarcel		fcntl_args.cmd = F_GETLK;
103283221Smarcel		fcntl_args.arg = (long)bsd_flock;
103383366Sjulian		error = fcntl(td, &fcntl_args);
103483221Smarcel		if (error)
103583221Smarcel			return (error);
103683221Smarcel		bsd_to_linux_flock(bsd_flock, &linux_flock);
103783221Smarcel		return (copyout(&linux_flock, (caddr_t)args->arg,
103883221Smarcel		    sizeof(linux_flock)));
103983221Smarcel
104083221Smarcel	case LINUX_F_SETLK:
104183221Smarcel		error = copyin((caddr_t)args->arg, &linux_flock,
104283221Smarcel		    sizeof(linux_flock));
104383221Smarcel		if (error)
104483221Smarcel			return (error);
104583221Smarcel		linux_to_bsd_flock(&linux_flock, bsd_flock);
104683221Smarcel		fcntl_args.fd = args->fd;
104783221Smarcel		fcntl_args.cmd = F_SETLK;
104883221Smarcel		fcntl_args.arg = (long)bsd_flock;
104983366Sjulian		return (fcntl(td, &fcntl_args));
105083221Smarcel
105183221Smarcel	case LINUX_F_SETLKW:
105283221Smarcel		error = copyin((caddr_t)args->arg, &linux_flock,
105383221Smarcel		    sizeof(linux_flock));
105483221Smarcel		if (error)
105583221Smarcel			return (error);
105683221Smarcel		linux_to_bsd_flock(&linux_flock, bsd_flock);
105783221Smarcel		fcntl_args.fd = args->fd;
105883221Smarcel		fcntl_args.cmd = F_SETLKW;
105983221Smarcel		fcntl_args.arg = (long)bsd_flock;
106083366Sjulian		return (fcntl(td, &fcntl_args));
106183221Smarcel	}
106283221Smarcel
106383221Smarcel	args64.fd = args->fd;
106483221Smarcel	args64.cmd = args->cmd;
106583221Smarcel	args64.arg = args->arg;
106683366Sjulian	return (fcntl_common(td, &args64));
106783221Smarcel}
106883221Smarcel
106983221Smarcel#if defined(__i386__)
107083221Smarcelint
107183366Sjulianlinux_fcntl64(struct thread *td, struct linux_fcntl64_args *args)
107283221Smarcel{
107383221Smarcel	struct fcntl_args fcntl_args;
107483221Smarcel	struct l_flock64 linux_flock;
107583221Smarcel	struct flock *bsd_flock;
107683221Smarcel	int error;
107783221Smarcel	caddr_t sg;
107883221Smarcel
107983221Smarcel	sg = stackgap_init();
108083221Smarcel	bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock));
108183221Smarcel
108283221Smarcel#ifdef DEBUG
108383221Smarcel	if (ldebug(fcntl64))
108483221Smarcel		printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd);
108583221Smarcel#endif
108683221Smarcel
108783221Smarcel	switch (args->cmd) {
108883221Smarcel	case LINUX_F_GETLK:
108983221Smarcel		error = copyin((caddr_t)args->arg, &linux_flock,
109083221Smarcel		    sizeof(linux_flock));
109183221Smarcel		if (error)
109283221Smarcel			return (error);
109383221Smarcel		linux_to_bsd_flock64(&linux_flock, bsd_flock);
109483221Smarcel		fcntl_args.fd = args->fd;
109583221Smarcel		fcntl_args.cmd = F_GETLK;
109683221Smarcel		fcntl_args.arg = (long)bsd_flock;
109783366Sjulian		error = fcntl(td, &fcntl_args);
109883221Smarcel		if (error)
109983221Smarcel			return (error);
110083221Smarcel		bsd_to_linux_flock64(bsd_flock, &linux_flock);
110183221Smarcel		return (copyout(&linux_flock, (caddr_t)args->arg,
110283221Smarcel		    sizeof(linux_flock)));
110383221Smarcel
110483221Smarcel	case LINUX_F_SETLK:
110583221Smarcel		error = copyin((caddr_t)args->arg, &linux_flock,
110683221Smarcel		    sizeof(linux_flock));
110783221Smarcel		if (error)
110883221Smarcel			return (error);
110983221Smarcel		linux_to_bsd_flock64(&linux_flock, bsd_flock);
111083221Smarcel		fcntl_args.fd = args->fd;
111183221Smarcel		fcntl_args.cmd = F_SETLK;
111283221Smarcel		fcntl_args.arg = (long)bsd_flock;
111383366Sjulian		return (fcntl(td, &fcntl_args));
111483221Smarcel
111583221Smarcel	case LINUX_F_SETLKW:
111683221Smarcel		error = copyin((caddr_t)args->arg, &linux_flock,
111783221Smarcel		    sizeof(linux_flock));
111883221Smarcel		if (error)
111983221Smarcel			return (error);
112083221Smarcel		linux_to_bsd_flock64(&linux_flock, bsd_flock);
112183221Smarcel		fcntl_args.fd = args->fd;
112283221Smarcel		fcntl_args.cmd = F_SETLKW;
112383221Smarcel		fcntl_args.arg = (long)bsd_flock;
112483366Sjulian		return (fcntl(td, &fcntl_args));
112583221Smarcel	}
112683221Smarcel
112783366Sjulian	return (fcntl_common(td, args));
112883221Smarcel}
112983221Smarcel#endif /* __i386__ */
113085022Smarcel
113185022Smarcelint
113285022Smarcellinux_chown(struct thread *td, struct linux_chown_args *args)
113385022Smarcel{
113485022Smarcel	struct chown_args bsd;
113585022Smarcel	caddr_t sg;
113685022Smarcel
113785022Smarcel	sg = stackgap_init();
113885022Smarcel	CHECKALTEXIST(td, &sg, args->path);
113985022Smarcel
114085022Smarcel#ifdef DEBUG
114185022Smarcel	if (ldebug(chown))
114285022Smarcel		printf(ARGS(chown, "%s, %d, %d"), args->path, args->uid,
114385022Smarcel		    args->gid);
114485022Smarcel#endif
114585022Smarcel
114685022Smarcel	bsd.path = args->path;
114785022Smarcel	bsd.uid = args->uid;
114885022Smarcel	bsd.gid = args->gid;
114985022Smarcel	return (chown(td, &bsd));
115085022Smarcel}
115185022Smarcel
115285022Smarcelint
115385022Smarcellinux_lchown(struct thread *td, struct linux_lchown_args *args)
115485022Smarcel{
115585022Smarcel	struct lchown_args bsd;
115685022Smarcel	caddr_t sg;
115785022Smarcel
115885022Smarcel	sg = stackgap_init();
115985022Smarcel	CHECKALTEXIST(td, &sg, args->path);
116085022Smarcel
116185022Smarcel#ifdef DEBUG
116285022Smarcel	if (ldebug(lchown))
116385022Smarcel		printf(ARGS(lchown, "%s, %d, %d"), args->path, args->uid,
116485022Smarcel		    args->gid);
116585022Smarcel#endif
116685022Smarcel
116785022Smarcel	bsd.path = args->path;
116885022Smarcel	bsd.uid = args->uid;
116985022Smarcel	bsd.gid = args->gid;
117085022Smarcel	return (lchown(td, &bsd));
117185022Smarcel}
1172