ibcs2_fcntl.c revision 92761
1/*
2 * Copyright (c) 1995 Scott Bartram
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 *    derived from this software without specific prior written permission
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * $FreeBSD: head/sys/i386/ibcs2/ibcs2_fcntl.c 92761 2002-03-20 05:48:58Z alfred $
28 */
29
30#include "opt_spx_hack.h"
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/fcntl.h>
35#include <sys/file.h>
36#include <sys/filedesc.h>
37#include <sys/lock.h>
38#include <sys/mutex.h>
39#include <sys/sysproto.h>
40#include <sys/ttycom.h>
41
42#include <i386/ibcs2/ibcs2_fcntl.h>
43#include <i386/ibcs2/ibcs2_signal.h>
44#include <i386/ibcs2/ibcs2_proto.h>
45#include <i386/ibcs2/ibcs2_util.h>
46
47static void cvt_iflock2flock(struct ibcs2_flock *, struct flock *);
48static void cvt_flock2iflock(struct flock *, struct ibcs2_flock *);
49static int  cvt_o_flags(int);
50static int  oflags2ioflags(int);
51static int  ioflags2oflags(int);
52
53static int
54cvt_o_flags(flags)
55	int flags;
56{
57	int r = 0;
58
59        /* convert mode into NetBSD mode */
60	if (flags & IBCS2_O_WRONLY) r |= O_WRONLY;
61	if (flags & IBCS2_O_RDWR)   r |= O_RDWR;
62	if (flags & (IBCS2_O_NDELAY | IBCS2_O_NONBLOCK)) r |= O_NONBLOCK;
63	if (flags & IBCS2_O_APPEND) r |= O_APPEND;
64	if (flags & IBCS2_O_SYNC)   r |= O_FSYNC;
65	if (flags & IBCS2_O_CREAT)  r |= O_CREAT;
66	if (flags & IBCS2_O_TRUNC)  r |= O_TRUNC /* | O_CREAT ??? */;
67	if (flags & IBCS2_O_EXCL)   r |= O_EXCL;
68	if (flags & IBCS2_O_RDONLY) r |= O_RDONLY;
69	if (flags & IBCS2_O_PRIV)   r |= O_EXLOCK;
70	if (flags & IBCS2_O_NOCTTY) r |= O_NOCTTY;
71	return r;
72}
73
74static void
75cvt_flock2iflock(flp, iflp)
76	struct flock *flp;
77	struct ibcs2_flock *iflp;
78{
79	switch (flp->l_type) {
80	case F_RDLCK:
81		iflp->l_type = IBCS2_F_RDLCK;
82		break;
83	case F_WRLCK:
84		iflp->l_type = IBCS2_F_WRLCK;
85		break;
86	case F_UNLCK:
87		iflp->l_type = IBCS2_F_UNLCK;
88		break;
89	}
90	iflp->l_whence = (short)flp->l_whence;
91	iflp->l_start = (ibcs2_off_t)flp->l_start;
92	iflp->l_len = (ibcs2_off_t)flp->l_len;
93	iflp->l_sysid = 0;
94	iflp->l_pid = (ibcs2_pid_t)flp->l_pid;
95}
96
97#ifdef DEBUG_IBCS2
98static void
99print_flock(struct flock *flp)
100{
101  printf("flock: start=%x len=%x pid=%d type=%d whence=%d\n",
102	 (int)flp->l_start, (int)flp->l_len, (int)flp->l_pid,
103	 flp->l_type, flp->l_whence);
104}
105#endif
106
107static void
108cvt_iflock2flock(iflp, flp)
109	struct ibcs2_flock *iflp;
110	struct flock *flp;
111{
112	flp->l_start = (off_t)iflp->l_start;
113	flp->l_len = (off_t)iflp->l_len;
114	flp->l_pid = (pid_t)iflp->l_pid;
115	switch (iflp->l_type) {
116	case IBCS2_F_RDLCK:
117		flp->l_type = F_RDLCK;
118		break;
119	case IBCS2_F_WRLCK:
120		flp->l_type = F_WRLCK;
121		break;
122	case IBCS2_F_UNLCK:
123		flp->l_type = F_UNLCK;
124		break;
125	}
126	flp->l_whence = iflp->l_whence;
127}
128
129/* convert iBCS2 mode into NetBSD mode */
130static int
131ioflags2oflags(flags)
132	int flags;
133{
134	int r = 0;
135
136	if (flags & IBCS2_O_RDONLY) r |= O_RDONLY;
137	if (flags & IBCS2_O_WRONLY) r |= O_WRONLY;
138	if (flags & IBCS2_O_RDWR) r |= O_RDWR;
139	if (flags & IBCS2_O_NDELAY) r |= O_NONBLOCK;
140	if (flags & IBCS2_O_APPEND) r |= O_APPEND;
141	if (flags & IBCS2_O_SYNC) r |= O_FSYNC;
142	if (flags & IBCS2_O_NONBLOCK) r |= O_NONBLOCK;
143	if (flags & IBCS2_O_CREAT) r |= O_CREAT;
144	if (flags & IBCS2_O_TRUNC) r |= O_TRUNC;
145	if (flags & IBCS2_O_EXCL) r |= O_EXCL;
146	if (flags & IBCS2_O_NOCTTY) r |= O_NOCTTY;
147	return r;
148}
149
150/* convert NetBSD mode into iBCS2 mode */
151static int
152oflags2ioflags(flags)
153	int flags;
154{
155	int r = 0;
156
157	if (flags & O_RDONLY) r |= IBCS2_O_RDONLY;
158	if (flags & O_WRONLY) r |= IBCS2_O_WRONLY;
159	if (flags & O_RDWR) r |= IBCS2_O_RDWR;
160	if (flags & O_NDELAY) r |= IBCS2_O_NONBLOCK;
161	if (flags & O_APPEND) r |= IBCS2_O_APPEND;
162	if (flags & O_FSYNC) r |= IBCS2_O_SYNC;
163	if (flags & O_NONBLOCK) r |= IBCS2_O_NONBLOCK;
164	if (flags & O_CREAT) r |= IBCS2_O_CREAT;
165	if (flags & O_TRUNC) r |= IBCS2_O_TRUNC;
166	if (flags & O_EXCL) r |= IBCS2_O_EXCL;
167	if (flags & O_NOCTTY) r |= IBCS2_O_NOCTTY;
168	return r;
169}
170
171int
172ibcs2_open(td, uap)
173	struct thread *td;
174	struct ibcs2_open_args *uap;
175{
176	struct proc *p = td->td_proc;
177	int noctty = SCARG(uap, flags) & IBCS2_O_NOCTTY;
178	int ret;
179	caddr_t sg = stackgap_init();
180
181	SCARG(uap, flags) = cvt_o_flags(SCARG(uap, flags));
182	if (SCARG(uap, flags) & O_CREAT)
183		CHECKALTCREAT(td, &sg, SCARG(uap, path));
184	else
185		CHECKALTEXIST(td, &sg, SCARG(uap, path));
186	ret = open(td, (struct open_args *)uap);
187
188#ifdef SPX_HACK
189	if (ret == ENXIO) {
190		if (!strcmp(SCARG(uap, path), "/compat/ibcs2/dev/spx"))
191			ret = spx_open(td, uap);
192	} else
193#endif /* SPX_HACK */
194	PROC_LOCK(p);
195	if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
196		struct file *fp;
197		int error;
198
199		error = fget(td, td->td_retval[0], &fp);
200		PROC_UNLOCK(p);
201		if (error)
202			return (EBADF);
203
204		/* ignore any error, just give it a try */
205		if (fp->f_type == DTYPE_VNODE)
206			fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td);
207		fdrop(fp, td);
208	} else
209		PROC_UNLOCK(p);
210	return ret;
211}
212
213int
214ibcs2_creat(td, uap)
215        struct thread *td;
216	struct ibcs2_creat_args *uap;
217{
218	struct open_args cup;
219	caddr_t sg = stackgap_init();
220
221	CHECKALTCREAT(td, &sg, SCARG(uap, path));
222	SCARG(&cup, path) = SCARG(uap, path);
223	SCARG(&cup, mode) = SCARG(uap, mode);
224	SCARG(&cup, flags) = O_WRONLY | O_CREAT | O_TRUNC;
225	return open(td, &cup);
226}
227
228int
229ibcs2_access(td, uap)
230        struct thread *td;
231        struct ibcs2_access_args *uap;
232{
233        struct access_args cup;
234        caddr_t sg = stackgap_init();
235
236        CHECKALTEXIST(td, &sg, SCARG(uap, path));
237        SCARG(&cup, path) = SCARG(uap, path);
238        SCARG(&cup, flags) = SCARG(uap, flags);
239        return access(td, &cup);
240}
241
242int
243ibcs2_fcntl(td, uap)
244	struct thread *td;
245	struct ibcs2_fcntl_args *uap;
246{
247	int error;
248	struct fcntl_args fa;
249	struct flock *flp;
250	struct ibcs2_flock ifl;
251
252	switch(SCARG(uap, cmd)) {
253	case IBCS2_F_DUPFD:
254		SCARG(&fa, fd) = SCARG(uap, fd);
255		SCARG(&fa, cmd) = F_DUPFD;
256		SCARG(&fa, arg) = (/* XXX */ int)SCARG(uap, arg);
257		return fcntl(td, &fa);
258	case IBCS2_F_GETFD:
259		SCARG(&fa, fd) = SCARG(uap, fd);
260		SCARG(&fa, cmd) = F_GETFD;
261		SCARG(&fa, arg) = (/* XXX */ int)SCARG(uap, arg);
262		return fcntl(td, &fa);
263	case IBCS2_F_SETFD:
264		SCARG(&fa, fd) = SCARG(uap, fd);
265		SCARG(&fa, cmd) = F_SETFD;
266		SCARG(&fa, arg) = (/* XXX */ int)SCARG(uap, arg);
267		return fcntl(td, &fa);
268	case IBCS2_F_GETFL:
269		SCARG(&fa, fd) = SCARG(uap, fd);
270		SCARG(&fa, cmd) = F_GETFL;
271		SCARG(&fa, arg) = (/* XXX */ int)SCARG(uap, arg);
272		error = fcntl(td, &fa);
273		if (error)
274			return error;
275		td->td_retval[0] = oflags2ioflags(td->td_retval[0]);
276		return error;
277	case IBCS2_F_SETFL:
278		SCARG(&fa, fd) = SCARG(uap, fd);
279		SCARG(&fa, cmd) = F_SETFL;
280		SCARG(&fa, arg) = (/* XXX */ int)
281				  ioflags2oflags((int)SCARG(uap, arg));
282		return fcntl(td, &fa);
283
284	case IBCS2_F_GETLK:
285	    {
286		caddr_t sg = stackgap_init();
287		flp = stackgap_alloc(&sg, sizeof(*flp));
288		error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&ifl,
289			       ibcs2_flock_len);
290		if (error)
291			return error;
292		cvt_iflock2flock(&ifl, flp);
293		SCARG(&fa, fd) = SCARG(uap, fd);
294		SCARG(&fa, cmd) = F_GETLK;
295		SCARG(&fa, arg) = (/* XXX */ int)flp;
296		error = fcntl(td, &fa);
297		if (error)
298			return error;
299		cvt_flock2iflock(flp, &ifl);
300		return copyout((caddr_t)&ifl, (caddr_t)SCARG(uap, arg),
301			       ibcs2_flock_len);
302	    }
303
304	case IBCS2_F_SETLK:
305	    {
306		caddr_t sg = stackgap_init();
307		flp = stackgap_alloc(&sg, sizeof(*flp));
308		error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&ifl,
309			       ibcs2_flock_len);
310		if (error)
311			return error;
312		cvt_iflock2flock(&ifl, flp);
313		SCARG(&fa, fd) = SCARG(uap, fd);
314		SCARG(&fa, cmd) = F_SETLK;
315		SCARG(&fa, arg) = (/* XXX */ int)flp;
316
317		return fcntl(td, &fa);
318	    }
319
320	case IBCS2_F_SETLKW:
321	    {
322		caddr_t sg = stackgap_init();
323		flp = stackgap_alloc(&sg, sizeof(*flp));
324		error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&ifl,
325			       ibcs2_flock_len);
326		if (error)
327			return error;
328		cvt_iflock2flock(&ifl, flp);
329		SCARG(&fa, fd) = SCARG(uap, fd);
330		SCARG(&fa, cmd) = F_SETLKW;
331		SCARG(&fa, arg) = (/* XXX */ int)flp;
332		return fcntl(td, &fa);
333	    }
334	}
335	return ENOSYS;
336}
337