1139799Simp/*-
211394Sswallace * Copyright (c) 1995 Scott Bartram
311394Sswallace * All rights reserved.
411394Sswallace *
511394Sswallace * Redistribution and use in source and binary forms, with or without
611394Sswallace * modification, are permitted provided that the following conditions
711394Sswallace * are met:
811394Sswallace * 1. Redistributions of source code must retain the above copyright
911394Sswallace *    notice, this list of conditions and the following disclaimer.
1011394Sswallace * 2. Redistributions in binary form must reproduce the above copyright
1111394Sswallace *    notice, this list of conditions and the following disclaimer in the
1211394Sswallace *    documentation and/or other materials provided with the distribution.
1311394Sswallace * 3. The name of the author may not be used to endorse or promote products
1411394Sswallace *    derived from this software without specific prior written permission
1511394Sswallace *
1611394Sswallace * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1711394Sswallace * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1811394Sswallace * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1911394Sswallace * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2011394Sswallace * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2111394Sswallace * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2211394Sswallace * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2311394Sswallace * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2411394Sswallace * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2511394Sswallace * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2611394Sswallace */
2711394Sswallace
28115684Sobrien#include <sys/cdefs.h>
29115684Sobrien__FBSDID("$FreeBSD$");
30115684Sobrien
3133071Seivind#include "opt_spx_hack.h"
3233071Seivind
3311394Sswallace#include <sys/param.h>
3411394Sswallace#include <sys/systm.h>
35224778Srwatson#include <sys/capability.h>
3624131Sbde#include <sys/fcntl.h>
3711394Sswallace#include <sys/file.h>
3811394Sswallace#include <sys/filedesc.h>
3976166Smarkm#include <sys/lock.h>
40141488Sjhb#include <sys/malloc.h>
4176166Smarkm#include <sys/mutex.h>
42134266Sjhb#include <sys/syscallsubr.h>
4376166Smarkm#include <sys/sysproto.h>
4424206Sbde#include <sys/ttycom.h>
4511394Sswallace
4611397Sswallace#include <i386/ibcs2/ibcs2_fcntl.h>
4711397Sswallace#include <i386/ibcs2/ibcs2_signal.h>
4811397Sswallace#include <i386/ibcs2/ibcs2_proto.h>
4911397Sswallace#include <i386/ibcs2/ibcs2_util.h>
5011394Sswallace
5192761Salfredstatic void cvt_iflock2flock(struct ibcs2_flock *, struct flock *);
5292761Salfredstatic void cvt_flock2iflock(struct flock *, struct ibcs2_flock *);
5392761Salfredstatic int  cvt_o_flags(int);
5492761Salfredstatic int  oflags2ioflags(int);
5592761Salfredstatic int  ioflags2oflags(int);
5611394Sswallace
5711394Sswallacestatic int
5811394Sswallacecvt_o_flags(flags)
5911394Sswallace	int flags;
6011394Sswallace{
6111394Sswallace	int r = 0;
6211394Sswallace
6311394Sswallace        /* convert mode into NetBSD mode */
6411394Sswallace	if (flags & IBCS2_O_WRONLY) r |= O_WRONLY;
6511397Sswallace	if (flags & IBCS2_O_RDWR)   r |= O_RDWR;
6611394Sswallace	if (flags & (IBCS2_O_NDELAY | IBCS2_O_NONBLOCK)) r |= O_NONBLOCK;
6711394Sswallace	if (flags & IBCS2_O_APPEND) r |= O_APPEND;
6811397Sswallace	if (flags & IBCS2_O_SYNC)   r |= O_FSYNC;
6911397Sswallace	if (flags & IBCS2_O_CREAT)  r |= O_CREAT;
7011397Sswallace	if (flags & IBCS2_O_TRUNC)  r |= O_TRUNC /* | O_CREAT ??? */;
7111397Sswallace	if (flags & IBCS2_O_EXCL)   r |= O_EXCL;
7211397Sswallace	if (flags & IBCS2_O_RDONLY) r |= O_RDONLY;
7311397Sswallace	if (flags & IBCS2_O_PRIV)   r |= O_EXLOCK;
7411397Sswallace	if (flags & IBCS2_O_NOCTTY) r |= O_NOCTTY;
7511394Sswallace	return r;
7611394Sswallace}
7711394Sswallace
7811394Sswallacestatic void
7911394Sswallacecvt_flock2iflock(flp, iflp)
8011394Sswallace	struct flock *flp;
8111394Sswallace	struct ibcs2_flock *iflp;
8211394Sswallace{
8311394Sswallace	switch (flp->l_type) {
8411394Sswallace	case F_RDLCK:
8511394Sswallace		iflp->l_type = IBCS2_F_RDLCK;
8611394Sswallace		break;
8711394Sswallace	case F_WRLCK:
8811394Sswallace		iflp->l_type = IBCS2_F_WRLCK;
8911394Sswallace		break;
9011394Sswallace	case F_UNLCK:
9111394Sswallace		iflp->l_type = IBCS2_F_UNLCK;
9211394Sswallace		break;
9311394Sswallace	}
9411394Sswallace	iflp->l_whence = (short)flp->l_whence;
9511394Sswallace	iflp->l_start = (ibcs2_off_t)flp->l_start;
9611394Sswallace	iflp->l_len = (ibcs2_off_t)flp->l_len;
97177633Sdfr	iflp->l_sysid = flp->l_sysid;
9811394Sswallace	iflp->l_pid = (ibcs2_pid_t)flp->l_pid;
9911394Sswallace}
10011394Sswallace
10111397Sswallace#ifdef DEBUG_IBCS2
10211394Sswallacestatic void
10311397Sswallaceprint_flock(struct flock *flp)
10411397Sswallace{
10511397Sswallace  printf("flock: start=%x len=%x pid=%d type=%d whence=%d\n",
10611397Sswallace	 (int)flp->l_start, (int)flp->l_len, (int)flp->l_pid,
10711397Sswallace	 flp->l_type, flp->l_whence);
10811397Sswallace}
10911397Sswallace#endif
11011397Sswallace
11111397Sswallacestatic void
11211394Sswallacecvt_iflock2flock(iflp, flp)
11311394Sswallace	struct ibcs2_flock *iflp;
11411394Sswallace	struct flock *flp;
11511394Sswallace{
11611394Sswallace	flp->l_start = (off_t)iflp->l_start;
11711394Sswallace	flp->l_len = (off_t)iflp->l_len;
11811394Sswallace	flp->l_pid = (pid_t)iflp->l_pid;
11911394Sswallace	switch (iflp->l_type) {
12011394Sswallace	case IBCS2_F_RDLCK:
12111394Sswallace		flp->l_type = F_RDLCK;
12211394Sswallace		break;
12311394Sswallace	case IBCS2_F_WRLCK:
12411394Sswallace		flp->l_type = F_WRLCK;
12511394Sswallace		break;
12611394Sswallace	case IBCS2_F_UNLCK:
12711394Sswallace		flp->l_type = F_UNLCK;
12811394Sswallace		break;
12911394Sswallace	}
13011394Sswallace	flp->l_whence = iflp->l_whence;
131177633Sdfr	flp->l_sysid = iflp->l_sysid;
13211394Sswallace}
13311394Sswallace
13411394Sswallace/* convert iBCS2 mode into NetBSD mode */
13511394Sswallacestatic int
13611394Sswallaceioflags2oflags(flags)
13711394Sswallace	int flags;
13811394Sswallace{
13911394Sswallace	int r = 0;
14011394Sswallace
14111394Sswallace	if (flags & IBCS2_O_RDONLY) r |= O_RDONLY;
14211394Sswallace	if (flags & IBCS2_O_WRONLY) r |= O_WRONLY;
14311394Sswallace	if (flags & IBCS2_O_RDWR) r |= O_RDWR;
14411394Sswallace	if (flags & IBCS2_O_NDELAY) r |= O_NONBLOCK;
14511394Sswallace	if (flags & IBCS2_O_APPEND) r |= O_APPEND;
14611394Sswallace	if (flags & IBCS2_O_SYNC) r |= O_FSYNC;
14711394Sswallace	if (flags & IBCS2_O_NONBLOCK) r |= O_NONBLOCK;
14811394Sswallace	if (flags & IBCS2_O_CREAT) r |= O_CREAT;
14911394Sswallace	if (flags & IBCS2_O_TRUNC) r |= O_TRUNC;
15011394Sswallace	if (flags & IBCS2_O_EXCL) r |= O_EXCL;
15111394Sswallace	if (flags & IBCS2_O_NOCTTY) r |= O_NOCTTY;
15211394Sswallace	return r;
15311394Sswallace}
15411394Sswallace
15511394Sswallace/* convert NetBSD mode into iBCS2 mode */
15611394Sswallacestatic int
15711394Sswallaceoflags2ioflags(flags)
15811394Sswallace	int flags;
15911394Sswallace{
16011394Sswallace	int r = 0;
16111394Sswallace
16211394Sswallace	if (flags & O_RDONLY) r |= IBCS2_O_RDONLY;
16311394Sswallace	if (flags & O_WRONLY) r |= IBCS2_O_WRONLY;
16411394Sswallace	if (flags & O_RDWR) r |= IBCS2_O_RDWR;
16511394Sswallace	if (flags & O_NDELAY) r |= IBCS2_O_NONBLOCK;
16611394Sswallace	if (flags & O_APPEND) r |= IBCS2_O_APPEND;
16711394Sswallace	if (flags & O_FSYNC) r |= IBCS2_O_SYNC;
16811394Sswallace	if (flags & O_NONBLOCK) r |= IBCS2_O_NONBLOCK;
16911394Sswallace	if (flags & O_CREAT) r |= IBCS2_O_CREAT;
17011394Sswallace	if (flags & O_TRUNC) r |= IBCS2_O_TRUNC;
17111394Sswallace	if (flags & O_EXCL) r |= IBCS2_O_EXCL;
17211394Sswallace	if (flags & O_NOCTTY) r |= IBCS2_O_NOCTTY;
17311394Sswallace	return r;
17411394Sswallace}
17511394Sswallace
17611394Sswallaceint
17783366Sjulianibcs2_open(td, uap)
17883366Sjulian	struct thread *td;
17911394Sswallace	struct ibcs2_open_args *uap;
18011394Sswallace{
181141488Sjhb	struct proc *p;
182141488Sjhb	char *path;
183141488Sjhb	int flags, noctty, ret;
18411394Sswallace
185141488Sjhb	p = td->td_proc;
186141488Sjhb	noctty = uap->flags & IBCS2_O_NOCTTY;
187141488Sjhb	flags = cvt_o_flags(uap->flags);
188107849Salfred	if (uap->flags & O_CREAT)
189141488Sjhb		CHECKALTCREAT(td, uap->path, &path);
19011394Sswallace	else
191141488Sjhb		CHECKALTEXIST(td, uap->path, &path);
192141488Sjhb	ret = kern_open(td, path, UIO_SYSSPACE, flags, uap->mode);
19311394Sswallace
19411527Sswallace#ifdef SPX_HACK
19546568Speter	if (ret == ENXIO) {
196141488Sjhb		if (!strcmp(path, "/compat/ibcs2/dev/spx"))
197141488Sjhb			ret = spx_open(td);
198141488Sjhb		free(path, M_TEMP);
19946568Speter	} else
20011527Sswallace#endif /* SPX_HACK */
201141488Sjhb	free(path, M_TEMP);
20271489Sjhb	PROC_LOCK(p);
20311394Sswallace	if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
204255219Spjd		cap_rights_t rights;
20589306Salfred		struct file *fp;
20689319Salfred		int error;
20711394Sswallace
208255219Spjd		error = fget(td, td->td_retval[0],
209255219Spjd		    cap_rights_init(&rights, CAP_IOCTL), &fp);
21071489Sjhb		PROC_UNLOCK(p);
21189319Salfred		if (error)
21289306Salfred			return (EBADF);
21389306Salfred
21411394Sswallace		/* ignore any error, just give it a try */
21511394Sswallace		if (fp->f_type == DTYPE_VNODE)
216102003Srwatson			fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred,
217102003Srwatson			    td);
21889306Salfred		fdrop(fp, td);
21971489Sjhb	} else
22071489Sjhb		PROC_UNLOCK(p);
22111394Sswallace	return ret;
22211394Sswallace}
22311394Sswallace
22411394Sswallaceint
22583366Sjulianibcs2_creat(td, uap)
22683366Sjulian        struct thread *td;
22711394Sswallace	struct ibcs2_creat_args *uap;
228141488Sjhb{
229141488Sjhb	char *path;
230141488Sjhb	int error;
23111394Sswallace
232141488Sjhb	CHECKALTCREAT(td, uap->path, &path);
233141488Sjhb	error = kern_open(td, path, UIO_SYSSPACE, O_WRONLY | O_CREAT | O_TRUNC,
234141488Sjhb	    uap->mode);
235141488Sjhb	free(path, M_TEMP);
236141488Sjhb	return (error);
23711394Sswallace}
23811394Sswallace
23911394Sswallaceint
24083366Sjulianibcs2_access(td, uap)
24183366Sjulian        struct thread *td;
24211394Sswallace        struct ibcs2_access_args *uap;
24311394Sswallace{
244141488Sjhb	char *path;
245141488Sjhb	int error;
24611394Sswallace
247141488Sjhb        CHECKALTEXIST(td, uap->path, &path);
248227691Sed	error = kern_access(td, path, UIO_SYSSPACE, uap->amode);
249141488Sjhb	free(path, M_TEMP);
250141488Sjhb	return (error);
25111394Sswallace}
25211394Sswallace
25311394Sswallaceint
25483366Sjulianibcs2_fcntl(td, uap)
25583366Sjulian	struct thread *td;
25611394Sswallace	struct ibcs2_fcntl_args *uap;
25711394Sswallace{
258134266Sjhb	intptr_t arg;
25911394Sswallace	int error;
260134266Sjhb	struct flock fl;
26111394Sswallace	struct ibcs2_flock ifl;
262134266Sjhb
263134266Sjhb	arg = (intptr_t)uap->arg;
264107849Salfred	switch(uap->cmd) {
26511394Sswallace	case IBCS2_F_DUPFD:
266134266Sjhb		return (kern_fcntl(td, uap->fd, F_DUPFD, arg));
26711394Sswallace	case IBCS2_F_GETFD:
268134266Sjhb		return (kern_fcntl(td, uap->fd, F_GETFD, arg));
26911394Sswallace	case IBCS2_F_SETFD:
270134266Sjhb		return (kern_fcntl(td, uap->fd, F_SETFD, arg));
27111394Sswallace	case IBCS2_F_GETFL:
272134266Sjhb		error = kern_fcntl(td, uap->fd, F_GETFL, arg);
27311394Sswallace		if (error)
27411394Sswallace			return error;
27583366Sjulian		td->td_retval[0] = oflags2ioflags(td->td_retval[0]);
27611394Sswallace		return error;
27711394Sswallace	case IBCS2_F_SETFL:
278134266Sjhb		return (kern_fcntl(td, uap->fd, F_SETFL,
279134266Sjhb		    ioflags2oflags(arg)));
28011394Sswallace
28111394Sswallace	case IBCS2_F_GETLK:
28211394Sswallace	    {
283107849Salfred		error = copyin((caddr_t)uap->arg, (caddr_t)&ifl,
28411394Sswallace			       ibcs2_flock_len);
28511394Sswallace		if (error)
28611394Sswallace			return error;
287134266Sjhb		cvt_iflock2flock(&ifl, &fl);
288134266Sjhb		error = kern_fcntl(td, uap->fd, F_GETLK, (intptr_t)&fl);
28911394Sswallace		if (error)
29011394Sswallace			return error;
291134266Sjhb		cvt_flock2iflock(&fl, &ifl);
292107849Salfred		return copyout((caddr_t)&ifl, (caddr_t)uap->arg,
29311394Sswallace			       ibcs2_flock_len);
29411394Sswallace	    }
29511394Sswallace
29611394Sswallace	case IBCS2_F_SETLK:
29711394Sswallace	    {
298107849Salfred		error = copyin((caddr_t)uap->arg, (caddr_t)&ifl,
29911394Sswallace			       ibcs2_flock_len);
30011394Sswallace		if (error)
30111394Sswallace			return error;
302134266Sjhb		cvt_iflock2flock(&ifl, &fl);
303134266Sjhb		return (kern_fcntl(td, uap->fd, F_SETLK, (intptr_t)&fl));
30411394Sswallace	    }
30511394Sswallace
30611394Sswallace	case IBCS2_F_SETLKW:
30711394Sswallace	    {
308107849Salfred		error = copyin((caddr_t)uap->arg, (caddr_t)&ifl,
30911394Sswallace			       ibcs2_flock_len);
31011394Sswallace		if (error)
31111394Sswallace			return error;
312134266Sjhb		cvt_iflock2flock(&ifl, &fl);
313134266Sjhb		return (kern_fcntl(td, uap->fd, F_SETLKW, (intptr_t)&fl));
31411394Sswallace	    }
31511394Sswallace	}
31611394Sswallace	return ENOSYS;
31711394Sswallace}
318