1 /* $NetBSD: sunos32_ioctl.c,v 1.36 2021/09/07 11:43:05 riastradh Exp $ */
2 /* from: NetBSD: sunos_ioctl.c,v 1.35 2001/02/03 22:20:02 mrg Exp */
3
4 /*
5 * Copyright (c) 2001 Matthew R. Green
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 /*
31 * Copyright (c) 1993 Markus Wild.
32 * All rights reserved.
33 *
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
36 * are met:
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. The name of the author may not be used to endorse or promote products
40 * derived from this software without specific prior written permission
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 *
53 * loosely from: Header: sunos_ioctl.c,v 1.7 93/05/28 04:40:43 torek Exp
54 */
55
56 #include <sys/cdefs.h>
57 __KERNEL_RCSID(0, "$NetBSD: sunos32_ioctl.c,v 1.36 2021/09/07 11:43:05 riastradh Exp $");
58
59 #if defined(_KERNEL_OPT)
60 #include "opt_compat_netbsd32.h"
61 #include "opt_execfmt.h"
62 #endif
63
64 #include <sys/param.h>
65 #include <sys/proc.h>
66 #include <sys/systm.h>
67 #include <sys/file.h>
68 #include <sys/filedesc.h>
69 #include <sys/ioctl.h>
70 #include <sys/termios.h>
71 #include <sys/tty.h>
72 #include <sys/socket.h>
73 #include <sys/audioio.h>
74 #include <sys/vnode.h>
75 #include <sys/mount.h>
76 #include <sys/disklabel.h>
77 #include <sys/syscallargs.h>
78
79 #include <miscfs/specfs/specdev.h>
80
81 #include <net/if.h>
82
83 #include <dev/sun/disklabel.h>
84
85 #include <compat/sys/sockio.h>
86
87 #include <compat/sunos/sunos.h>
88 #include <compat/sunos/sunos_syscallargs.h>
89 #include <compat/netbsd32/netbsd32.h>
90 #include <compat/netbsd32/netbsd32_syscallargs.h>
91 #include <compat/sunos32/sunos32.h>
92 #include <compat/sunos32/sunos32_syscallargs.h>
93 #include <compat/common/compat_util.h>
94
95 /*
96 * SunOS ioctl calls.
97 * This file is something of a hodge-podge.
98 * Support gets added as things turn up....
99 */
100
101 static const struct speedtab sptab[] = {
102 { 0, 0 },
103 { 50, 1 },
104 { 75, 2 },
105 { 110, 3 },
106 { 134, 4 },
107 { 135, 4 },
108 { 150, 5 },
109 { 200, 6 },
110 { 300, 7 },
111 { 600, 8 },
112 { 1200, 9 },
113 { 1800, 10 },
114 { 2400, 11 },
115 { 4800, 12 },
116 { 9600, 13 },
117 { 19200, 14 },
118 { 38400, 15 },
119 { -1, -1 }
120 };
121
122 static const netbsd32_u_long s2btab[] = {
123 0,
124 50,
125 75,
126 110,
127 134,
128 150,
129 200,
130 300,
131 600,
132 1200,
133 1800,
134 2400,
135 4800,
136 9600,
137 19200,
138 38400,
139 };
140
141 static void stios2btios(struct sunos_termios *, struct termios *);
142 static void btios2stios(struct termios *, struct sunos_termios *);
143 static void stios2stio(struct sunos_termios *, struct sunos_termio *);
144 static void stio2stios(struct sunos_termio *, struct sunos_termios *);
145
146 /*
147 * These two conversion functions have mostly been done
148 * with some perl cut&paste, then hand-edited to comment
149 * out what doesn't exist under NetBSD.
150 * A note from Markus's code:
151 * (l & BITMASK1) / BITMASK1 * BITMASK2 is translated
152 * optimally by gcc m68k, much better than any ?: stuff.
153 * Code may vary with different architectures of course.
154 *
155 * I don't know what optimizer you used, but seeing divu's and
156 * bfextu's in the m68k assembly output did not encourage me...
157 * as well, gcc on the sparc definitely generates much better
158 * code with `?:'.
159 */
160
161 static void
stios2btios(struct sunos_termios * st,struct termios * bt)162 stios2btios(struct sunos_termios *st, struct termios *bt)
163 {
164 netbsd32_u_long l, r;
165
166 memset(bt, 0, sizeof(*bt));
167
168 l = st->c_iflag;
169 r = ((l & 0x00000001) ? IGNBRK : 0);
170 r |= ((l & 0x00000002) ? BRKINT : 0);
171 r |= ((l & 0x00000004) ? IGNPAR : 0);
172 r |= ((l & 0x00000008) ? PARMRK : 0);
173 r |= ((l & 0x00000010) ? INPCK : 0);
174 r |= ((l & 0x00000020) ? ISTRIP : 0);
175 r |= ((l & 0x00000040) ? INLCR : 0);
176 r |= ((l & 0x00000080) ? IGNCR : 0);
177 r |= ((l & 0x00000100) ? ICRNL : 0);
178 /* ((l & 0x00000200) ? IUCLC : 0) */
179 r |= ((l & 0x00000400) ? IXON : 0);
180 r |= ((l & 0x00000800) ? IXANY : 0);
181 r |= ((l & 0x00001000) ? IXOFF : 0);
182 r |= ((l & 0x00002000) ? IMAXBEL : 0);
183 bt->c_iflag = r;
184
185 l = st->c_oflag;
186 r = ((l & 0x00000001) ? OPOST : 0);
187 /* ((l & 0x00000002) ? OLCUC : 0) */
188 r |= ((l & 0x00000004) ? ONLCR : 0);
189 /* ((l & 0x00000008) ? OCRNL : 0) */
190 /* ((l & 0x00000010) ? ONOCR : 0) */
191 /* ((l & 0x00000020) ? ONLRET : 0) */
192 /* ((l & 0x00000040) ? OFILL : 0) */
193 /* ((l & 0x00000080) ? OFDEL : 0) */
194 /* ((l & 0x00000100) ? NLDLY : 0) */
195 /* ((l & 0x00000100) ? NL1 : 0) */
196 /* ((l & 0x00000600) ? CRDLY : 0) */
197 /* ((l & 0x00000200) ? CR1 : 0) */
198 /* ((l & 0x00000400) ? CR2 : 0) */
199 /* ((l & 0x00000600) ? CR3 : 0) */
200 /* ((l & 0x00001800) ? TABDLY : 0) */
201 /* ((l & 0x00000800) ? TAB1 : 0) */
202 /* ((l & 0x00001000) ? TAB2 : 0) */
203 r |= ((l & 0x00001800) ? OXTABS : 0);
204 /* ((l & 0x00002000) ? BSDLY : 0) */
205 /* ((l & 0x00002000) ? BS1 : 0) */
206 /* ((l & 0x00004000) ? VTDLY : 0) */
207 /* ((l & 0x00004000) ? VT1 : 0) */
208 /* ((l & 0x00008000) ? FFDLY : 0) */
209 /* ((l & 0x00008000) ? FF1 : 0) */
210 /* ((l & 0x00010000) ? PAGEOUT : 0) */
211 /* ((l & 0x00020000) ? WRAP : 0) */
212 bt->c_oflag = r;
213
214 l = st->c_cflag;
215 switch (l & 0x00000030) {
216 case 0:
217 r = CS5;
218 break;
219 case 0x00000010:
220 r = CS6;
221 break;
222 case 0x00000020:
223 r = CS7;
224 break;
225 case 0x00000030:
226 r = CS8;
227 break;
228 }
229 r |= ((l & 0x00000040) ? CSTOPB : 0);
230 r |= ((l & 0x00000080) ? CREAD : 0);
231 r |= ((l & 0x00000100) ? PARENB : 0);
232 r |= ((l & 0x00000200) ? PARODD : 0);
233 r |= ((l & 0x00000400) ? HUPCL : 0);
234 r |= ((l & 0x00000800) ? CLOCAL : 0);
235 /* ((l & 0x00001000) ? LOBLK : 0) */
236 r |= ((l & 0x80000000) ? (CRTS_IFLOW|CCTS_OFLOW) : 0);
237 bt->c_cflag = r;
238
239 bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f];
240
241 l = st->c_lflag;
242 r = ((l & 0x00000001) ? ISIG : 0);
243 r |= ((l & 0x00000002) ? ICANON : 0);
244 /* ((l & 0x00000004) ? XCASE : 0) */
245 r |= ((l & 0x00000008) ? ECHO : 0);
246 r |= ((l & 0x00000010) ? ECHOE : 0);
247 r |= ((l & 0x00000020) ? ECHOK : 0);
248 r |= ((l & 0x00000040) ? ECHONL : 0);
249 r |= ((l & 0x00000080) ? NOFLSH : 0);
250 r |= ((l & 0x00000100) ? TOSTOP : 0);
251 r |= ((l & 0x00000200) ? ECHOCTL : 0);
252 r |= ((l & 0x00000400) ? ECHOPRT : 0);
253 r |= ((l & 0x00000800) ? ECHOKE : 0);
254 /* ((l & 0x00001000) ? DEFECHO : 0) */
255 r |= ((l & 0x00002000) ? FLUSHO : 0);
256 r |= ((l & 0x00004000) ? PENDIN : 0);
257 bt->c_lflag = r;
258
259 bt->c_cc[VINTR] = st->c_cc[0] ? st->c_cc[0] : _POSIX_VDISABLE;
260 bt->c_cc[VQUIT] = st->c_cc[1] ? st->c_cc[1] : _POSIX_VDISABLE;
261 bt->c_cc[VERASE] = st->c_cc[2] ? st->c_cc[2] : _POSIX_VDISABLE;
262 bt->c_cc[VKILL] = st->c_cc[3] ? st->c_cc[3] : _POSIX_VDISABLE;
263 bt->c_cc[VEOF] = st->c_cc[4] ? st->c_cc[4] : _POSIX_VDISABLE;
264 bt->c_cc[VEOL] = st->c_cc[5] ? st->c_cc[5] : _POSIX_VDISABLE;
265 bt->c_cc[VEOL2] = st->c_cc[6] ? st->c_cc[6] : _POSIX_VDISABLE;
266 /* bt->c_cc[VSWTCH] = st->c_cc[7] ? st->c_cc[7] : _POSIX_VDISABLE; */
267 bt->c_cc[VSTART] = st->c_cc[8] ? st->c_cc[8] : _POSIX_VDISABLE;
268 bt->c_cc[VSTOP] = st->c_cc[9] ? st->c_cc[9] : _POSIX_VDISABLE;
269 bt->c_cc[VSUSP] = st->c_cc[10] ? st->c_cc[10] : _POSIX_VDISABLE;
270 bt->c_cc[VDSUSP] = st->c_cc[11] ? st->c_cc[11] : _POSIX_VDISABLE;
271 bt->c_cc[VREPRINT] = st->c_cc[12] ? st->c_cc[12] : _POSIX_VDISABLE;
272 bt->c_cc[VDISCARD] = st->c_cc[13] ? st->c_cc[13] : _POSIX_VDISABLE;
273 bt->c_cc[VWERASE] = st->c_cc[14] ? st->c_cc[14] : _POSIX_VDISABLE;
274 bt->c_cc[VLNEXT] = st->c_cc[15] ? st->c_cc[15] : _POSIX_VDISABLE;
275 bt->c_cc[VSTATUS] = st->c_cc[16] ? st->c_cc[16] : _POSIX_VDISABLE;
276
277 /* if `raw mode', create native VMIN/VTIME from SunOS VEOF/VEOL */
278 bt->c_cc[VMIN] = (bt->c_lflag & ICANON) ? 1 : bt->c_cc[VEOF];
279 bt->c_cc[VTIME] = (bt->c_lflag & ICANON) ? 1 : bt->c_cc[VEOL];
280 }
281
282
283 static void
btios2stios(struct termios * bt,struct sunos_termios * st)284 btios2stios(struct termios *bt, struct sunos_termios *st)
285 {
286 netbsd32_u_long l, r;
287 int s;
288
289 memset(st, 0, sizeof(*st));
290
291 l = bt->c_iflag;
292 r = ((l & IGNBRK) ? 0x00000001 : 0);
293 r |= ((l & BRKINT) ? 0x00000002 : 0);
294 r |= ((l & IGNPAR) ? 0x00000004 : 0);
295 r |= ((l & PARMRK) ? 0x00000008 : 0);
296 r |= ((l & INPCK) ? 0x00000010 : 0);
297 r |= ((l & ISTRIP) ? 0x00000020 : 0);
298 r |= ((l & INLCR) ? 0x00000040 : 0);
299 r |= ((l & IGNCR) ? 0x00000080 : 0);
300 r |= ((l & ICRNL) ? 0x00000100 : 0);
301 /* ((l & IUCLC) ? 0x00000200 : 0) */
302 r |= ((l & IXON) ? 0x00000400 : 0);
303 r |= ((l & IXANY) ? 0x00000800 : 0);
304 r |= ((l & IXOFF) ? 0x00001000 : 0);
305 r |= ((l & IMAXBEL) ? 0x00002000 : 0);
306 st->c_iflag = r;
307
308 l = bt->c_oflag;
309 r = ((l & OPOST) ? 0x00000001 : 0);
310 /* ((l & OLCUC) ? 0x00000002 : 0) */
311 r |= ((l & ONLCR) ? 0x00000004 : 0);
312 /* ((l & OCRNL) ? 0x00000008 : 0) */
313 /* ((l & ONOCR) ? 0x00000010 : 0) */
314 /* ((l & ONLRET) ? 0x00000020 : 0) */
315 /* ((l & OFILL) ? 0x00000040 : 0) */
316 /* ((l & OFDEL) ? 0x00000080 : 0) */
317 /* ((l & NLDLY) ? 0x00000100 : 0) */
318 /* ((l & NL1) ? 0x00000100 : 0) */
319 /* ((l & CRDLY) ? 0x00000600 : 0) */
320 /* ((l & CR1) ? 0x00000200 : 0) */
321 /* ((l & CR2) ? 0x00000400 : 0) */
322 /* ((l & CR3) ? 0x00000600 : 0) */
323 /* ((l & TABDLY) ? 0x00001800 : 0) */
324 /* ((l & TAB1) ? 0x00000800 : 0) */
325 /* ((l & TAB2) ? 0x00001000 : 0) */
326 r |= ((l & OXTABS) ? 0x00001800 : 0);
327 /* ((l & BSDLY) ? 0x00002000 : 0) */
328 /* ((l & BS1) ? 0x00002000 : 0) */
329 /* ((l & VTDLY) ? 0x00004000 : 0) */
330 /* ((l & VT1) ? 0x00004000 : 0) */
331 /* ((l & FFDLY) ? 0x00008000 : 0) */
332 /* ((l & FF1) ? 0x00008000 : 0) */
333 /* ((l & PAGEOUT) ? 0x00010000 : 0) */
334 /* ((l & WRAP) ? 0x00020000 : 0) */
335 st->c_oflag = r;
336
337 l = bt->c_cflag;
338 switch (l & CSIZE) {
339 case CS5:
340 r = 0;
341 break;
342 case CS6:
343 r = 0x00000010;
344 break;
345 case CS7:
346 r = 0x00000020;
347 break;
348 case CS8:
349 r = 0x00000030;
350 break;
351 }
352 r |= ((l & CSTOPB) ? 0x00000040 : 0);
353 r |= ((l & CREAD) ? 0x00000080 : 0);
354 r |= ((l & PARENB) ? 0x00000100 : 0);
355 r |= ((l & PARODD) ? 0x00000200 : 0);
356 r |= ((l & HUPCL) ? 0x00000400 : 0);
357 r |= ((l & CLOCAL) ? 0x00000800 : 0);
358 /* ((l & LOBLK) ? 0x00001000 : 0) */
359 r |= ((l & (CRTS_IFLOW|CCTS_OFLOW)) ? 0x80000000 : 0);
360 st->c_cflag = r;
361
362 l = bt->c_lflag;
363 r = ((l & ISIG) ? 0x00000001 : 0);
364 r |= ((l & ICANON) ? 0x00000002 : 0);
365 /* ((l & XCASE) ? 0x00000004 : 0) */
366 r |= ((l & ECHO) ? 0x00000008 : 0);
367 r |= ((l & ECHOE) ? 0x00000010 : 0);
368 r |= ((l & ECHOK) ? 0x00000020 : 0);
369 r |= ((l & ECHONL) ? 0x00000040 : 0);
370 r |= ((l & NOFLSH) ? 0x00000080 : 0);
371 r |= ((l & TOSTOP) ? 0x00000100 : 0);
372 r |= ((l & ECHOCTL) ? 0x00000200 : 0);
373 r |= ((l & ECHOPRT) ? 0x00000400 : 0);
374 r |= ((l & ECHOKE) ? 0x00000800 : 0);
375 /* ((l & DEFECHO) ? 0x00001000 : 0) */
376 r |= ((l & FLUSHO) ? 0x00002000 : 0);
377 r |= ((l & PENDIN) ? 0x00004000 : 0);
378 st->c_lflag = r;
379
380 s = ttspeedtab(bt->c_ospeed, sptab);
381 if (s >= 0)
382 st->c_cflag |= s;
383
384 st->c_cc[0] = bt->c_cc[VINTR] != _POSIX_VDISABLE? bt->c_cc[VINTR]:0;
385 st->c_cc[1] = bt->c_cc[VQUIT] != _POSIX_VDISABLE? bt->c_cc[VQUIT]:0;
386 st->c_cc[2] = bt->c_cc[VERASE] != _POSIX_VDISABLE? bt->c_cc[VERASE]:0;
387 st->c_cc[3] = bt->c_cc[VKILL] != _POSIX_VDISABLE? bt->c_cc[VKILL]:0;
388 st->c_cc[4] = bt->c_cc[VEOF] != _POSIX_VDISABLE? bt->c_cc[VEOF]:0;
389 st->c_cc[5] = bt->c_cc[VEOL] != _POSIX_VDISABLE? bt->c_cc[VEOL]:0;
390 st->c_cc[6] = bt->c_cc[VEOL2] != _POSIX_VDISABLE? bt->c_cc[VEOL2]:0;
391 st->c_cc[7] = 0;
392 /* bt->c_cc[VSWTCH] != _POSIX_VDISABLE? bt->c_cc[VSWTCH]: */
393 st->c_cc[8] = bt->c_cc[VSTART] != _POSIX_VDISABLE? bt->c_cc[VSTART]:0;
394 st->c_cc[9] = bt->c_cc[VSTOP] != _POSIX_VDISABLE? bt->c_cc[VSTOP]:0;
395 st->c_cc[10]= bt->c_cc[VSUSP] != _POSIX_VDISABLE? bt->c_cc[VSUSP]:0;
396 st->c_cc[11]= bt->c_cc[VDSUSP] != _POSIX_VDISABLE? bt->c_cc[VDSUSP]:0;
397 st->c_cc[12]= bt->c_cc[VREPRINT]!= _POSIX_VDISABLE? bt->c_cc[VREPRINT]:0;
398 st->c_cc[13]= bt->c_cc[VDISCARD]!= _POSIX_VDISABLE? bt->c_cc[VDISCARD]:0;
399 st->c_cc[14]= bt->c_cc[VWERASE] != _POSIX_VDISABLE? bt->c_cc[VWERASE]:0;
400 st->c_cc[15]= bt->c_cc[VLNEXT] != _POSIX_VDISABLE? bt->c_cc[VLNEXT]:0;
401 st->c_cc[16]= bt->c_cc[VSTATUS] != _POSIX_VDISABLE? bt->c_cc[VSTATUS]:0;
402
403 if (!(bt->c_lflag & ICANON)) {
404 /* SunOS stores VMIN/VTIME in VEOF/VEOL (if ICANON is off) */
405 st->c_cc[4] = bt->c_cc[VMIN];
406 st->c_cc[5] = bt->c_cc[VTIME];
407 }
408
409 st->c_line = 0;
410 }
411
412 static void
stios2stio(struct sunos_termios * ts,struct sunos_termio * t)413 stios2stio(struct sunos_termios *ts, struct sunos_termio *t)
414 {
415
416 memset(t, 0, sizeof(*t));
417 t->c_iflag = ts->c_iflag;
418 t->c_oflag = ts->c_oflag;
419 t->c_cflag = ts->c_cflag;
420 t->c_lflag = ts->c_lflag;
421 t->c_line = ts->c_line;
422 memcpy(t->c_cc, ts->c_cc, 8);
423 }
424
425 static void
stio2stios(struct sunos_termio * t,struct sunos_termios * ts)426 stio2stios(struct sunos_termio *t, struct sunos_termios *ts)
427 {
428
429 memset(ts, 0, sizeof(*ts));
430 ts->c_iflag = t->c_iflag;
431 ts->c_oflag = t->c_oflag;
432 ts->c_cflag = t->c_cflag;
433 ts->c_lflag = t->c_lflag;
434 ts->c_line = t->c_line;
435 memcpy(ts->c_cc, t->c_cc, 8); /* don't touch the upper fields! */
436 }
437
438
439 static int
sunos32_do_ioctl(int fd,int cmd,void * arg,struct lwp * l)440 sunos32_do_ioctl(int fd, int cmd, void *arg, struct lwp *l)
441 {
442 file_t *fp;
443 struct vnode *vp;
444 int error;
445
446 if ((error = fd_getvnode(fd, &fp)) != 0)
447 return error;
448 if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
449 fd_putfile(fd);
450 return EBADF;
451 }
452 error = fp->f_ops->fo_ioctl(fp, cmd, arg);
453 if (error == EIO && cmd == TIOCGPGRP) {
454 vp = fp->f_vnode;
455 if (vp != NULL && vp->v_type == VCHR && major(vp->v_rdev) == 21)
456 error = ENOTTY;
457 }
458 fd_putfile(fd);
459 return error;
460 }
461
462 int
sunos32_sys_ioctl(struct lwp * l,const struct sunos32_sys_ioctl_args * uap,register_t * retval)463 sunos32_sys_ioctl(struct lwp *l, const struct sunos32_sys_ioctl_args *uap,
464 register_t *retval)
465 {
466 /* {
467 int fd;
468 netbsd32_u_long com;
469 netbsd32_caddr_t data;
470 } */
471 struct netbsd32_ioctl_args bsd_ua;
472 int error;
473
474 SCARG(&bsd_ua, fd) = SCARG(uap, fd);
475 SCARG(&bsd_ua, com) = SCARG(uap, com);
476 SCARG(&bsd_ua, data) = SCARG(uap, data);
477
478 switch (SCARG(uap, com)) {
479 case _IOR('t', 0, int):
480 SCARG(&bsd_ua, com) = TIOCGETD;
481 break;
482 case _IOW('t', 1, int):
483 {
484 int disc;
485
486 if ((error = copyin(SCARG_P32(uap, data), &disc,
487 sizeof disc)) != 0)
488 return error;
489
490 /* map SunOS NTTYDISC into our termios discipline */
491 if (disc == 2)
492 disc = 0;
493 /* all other disciplines are not supported by NetBSD */
494 if (disc)
495 return ENXIO;
496
497 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSETD, &disc, l);
498 }
499 case _IOW('t', 101, int): /* sun SUNOS_TIOCSSOFTCAR */
500 {
501 int x; /* unused */
502
503 return copyin(SCARG_P32(uap, data), &x, sizeof x);
504 }
505 case _IOR('t', 100, int): /* sun SUNOS_TIOCSSOFTCAR */
506 {
507 int x = 0;
508
509 return copyout(&x, SCARG_P32(uap, data), sizeof x);
510 }
511 case _IO('t', 36): /* sun TIOCCONS, no parameters */
512 {
513 int on = 1;
514 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCCONS, &on, l);
515 }
516 case _IOW('t', 37, struct sunos_ttysize):
517 {
518 struct winsize ws;
519 struct sunos_ttysize ss;
520
521 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGWINSZ, &ws,
522 l);
523 if (error != 0)
524 return error;
525
526 error = copyin(SCARG_P32(uap, data), &ss, sizeof(ss));
527 if (error != 0)
528 return error;
529
530 ws.ws_row = ss.ts_row;
531 ws.ws_col = ss.ts_col;
532
533 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSWINSZ, &ws, l);
534 }
535 case _IOW('t', 38, struct sunos_ttysize):
536 {
537 struct winsize ws;
538 struct sunos_ttysize ss;
539
540 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGWINSZ, &ws,
541 l);
542 if (error != 0)
543 return error;
544
545 memset(&ss, 0, sizeof(ss));
546 ss.ts_row = ws.ws_row;
547 ss.ts_col = ws.ws_col;
548
549 return copyout(&ss, SCARG_P32(uap, data), sizeof(ss));
550 }
551 case _IOW('t', 130, int): /* TIOCSETPGRP: posix variant */
552 SCARG(&bsd_ua, com) = TIOCSPGRP;
553 break;
554 case _IOR('t', 131, int): /* TIOCGETPGRP: posix variant */
555 {
556 /*
557 * sigh, must do error translation on pty devices
558 * (see also kern/tty_pty.c)
559 */
560 int pgrp;
561 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGPGRP, &pgrp,
562 l);
563 if (error)
564 return error;
565 return copyout(&pgrp, SCARG_P32(uap, data), sizeof(pgrp));
566 }
567 case _IO('t', 132):
568 SCARG(&bsd_ua, com) = TIOCSCTTY;
569 break;
570 case SUNOS_TCGETA:
571 case SUNOS_TCGETS:
572 {
573 struct termios bts;
574 struct sunos_termios sts;
575 struct sunos_termio st;
576
577 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGETA, &bts,
578 l);
579 if (error != 0)
580 return error;
581
582 btios2stios (&bts, &sts);
583 if (SCARG(uap, com) == SUNOS_TCGETA) {
584 stios2stio (&sts, &st);
585 return copyout(&st, SCARG_P32(uap, data), sizeof(st));
586 } else
587 return copyout(&sts, SCARG_P32(uap, data),
588 sizeof(sts));
589 /*NOTREACHED*/
590 }
591 case SUNOS_TCSETA:
592 case SUNOS_TCSETAW:
593 case SUNOS_TCSETAF:
594 {
595 struct termios bts;
596 struct sunos_termios sts;
597 struct sunos_termio st;
598
599 if ((error = copyin(SCARG_P32(uap, data), &st,
600 sizeof(st))) != 0)
601 return error;
602
603 /* get full BSD termios so we don't lose information */
604 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGETA,
605 &bts, l)) != 0)
606 return error;
607
608 /*
609 * convert to sun termios, copy in information from
610 * termio, and convert back, then set new values.
611 */
612 btios2stios(&bts, &sts);
613 stio2stios(&st, &sts);
614 stios2btios(&sts, &bts);
615
616 return sunos32_do_ioctl(SCARG(&bsd_ua, fd),
617 SCARG(uap, com) - SUNOS_TCSETA + TIOCSETA, &bts, l);
618 }
619 case SUNOS_TCSETS:
620 case SUNOS_TCSETSW:
621 case SUNOS_TCSETSF:
622 {
623 struct termios bts;
624 struct sunos_termios sts;
625
626 if ((error = copyin(SCARG_P32(uap, data), &sts,
627 sizeof(sts))) != 0)
628 return error;
629 stios2btios (&sts, &bts);
630 return sunos32_do_ioctl(SCARG(&bsd_ua, fd),
631 SCARG(uap, com) - SUNOS_TCSETS + TIOCSETA, &bts, l);
632 }
633 /*
634 * Pseudo-tty ioctl translations.
635 */
636 case _IOW('t', 32, int): { /* TIOCTCNTL */
637 int error1, on;
638
639 error1 = copyin(SCARG_P32(uap, data), &on, sizeof(on));
640 if (error1)
641 return error1;
642 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCUCNTL, &on, l);
643 }
644 case _IOW('t', 33, int): { /* TIOCSIGNAL */
645 int error1, sig;
646
647 error1 = copyin(SCARG_P32(uap, data), &sig, sizeof(sig));
648 if (error1)
649 return error1;
650 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSIG, &sig, l);
651 }
652
653 /*
654 * Socket ioctl translations.
655 */
656 #define IFREQ_IN(a) { \
657 struct oifreq ifreq; \
658 error = copyin(SCARG_P32(uap, data), &ifreq, sizeof(ifreq)); \
659 if (error) \
660 return error; \
661 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), a, &ifreq, l); \
662 }
663 #define IFREQ_INOUT(a) { \
664 struct oifreq ifreq; \
665 error = copyin(SCARG_P32(uap, data), &ifreq, sizeof(ifreq)); \
666 if (error) \
667 return error; \
668 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), a, &ifreq, l)) != 0) \
669 return error; \
670 return copyout(&ifreq, SCARG_P32(uap, data), sizeof(ifreq)); \
671 }
672
673 case _IOW('i', 12, struct oifreq):
674 /* SIOCSIFADDR */
675 break;
676
677 case _IOWR('i', 13, struct oifreq):
678 IFREQ_INOUT(OOSIOCGIFADDR);
679
680 case _IOW('i', 14, struct oifreq):
681 /* SIOCSIFDSTADDR */
682 break;
683
684 case _IOWR('i', 15, struct oifreq):
685 IFREQ_INOUT(OOSIOCGIFDSTADDR);
686
687 case _IOW('i', 16, struct oifreq):
688 /* SIOCSIFFLAGS */
689 break;
690
691 case _IOWR('i', 17, struct oifreq):
692 /* SIOCGIFFLAGS */
693 break;
694
695 case _IOW('i', 21, struct oifreq):
696 IFREQ_IN(SIOCSIFMTU);
697
698 case _IOWR('i', 22, struct oifreq):
699 IFREQ_INOUT(SIOCGIFMTU);
700
701 case _IOWR('i', 23, struct oifreq):
702 IFREQ_INOUT(SIOCGIFBRDADDR);
703
704 case _IOW('i', 24, struct oifreq):
705 IFREQ_IN(SIOCSIFBRDADDR);
706
707 case _IOWR('i', 25, struct oifreq):
708 IFREQ_INOUT(OOSIOCGIFNETMASK);
709
710 case _IOW('i', 26, struct oifreq):
711 IFREQ_IN(SIOCSIFNETMASK);
712
713 case _IOWR('i', 27, struct oifreq):
714 IFREQ_INOUT(SIOCGIFMETRIC);
715
716 case _IOWR('i', 28, struct oifreq):
717 IFREQ_IN(SIOCSIFMETRIC);
718
719 case _IOW('i', 30, struct arpreq):
720 /* SIOCSARP */
721 break;
722
723 case _IOWR('i', 31, struct arpreq):
724 /* SIOCGARP */
725 break;
726
727 case _IOW('i', 32, struct arpreq):
728 /* SIOCDARP */
729 break;
730
731 case _IOW('i', 18, struct oifreq): /* SIOCSIFMEM */
732 case _IOWR('i', 19, struct oifreq): /* SIOCGIFMEM */
733 case _IOW('i', 40, struct oifreq): /* SIOCUPPER */
734 case _IOW('i', 41, struct oifreq): /* SIOCLOWER */
735 case _IOW('i', 44, struct oifreq): /* SIOCSETSYNC */
736 case _IOWR('i', 45, struct oifreq): /* SIOCGETSYNC */
737 case _IOWR('i', 46, struct oifreq): /* SIOCSDSTATS */
738 case _IOWR('i', 47, struct oifreq): /* SIOCSESTATS */
739 case _IOW('i', 48, int): /* SIOCSPROMISC */
740 case _IOW('i', 49, struct oifreq): /* SIOCADDMULTI */
741 case _IOW('i', 50, struct oifreq): /* SIOCDELMULTI */
742 return EOPNOTSUPP;
743
744 case _IOWR('i', 20, struct oifconf): /* SIOCGIFCONF */
745 {
746 struct oifconf ifcf;
747
748 /*
749 * XXX: two more problems
750 * 1. our sockaddr's are variable length, not always
751 * sizeof(sockaddr)
752 * 2. this returns a name per protocol, ie. it returns two
753 * "lo0"'s
754 */
755 error = copyin(SCARG_P32(uap, data), &ifcf, sizeof(ifcf));
756 if (error)
757 return error;
758 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), OOSIOCGIFCONF,
759 &ifcf, l);
760 if (error)
761 return error;
762 return copyout(&ifcf, SCARG_P32(uap, data), sizeof(ifcf));
763 }
764
765 /*
766 * Audio ioctl translations.
767 */
768 case _IOR('A', 1, struct sunos_audio_info): /* AUDIO_GETINFO */
769 sunos_au_getinfo:
770 {
771 struct audio_info aui;
772 struct sunos_audio_info sunos_aui;
773
774 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_GETINFO, &aui, l);
775 if (error)
776 return error;
777
778 memset(&sunos_aui, 0, sizeof(sunos_aui));
779
780 sunos_aui.play = *(struct sunos_audio_prinfo *)&aui.play;
781 sunos_aui.record = *(struct sunos_audio_prinfo *)&aui.record;
782
783 /* `avail_ports' is `seek' in BSD */
784 sunos_aui.play.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
785 sunos_aui.record.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
786
787 sunos_aui.play.waiting = 0;
788 sunos_aui.record.waiting = 0;
789 sunos_aui.play.eof = 0;
790 sunos_aui.record.eof = 0;
791 sunos_aui.monitor_gain = 0; /* aui.__spare; XXX */
792 /*XXXsunos_aui.output_muted = 0;*/
793 /*XXX*/sunos_aui.reserved[0] = 0;
794 /*XXX*/sunos_aui.reserved[1] = 0;
795 /*XXX*/sunos_aui.reserved[2] = 0;
796 /*XXX*/sunos_aui.reserved[3] = 0;
797
798 return copyout(&sunos_aui, SCARG_P32(uap, data),
799 sizeof(sunos_aui));
800 }
801
802 case _IOWR('A', 2, struct sunos_audio_info): /* AUDIO_SETINFO */
803 {
804 struct audio_info aui;
805 struct sunos_audio_info sunos_aui;
806
807 error = copyin(SCARG_P32(uap, data), &sunos_aui,
808 sizeof(sunos_aui));
809 if (error)
810 return error;
811
812 aui.play = *(struct audio_prinfo *)&sunos_aui.play;
813 aui.record = *(struct audio_prinfo *)&sunos_aui.record;
814 /* aui.__spare = sunos_aui.monitor_gain; */
815 aui.blocksize = ~0;
816 aui.hiwat = ~0;
817 aui.lowat = ~0;
818 /* XXX somebody check this please. - is: aui.backlog = ~0; */
819 aui.mode = ~0;
820 /*
821 * The bsd driver does not distinguish between paused and
822 * active. (In the sun driver, not active means samples are
823 * not output at all, but paused means the last streams buffer
824 * is drained and then output stops.) If either are 0, then
825 * when stop output. Otherwise, if either are non-zero,
826 * we resume.
827 */
828 if (sunos_aui.play.pause == 0 || sunos_aui.play.active == 0)
829 aui.play.pause = 0;
830 else if (sunos_aui.play.pause != (u_char)~0 ||
831 sunos_aui.play.active != (u_char)~0)
832 aui.play.pause = 1;
833 if (sunos_aui.record.pause == 0 || sunos_aui.record.active == 0)
834 aui.record.pause = 0;
835 else if (sunos_aui.record.pause != (u_char)~0 ||
836 sunos_aui.record.active != (u_char)~0)
837 aui.record.pause = 1;
838
839 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_SETINFO,
840 &aui, l);
841 if (error)
842 return error;
843 /* Return new state */
844 goto sunos_au_getinfo;
845 }
846 case _IO('A', 3): /* AUDIO_DRAIN */
847 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_DRAIN, NULL,
848 l);
849 case _IOR('A', 4, int): /* AUDIO_GETDEV */
850 {
851 int devtype = SUNOS_AUDIO_DEV_AMD;
852 return copyout(&devtype, SCARG_P32(uap, data),
853 sizeof(devtype));
854 }
855
856 /*
857 * Selected streams ioctls.
858 */
859 #define SUNOS_S_FLUSHR 1
860 #define SUNOS_S_FLUSHW 2
861 #define SUNOS_S_FLUSHRW 3
862
863 #define SUNOS_S_INPUT 1
864 #define SUNOS_S_HIPRI 2
865 #define SUNOS_S_OUTPUT 4
866 #define SUNOS_S_MSG 8
867
868 case _IO('S', 5): /* I_FLUSH */
869 {
870 int tmp = 0;
871 switch ((intptr_t)SCARG_P32(uap, data)) {
872 case SUNOS_S_FLUSHR: tmp = FREAD; break;
873 case SUNOS_S_FLUSHW: tmp = FWRITE; break;
874 case SUNOS_S_FLUSHRW: tmp = FREAD|FWRITE; break;
875 }
876 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCFLUSH, &tmp, l);
877 }
878 case _IO('S', 9): /* I_SETSIG */
879 {
880 int on = 1;
881 if (((intptr_t)SCARG_P32(uap, data) &
882 (SUNOS_S_HIPRI|SUNOS_S_INPUT)) == SUNOS_S_HIPRI)
883 return EOPNOTSUPP;
884 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), FIOASYNC, &on, l);
885 }
886 /*
887 * SunOS disk ioctls, taken from arch/sparc/sparc/disksubr.c
888 * (which was from the old sparc/scsi/sun_disklabel.c), and
889 * modified to suite.
890 */
891 case SUN_DKIOCGGEOM:
892 {
893 struct disklabel dl;
894
895 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), DIOCGDINFO,
896 &dl, l);
897 if (error)
898 return error;
899
900 #define datageom ((struct sun_dkgeom *)SCARG_P32(uap, data))
901 /* XXX can't do memset() on a user address (dsl) */
902 memset(SCARG_P32(uap, data), 0, sizeof(*datageom));
903
904 datageom->sdkc_ncylinders = dl.d_ncylinders;
905 datageom->sdkc_acylinders = dl.d_acylinders;
906 datageom->sdkc_ntracks = dl.d_ntracks;
907 datageom->sdkc_nsectors = dl.d_nsectors;
908 datageom->sdkc_interleave = dl.d_interleave;
909 datageom->sdkc_sparespercyl = dl.d_sparespercyl;
910 datageom->sdkc_rpm = dl.d_rpm;
911 datageom->sdkc_pcylinders = dl.d_ncylinders + dl.d_acylinders;
912 #undef datageom
913 break;
914 }
915
916 case SUN_DKIOCINFO:
917 /* Homey don't do DKIOCINFO */
918 /* XXX can't do memset() on a user address (dsl) */
919 memset(SCARG_P32(uap, data), 0, sizeof(struct sun_dkctlr));
920 break;
921
922 case SUN_DKIOCGPART:
923 {
924 struct partinfo pi;
925 struct disklabel label;
926 int fd = SCARG(&bsd_ua, fd);
927
928 error = sunos32_do_ioctl(fd, DIOCGPARTINFO, &pi, l);
929 if (error)
930 return error;
931 error = sunos32_do_ioctl(fd, DIOCGDINFO, &label, l);
932 if (error)
933 return error;
934
935 if (label.d_secpercyl == 0)
936 return ERANGE; /* XXX */
937 if (pi.pi_offset % label.d_secpercyl != 0)
938 return ERANGE; /* XXX */
939 /* XXX can't do direct writes to a user address (dsl) */
940 #define datapart ((struct sun_dkpart *)SCARG_P32(uap, data))
941 datapart->sdkp_cyloffset = pi.pi_offset / label.d_secpercyl;
942 datapart->sdkp_nsectors = pi.pi_size;
943 #undef datapart
944 }
945
946 }
947 return netbsd32_ioctl(l, &bsd_ua, retval);
948 }
949
950 /* SunOS fcntl(2) cmds not implemented */
951 #define SUN_F_RGETLK 10
952 #define SUN_F_RSETLK 11
953 #define SUN_F_CNVT 12
954 #define SUN_F_RSETLKW 13
955
956 /* SunOS flock translation */
957 struct sunos_flock {
958 short l_type;
959 short l_whence;
960 netbsd32_long l_start;
961 netbsd32_long l_len;
962 short l_pid;
963 short l_xxx;
964 };
965
966 static void bsd_to_sunos_flock(struct flock *, struct sunos_flock *);
967 static void sunos_to_bsd_flock(struct sunos_flock *, struct flock *);
968
969 #define SUNOS_F_RDLCK 1
970 #define SUNOS_F_WRLCK 2
971 #define SUNOS_F_UNLCK 3
972
973 static void
bsd_to_sunos_flock(struct flock * iflp,struct sunos_flock * oflp)974 bsd_to_sunos_flock(struct flock *iflp, struct sunos_flock *oflp)
975 {
976
977 memset(oflp, 0, sizeof(*oflp));
978
979 switch (iflp->l_type) {
980 case F_RDLCK:
981 oflp->l_type = SUNOS_F_RDLCK;
982 break;
983 case F_WRLCK:
984 oflp->l_type = SUNOS_F_WRLCK;
985 break;
986 case F_UNLCK:
987 oflp->l_type = SUNOS_F_UNLCK;
988 break;
989 default:
990 oflp->l_type = -1;
991 break;
992 }
993
994 oflp->l_whence = (short)iflp->l_whence;
995 oflp->l_start = (netbsd32_long)iflp->l_start;
996 oflp->l_len = (netbsd32_long)iflp->l_len;
997 oflp->l_pid = (short)iflp->l_pid;
998 oflp->l_xxx = 0;
999 }
1000
1001
1002 static void
sunos_to_bsd_flock(struct sunos_flock * iflp,struct flock * oflp)1003 sunos_to_bsd_flock(struct sunos_flock *iflp, struct flock *oflp)
1004 {
1005
1006 memset(oflp, 0, sizeof(*oflp));
1007
1008 switch (iflp->l_type) {
1009 case SUNOS_F_RDLCK:
1010 oflp->l_type = F_RDLCK;
1011 break;
1012 case SUNOS_F_WRLCK:
1013 oflp->l_type = F_WRLCK;
1014 break;
1015 case SUNOS_F_UNLCK:
1016 oflp->l_type = F_UNLCK;
1017 break;
1018 default:
1019 oflp->l_type = -1;
1020 break;
1021 }
1022
1023 oflp->l_whence = iflp->l_whence;
1024 oflp->l_start = (off_t) iflp->l_start;
1025 oflp->l_len = (off_t) iflp->l_len;
1026 oflp->l_pid = (pid_t) iflp->l_pid;
1027
1028 }
1029 static struct {
1030 netbsd32_long sun_flg;
1031 netbsd32_long bsd_flg;
1032 } sunfcntl_flgtab[] = {
1033 /* F_[GS]ETFLags that differ: */
1034 #define SUN_FSETBLK 0x0010
1035 #define SUN_SHLOCK 0x0080
1036 #define SUN_EXLOCK 0x0100
1037 #define SUN_FNBIO 0x1000
1038 #define SUN_FSYNC 0x2000
1039 #define SUN_NONBLOCK 0x4000
1040 #define SUN_FNOCTTY 0x8000
1041 { SUN_NONBLOCK, O_NONBLOCK },
1042 { SUN_FNBIO, O_NONBLOCK },
1043 { SUN_SHLOCK, O_SHLOCK },
1044 { SUN_EXLOCK, O_EXLOCK },
1045 { SUN_FSYNC, O_FSYNC },
1046 { SUN_FSETBLK, 0 },
1047 { SUN_FNOCTTY, 0 }
1048 };
1049
1050 int
sunos32_sys_fcntl(struct lwp * l,const struct sunos32_sys_fcntl_args * uap,register_t * retval)1051 sunos32_sys_fcntl(struct lwp *l, const struct sunos32_sys_fcntl_args *uap,
1052 register_t *retval)
1053 {
1054 /* {
1055 syscallarg(int) fd;
1056 syscallarg(int) cmd;
1057 syscallarg(netbsd32_voidp) arg;
1058 } */
1059 struct sys_fcntl_args bsd_ua;
1060 uintptr_t flg;
1061 int n, ret;
1062
1063 SCARG(&bsd_ua, fd) = SCARG(uap, fd);
1064 SCARG(&bsd_ua, cmd) = SCARG(uap, cmd);
1065 SCARG(&bsd_ua, arg) = SCARG_P32(uap, arg);
1066
1067 switch (SCARG(uap, cmd)) {
1068 case F_SETFL:
1069 flg = (intptr_t)SCARG_P32(uap, arg);
1070 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1071 while (--n >= 0) {
1072 if (flg & sunfcntl_flgtab[n].sun_flg) {
1073 flg &= ~sunfcntl_flgtab[n].sun_flg;
1074 flg |= sunfcntl_flgtab[n].bsd_flg;
1075 }
1076 }
1077 SCARG(&bsd_ua, arg) = (void *)flg;
1078 break;
1079
1080 case F_GETLK:
1081 case F_SETLK:
1082 case F_SETLKW:
1083 {
1084 int error;
1085 struct sunos_flock ifl;
1086 struct flock fl;
1087
1088 error = copyin(SCARG_P32(uap, arg), &ifl, sizeof ifl);
1089 if (error)
1090 return error;
1091 sunos_to_bsd_flock(&ifl, &fl);
1092
1093 error = do_fcntl_lock(SCARG(uap, fd), SCARG(uap, cmd),
1094 &fl);
1095 if (error || SCARG(uap, cmd) != F_GETLK)
1096 return error;
1097
1098 bsd_to_sunos_flock(&fl, &ifl);
1099 return copyout(&ifl, SCARG_P32(uap, arg), sizeof ifl);
1100 }
1101 break;
1102 case SUN_F_RGETLK:
1103 case SUN_F_RSETLK:
1104 case SUN_F_CNVT:
1105 case SUN_F_RSETLKW:
1106 return EOPNOTSUPP;
1107 }
1108
1109 ret = sys_fcntl(l, &bsd_ua, retval);
1110 if (ret != 0)
1111 return ret;
1112
1113 switch (SCARG(uap, cmd)) {
1114 case F_GETFL:
1115 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1116 ret = *retval;
1117 while (--n >= 0) {
1118 if (ret & sunfcntl_flgtab[n].bsd_flg) {
1119 ret &= ~sunfcntl_flgtab[n].bsd_flg;
1120 ret |= sunfcntl_flgtab[n].sun_flg;
1121 }
1122 }
1123 *retval = ret;
1124 break;
1125 }
1126
1127 return 0;
1128 }
1129