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