Initial import from FreeBSD RELENG_4:
[games.git] / sys / emulation / ibcs2 / i386 / ibcs2_fcntl.c
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: src/sys/i386/ibcs2/ibcs2_fcntl.c,v 1.14 1999/09/19 17:00:14 green Exp $
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/ttycom.h>
38 #include <sys/sysproto.h>
39
40 #include <i386/ibcs2/ibcs2_fcntl.h>
41 #include <i386/ibcs2/ibcs2_signal.h>
42 #include <i386/ibcs2/ibcs2_proto.h>
43 #include <i386/ibcs2/ibcs2_util.h>
44
45 static void cvt_iflock2flock __P((struct ibcs2_flock *, struct flock *));
46 static void cvt_flock2iflock __P((struct flock *, struct ibcs2_flock *));
47 static int  cvt_o_flags      __P((int));
48 static int  oflags2ioflags   __P((int));
49 static int  ioflags2oflags   __P((int));
50
51 static int
52 cvt_o_flags(flags)
53         int flags;
54 {
55         int r = 0;
56
57         /* convert mode into NetBSD mode */
58         if (flags & IBCS2_O_WRONLY) r |= O_WRONLY;
59         if (flags & IBCS2_O_RDWR)   r |= O_RDWR;
60         if (flags & (IBCS2_O_NDELAY | IBCS2_O_NONBLOCK)) r |= O_NONBLOCK;
61         if (flags & IBCS2_O_APPEND) r |= O_APPEND;
62         if (flags & IBCS2_O_SYNC)   r |= O_FSYNC;
63         if (flags & IBCS2_O_CREAT)  r |= O_CREAT;
64         if (flags & IBCS2_O_TRUNC)  r |= O_TRUNC /* | O_CREAT ??? */;
65         if (flags & IBCS2_O_EXCL)   r |= O_EXCL;
66         if (flags & IBCS2_O_RDONLY) r |= O_RDONLY;
67         if (flags & IBCS2_O_PRIV)   r |= O_EXLOCK;
68         if (flags & IBCS2_O_NOCTTY) r |= O_NOCTTY;
69         return r;
70 }
71
72 static void
73 cvt_flock2iflock(flp, iflp)
74         struct flock *flp;
75         struct ibcs2_flock *iflp;
76 {
77         switch (flp->l_type) {
78         case F_RDLCK:
79                 iflp->l_type = IBCS2_F_RDLCK;
80                 break;
81         case F_WRLCK:
82                 iflp->l_type = IBCS2_F_WRLCK;
83                 break;
84         case F_UNLCK:
85                 iflp->l_type = IBCS2_F_UNLCK;
86                 break;
87         }
88         iflp->l_whence = (short)flp->l_whence;
89         iflp->l_start = (ibcs2_off_t)flp->l_start;
90         iflp->l_len = (ibcs2_off_t)flp->l_len;
91         iflp->l_sysid = 0;
92         iflp->l_pid = (ibcs2_pid_t)flp->l_pid;
93 }
94
95 #ifdef DEBUG_IBCS2
96 static void
97 print_flock(struct flock *flp)
98 {
99   printf("flock: start=%x len=%x pid=%d type=%d whence=%d\n",
100          (int)flp->l_start, (int)flp->l_len, (int)flp->l_pid,
101          flp->l_type, flp->l_whence);
102 }
103 #endif
104
105 static void
106 cvt_iflock2flock(iflp, flp)
107         struct ibcs2_flock *iflp;
108         struct flock *flp;
109 {
110         flp->l_start = (off_t)iflp->l_start;
111         flp->l_len = (off_t)iflp->l_len;
112         flp->l_pid = (pid_t)iflp->l_pid;
113         switch (iflp->l_type) {
114         case IBCS2_F_RDLCK:
115                 flp->l_type = F_RDLCK;
116                 break;
117         case IBCS2_F_WRLCK:
118                 flp->l_type = F_WRLCK;
119                 break;
120         case IBCS2_F_UNLCK:
121                 flp->l_type = F_UNLCK;
122                 break;
123         }
124         flp->l_whence = iflp->l_whence;
125 }
126
127 /* convert iBCS2 mode into NetBSD mode */
128 static int
129 ioflags2oflags(flags)
130         int flags;
131 {
132         int r = 0;
133         
134         if (flags & IBCS2_O_RDONLY) r |= O_RDONLY;
135         if (flags & IBCS2_O_WRONLY) r |= O_WRONLY;
136         if (flags & IBCS2_O_RDWR) r |= O_RDWR;
137         if (flags & IBCS2_O_NDELAY) r |= O_NONBLOCK;
138         if (flags & IBCS2_O_APPEND) r |= O_APPEND;
139         if (flags & IBCS2_O_SYNC) r |= O_FSYNC;
140         if (flags & IBCS2_O_NONBLOCK) r |= O_NONBLOCK;
141         if (flags & IBCS2_O_CREAT) r |= O_CREAT;
142         if (flags & IBCS2_O_TRUNC) r |= O_TRUNC;
143         if (flags & IBCS2_O_EXCL) r |= O_EXCL;
144         if (flags & IBCS2_O_NOCTTY) r |= O_NOCTTY;
145         return r;
146 }
147
148 /* convert NetBSD mode into iBCS2 mode */
149 static int
150 oflags2ioflags(flags)
151         int flags;
152 {
153         int r = 0;
154         
155         if (flags & O_RDONLY) r |= IBCS2_O_RDONLY;
156         if (flags & O_WRONLY) r |= IBCS2_O_WRONLY;
157         if (flags & O_RDWR) r |= IBCS2_O_RDWR;
158         if (flags & O_NDELAY) r |= IBCS2_O_NONBLOCK;
159         if (flags & O_APPEND) r |= IBCS2_O_APPEND;
160         if (flags & O_FSYNC) r |= IBCS2_O_SYNC;
161         if (flags & O_NONBLOCK) r |= IBCS2_O_NONBLOCK;
162         if (flags & O_CREAT) r |= IBCS2_O_CREAT;
163         if (flags & O_TRUNC) r |= IBCS2_O_TRUNC;
164         if (flags & O_EXCL) r |= IBCS2_O_EXCL;
165         if (flags & O_NOCTTY) r |= IBCS2_O_NOCTTY;
166         return r;
167 }
168
169 int
170 ibcs2_open(p, uap)
171         struct proc *p;
172         struct ibcs2_open_args *uap;
173 {
174         int noctty = SCARG(uap, flags) & IBCS2_O_NOCTTY;
175         int ret;
176         caddr_t sg = stackgap_init();
177
178         SCARG(uap, flags) = cvt_o_flags(SCARG(uap, flags));
179         if (SCARG(uap, flags) & O_CREAT)
180                 CHECKALTCREAT(p, &sg, SCARG(uap, path));
181         else
182                 CHECKALTEXIST(p, &sg, SCARG(uap, path));
183         ret = open(p, (struct open_args *)uap);
184
185 #ifdef SPX_HACK
186         if (ret == ENXIO) {
187                 if (!strcmp(SCARG(uap, path), "/compat/ibcs2/dev/spx"))
188                         ret = spx_open(p, uap);
189         } else
190 #endif /* SPX_HACK */
191         if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
192                 struct filedesc *fdp = p->p_fd;
193                 struct file *fp = fdp->fd_ofiles[p->p_retval[0]];
194
195                 /* ignore any error, just give it a try */
196                 if (fp->f_type == DTYPE_VNODE)
197                         fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, p);
198         }
199         return ret;
200 }
201
202 int
203 ibcs2_creat(p, uap)
204         struct proc *p;  
205         struct ibcs2_creat_args *uap;
206 {       
207         struct open_args cup;   
208         caddr_t sg = stackgap_init();
209
210         CHECKALTCREAT(p, &sg, SCARG(uap, path));
211         SCARG(&cup, path) = SCARG(uap, path);
212         SCARG(&cup, mode) = SCARG(uap, mode);
213         SCARG(&cup, flags) = O_WRONLY | O_CREAT | O_TRUNC;
214         return open(p, &cup);
215 }       
216
217 int
218 ibcs2_access(p, uap)
219         struct proc *p;
220         struct ibcs2_access_args *uap;
221 {
222         struct access_args cup;
223         caddr_t sg = stackgap_init();
224
225         CHECKALTEXIST(p, &sg, SCARG(uap, path));
226         SCARG(&cup, path) = SCARG(uap, path);
227         SCARG(&cup, flags) = SCARG(uap, flags);
228         return access(p, &cup);
229 }
230
231 int
232 ibcs2_fcntl(p, uap)
233         struct proc *p;
234         struct ibcs2_fcntl_args *uap;
235 {
236         int error;
237         struct fcntl_args fa;
238         struct flock *flp;
239         struct ibcs2_flock ifl;
240         
241         switch(SCARG(uap, cmd)) {
242         case IBCS2_F_DUPFD:
243                 SCARG(&fa, fd) = SCARG(uap, fd);
244                 SCARG(&fa, cmd) = F_DUPFD;
245                 SCARG(&fa, arg) = (/* XXX */ int)SCARG(uap, arg);
246                 return fcntl(p, &fa);
247         case IBCS2_F_GETFD:
248                 SCARG(&fa, fd) = SCARG(uap, fd);
249                 SCARG(&fa, cmd) = F_GETFD;
250                 SCARG(&fa, arg) = (/* XXX */ int)SCARG(uap, arg);
251                 return fcntl(p, &fa);
252         case IBCS2_F_SETFD:
253                 SCARG(&fa, fd) = SCARG(uap, fd);
254                 SCARG(&fa, cmd) = F_SETFD;
255                 SCARG(&fa, arg) = (/* XXX */ int)SCARG(uap, arg);
256                 return fcntl(p, &fa);
257         case IBCS2_F_GETFL:
258                 SCARG(&fa, fd) = SCARG(uap, fd);
259                 SCARG(&fa, cmd) = F_GETFL;
260                 SCARG(&fa, arg) = (/* XXX */ int)SCARG(uap, arg);
261                 error = fcntl(p, &fa);
262                 if (error)
263                         return error;
264                 p->p_retval[0] = oflags2ioflags(p->p_retval[0]);
265                 return error;
266         case IBCS2_F_SETFL:
267                 SCARG(&fa, fd) = SCARG(uap, fd);
268                 SCARG(&fa, cmd) = F_SETFL;
269                 SCARG(&fa, arg) = (/* XXX */ int)
270                                   ioflags2oflags((int)SCARG(uap, arg));
271                 return fcntl(p, &fa);
272
273         case IBCS2_F_GETLK:
274             {
275                 caddr_t sg = stackgap_init();
276                 flp = stackgap_alloc(&sg, sizeof(*flp));
277                 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&ifl,
278                                ibcs2_flock_len);
279                 if (error)
280                         return error;
281                 cvt_iflock2flock(&ifl, flp);
282                 SCARG(&fa, fd) = SCARG(uap, fd);
283                 SCARG(&fa, cmd) = F_GETLK;
284                 SCARG(&fa, arg) = (/* XXX */ int)flp;
285                 error = fcntl(p, &fa);
286                 if (error)
287                         return error;
288                 cvt_flock2iflock(flp, &ifl);
289                 return copyout((caddr_t)&ifl, (caddr_t)SCARG(uap, arg),
290                                ibcs2_flock_len);
291             }
292
293         case IBCS2_F_SETLK:
294             {
295                 caddr_t sg = stackgap_init();
296                 flp = stackgap_alloc(&sg, sizeof(*flp));
297                 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&ifl,
298                                ibcs2_flock_len);
299                 if (error)
300                         return error;
301                 cvt_iflock2flock(&ifl, flp);
302                 SCARG(&fa, fd) = SCARG(uap, fd);
303                 SCARG(&fa, cmd) = F_SETLK;
304                 SCARG(&fa, arg) = (/* XXX */ int)flp;
305
306                 return fcntl(p, &fa);
307             }
308
309         case IBCS2_F_SETLKW:
310             {
311                 caddr_t sg = stackgap_init();
312                 flp = stackgap_alloc(&sg, sizeof(*flp));
313                 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&ifl,
314                                ibcs2_flock_len);
315                 if (error)
316                         return error;
317                 cvt_iflock2flock(&ifl, flp);
318                 SCARG(&fa, fd) = SCARG(uap, fd);
319                 SCARG(&fa, cmd) = F_SETLKW;
320                 SCARG(&fa, arg) = (/* XXX */ int)flp;
321                 return fcntl(p, &fa);
322             }
323         }
324         return ENOSYS;
325 }