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 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 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 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 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 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 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 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 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 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