1 /* $NetBSD: sunos32_misc.c,v 1.38 2006/06/26 21:23:58 mrg Exp $ */ 2 /* from :NetBSD: sunos_misc.c,v 1.107 2000/12/01 19:25:10 jdolecek 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 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1992, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * This software was developed by the Computer Systems Engineering group 37 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 38 * contributed to Berkeley. 39 * 40 * All advertising materials mentioning features or use of this software 41 * must display the following acknowledgement: 42 * This product includes software developed by the University of 43 * California, Lawrence Berkeley Laboratory. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. Neither the name of the University nor the names of its contributors 54 * may be used to endorse or promote products derived from this software 55 * without specific prior written permission. 56 * 57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * SUCH DAMAGE. 68 * 69 * @(#)sunos_misc.c 8.1 (Berkeley) 6/18/93 70 * 71 * Header: sunos_misc.c,v 1.16 93/04/07 02:46:27 torek Exp 72 */ 73 74 /* 75 * SunOS compatibility module, 64-bit kernel version 76 * 77 * SunOS system calls that are implemented differently in BSD are 78 * handled here. 79 */ 80 81 #include <sys/cdefs.h> 82 __KERNEL_RCSID(0, "$NetBSD: sunos32_misc.c,v 1.38 2006/06/26 21:23:58 mrg Exp $"); 83 84 #define COMPAT_SUNOS 1 85 86 #if defined(_KERNEL_OPT) 87 #include "opt_nfsserver.h" 88 #include "opt_compat_43.h" 89 #include "opt_compat_netbsd.h" 90 #include "fs_nfs.h" 91 #endif 92 93 #include <sys/param.h> 94 #include <sys/systm.h> 95 #include <sys/namei.h> 96 #include <sys/proc.h> 97 #include <sys/dirent.h> 98 #include <sys/file.h> 99 #include <sys/stat.h> 100 #include <sys/filedesc.h> 101 #include <sys/ioctl.h> 102 #include <sys/kernel.h> 103 #include <sys/reboot.h> 104 #include <sys/malloc.h> 105 #include <sys/mbuf.h> 106 #include <sys/mman.h> 107 #include <sys/mount.h> 108 #include <sys/ptrace.h> 109 #include <sys/resource.h> 110 #include <sys/resourcevar.h> 111 #include <sys/signal.h> 112 #include <sys/signalvar.h> 113 #include <sys/socket.h> 114 #include <sys/tty.h> 115 #include <sys/vnode.h> 116 #include <sys/uio.h> 117 #include <sys/wait.h> 118 #include <sys/utsname.h> 119 #include <sys/unistd.h> 120 #include <sys/sa.h> 121 #include <sys/syscallargs.h> 122 #include <sys/conf.h> 123 #include <sys/socketvar.h> 124 #include <sys/exec.h> 125 #include <sys/swap.h> 126 #include <sys/kauth.h> 127 128 #include <compat/netbsd32/netbsd32.h> 129 #include <compat/netbsd32/netbsd32_syscallargs.h> 130 #include <compat/sunos32/sunos32.h> 131 #include <compat/sunos32/sunos32_dirent.h> 132 #include <compat/sunos32/sunos32_syscallargs.h> 133 #include <compat/common/compat_util.h> 134 135 #include <netinet/in.h> 136 137 #include <miscfs/specfs/specdev.h> 138 139 #include <nfs/rpcv2.h> 140 #include <nfs/nfsproto.h> 141 #include <nfs/nfs.h> 142 #include <nfs/nfsmount.h> 143 144 static void sunos32_sigvec_to_sigaction(const struct netbsd32_sigvec *, struct sigaction *); 145 static void sunos32_sigvec_from_sigaction(struct netbsd32_sigvec *, const struct sigaction *); 146 147 static int sunstatfs __P((struct statvfs *, caddr_t)); 148 149 static void 150 sunos32_sigvec_to_sigaction(sv, sa) 151 const struct netbsd32_sigvec *sv; 152 struct sigaction *sa; 153 { 154 /*XXX*/ extern void compat_43_sigmask_to_sigset __P((const int *, sigset_t *)); 155 156 sa->sa_handler = (void *)(u_long)sv->sv_handler; 157 compat_43_sigmask_to_sigset(&sv->sv_mask, &sa->sa_mask); 158 sa->sa_flags = sv->sv_flags ^ SA_RESTART; 159 } 160 161 static 162 void sunos32_sigvec_from_sigaction(sv, sa) 163 struct netbsd32_sigvec *sv; 164 const struct sigaction *sa; 165 { 166 /*XXX*/ extern void compat_43_sigset_to_sigmask __P((const sigset_t *, int *)); 167 168 sv->sv_handler = (netbsd32_voidp)(u_long)sa->sa_handler; 169 compat_43_sigset_to_sigmask(&sa->sa_mask, &sv->sv_mask); 170 sv->sv_flags = sa->sa_flags ^ SA_RESTART; 171 } 172 173 int 174 sunos32_sys_stime(l, v, retval) 175 struct lwp *l; 176 void *v; 177 register_t *retval; 178 { 179 struct sunos32_sys_stime_args /* { 180 syscallarg(sunos32_time_tp) tp; 181 } */ *uap = v; 182 struct proc *p = l->l_proc; 183 struct sys_settimeofday_args ap; 184 caddr_t sg = stackgap_init(p, 0); 185 struct netbsd32_timeval ntv; 186 struct timeval tv, *sgtvp; 187 int error; 188 189 error = copyin((caddr_t)(u_long)SCARG(uap, tp), &ntv.tv_sec, sizeof(ntv.tv_sec)); 190 if (error) 191 return error; 192 tv.tv_sec = ntv.tv_sec; 193 tv.tv_usec = 0; 194 195 SCARG(&ap, tv) = sgtvp = stackgap_alloc(p, &sg, sizeof(struct timeval)); 196 SCARG(&ap, tzp) = NULL; 197 198 error = copyout(&tv, sgtvp, sizeof(struct timeval)); 199 if (error) 200 return error; 201 202 return sys_settimeofday(l, &ap, retval); 203 } 204 205 int 206 sunos32_sys_wait4(l, v, retval) 207 struct lwp *l; 208 void *v; 209 register_t *retval; 210 { 211 struct sunos32_sys_wait4_args /* { 212 syscallarg(int) pid; 213 syscallarg(netbsd32_intp) status; 214 syscallarg(int) options; 215 syscallarg(netbsd32_rusagep_t) rusage; 216 } */ *uap = v; 217 218 if (SCARG(uap, pid) == 0) 219 SCARG(uap, pid) = WAIT_ANY; 220 return (netbsd32_wait4(l, uap, retval)); 221 } 222 223 int 224 sunos32_sys_creat(l, v, retval) 225 struct lwp *l; 226 void *v; 227 register_t *retval; 228 { 229 struct sunos32_sys_creat_args /* { 230 syscallarg(const netbsd32_charp) path; 231 syscallarg(int) mode; 232 } */ *uap = v; 233 struct proc *p = l->l_proc; 234 struct sys_open_args ua; 235 caddr_t sg = stackgap_init(p, 0); 236 237 SUNOS32TOP_UAP(path, const char); 238 SCARG(&ua, flags) = O_WRONLY | O_CREAT | O_TRUNC; 239 SUNOS32TO64_UAP(mode); 240 241 SUNOS32_CHECK_ALT_CREAT(l, &sg, SCARG(&ua, path)); 242 243 return (sys_open(l, &ua, retval)); 244 } 245 246 int 247 sunos32_sys_access(l, v, retval) 248 struct lwp *l; 249 void *v; 250 register_t *retval; 251 { 252 struct sunos32_sys_access_args /* { 253 syscallarg(const netbsd32_charp) path; 254 syscallarg(int) flags; 255 } */ *uap = v; 256 struct proc *p = l->l_proc; 257 struct sys_access_args ua; 258 caddr_t sg = stackgap_init(p, 0); 259 260 SUNOS32TOP_UAP(path, const char); 261 SUNOS32TO64_UAP(flags); 262 SUNOS32_CHECK_ALT_EXIST(l, &sg, SCARG(&ua, path)); 263 264 return (sys_access(l, &ua, retval)); 265 } 266 267 static inline void sunos32_from___stat13 __P((struct stat *, struct netbsd32_stat43 *)); 268 269 static inline void 270 sunos32_from___stat13(sbp, sb32p) 271 struct stat *sbp; 272 struct netbsd32_stat43 *sb32p; 273 { 274 sb32p->st_dev = sbp->st_dev; 275 sb32p->st_ino = sbp->st_ino; 276 sb32p->st_mode = sbp->st_mode; 277 sb32p->st_nlink = sbp->st_nlink; 278 sb32p->st_uid = sbp->st_uid; 279 sb32p->st_gid = sbp->st_gid; 280 sb32p->st_rdev = sbp->st_rdev; 281 if (sbp->st_size < (quad_t)1 << 32) 282 sb32p->st_size = sbp->st_size; 283 else 284 sb32p->st_size = -2; 285 sb32p->st_atimespec.tv_sec = (netbsd32_time_t)sbp->st_atimespec.tv_sec; 286 sb32p->st_atimespec.tv_nsec = (netbsd32_long)sbp->st_atimespec.tv_nsec; 287 sb32p->st_mtimespec.tv_sec = (netbsd32_time_t)sbp->st_mtimespec.tv_sec; 288 sb32p->st_mtimespec.tv_nsec = (netbsd32_long)sbp->st_mtimespec.tv_nsec; 289 sb32p->st_ctimespec.tv_sec = (netbsd32_time_t)sbp->st_ctimespec.tv_sec; 290 sb32p->st_ctimespec.tv_nsec = (netbsd32_long)sbp->st_ctimespec.tv_nsec; 291 sb32p->st_blksize = sbp->st_blksize; 292 sb32p->st_blocks = sbp->st_blocks; 293 sb32p->st_flags = sbp->st_flags; 294 sb32p->st_gen = sbp->st_gen; 295 } 296 297 298 int 299 sunos32_sys_stat(l, v, retval) 300 struct lwp *l; 301 void *v; 302 register_t *retval; 303 { 304 struct sunos32_sys_stat_args /* { 305 syscallarg(const netbsd32_charp) path; 306 syscallarg(netbsd32_stat43p_t) ub; 307 } */ *uap = v; 308 struct proc *p = l->l_proc; 309 struct netbsd32_stat43 sb32; 310 struct stat sb; 311 struct nameidata nd; 312 caddr_t sg; 313 const char *path; 314 int error; 315 316 path = (char *)(u_long)SCARG(uap, path); 317 sg = stackgap_init(p, 0); 318 SUNOS32_CHECK_ALT_EXIST(l, &sg, path); 319 320 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, path, l); 321 if ((error = namei(&nd)) != 0) 322 return (error); 323 error = vn_stat(nd.ni_vp, &sb, l); 324 vput(nd.ni_vp); 325 if (error) 326 return (error); 327 sunos32_from___stat13(&sb, &sb32); 328 error = copyout((caddr_t)&sb32, (caddr_t)(u_long)SCARG(uap, ub), sizeof (sb32)); 329 return (error); 330 } 331 332 int 333 sunos32_sys_lstat(l, v, retval) 334 struct lwp *l; 335 void *v; 336 register_t *retval; 337 { 338 struct sunos32_sys_lstat_args /* { 339 syscallarg(const netbsd32_charp) path; 340 syscallarg(netbsd32_stat43p_t) ub; 341 } */ *uap = v; 342 struct vnode *vp, *dvp; 343 struct proc *p = l->l_proc; 344 struct stat sb, sb1; 345 struct netbsd32_stat43 sb32; 346 int error; 347 struct nameidata nd; 348 int ndflags; 349 const char *path; 350 caddr_t sg; 351 352 path = (char *)(u_long)SCARG(uap, path); 353 sg = stackgap_init(p, 0); 354 SUNOS32_CHECK_ALT_EXIST(l, &sg, path); 355 356 ndflags = NOFOLLOW | LOCKLEAF | LOCKPARENT; 357 again: 358 NDINIT(&nd, LOOKUP, ndflags, UIO_USERSPACE, path, l); 359 if ((error = namei(&nd))) { 360 if (error == EISDIR && (ndflags & LOCKPARENT) != 0) { 361 /* 362 * Should only happen on '/'. Retry without LOCKPARENT; 363 * this is safe since the vnode won't be a VLNK. 364 */ 365 ndflags &= ~LOCKPARENT; 366 goto again; 367 } 368 return (error); 369 } 370 /* 371 * For symbolic links, always return the attributes of its 372 * containing directory, except for mode, size, and links. 373 */ 374 vp = nd.ni_vp; 375 dvp = nd.ni_dvp; 376 if (vp->v_type != VLNK) { 377 if ((ndflags & LOCKPARENT) != 0) { 378 if (dvp == vp) 379 vrele(dvp); 380 else 381 vput(dvp); 382 } 383 error = vn_stat(vp, &sb, l); 384 vput(vp); 385 if (error) 386 return (error); 387 } else { 388 error = vn_stat(dvp, &sb, l); 389 vput(dvp); 390 if (error) { 391 vput(vp); 392 return (error); 393 } 394 error = vn_stat(vp, &sb1, l); 395 vput(vp); 396 if (error) 397 return (error); 398 sb.st_mode &= ~S_IFDIR; 399 sb.st_mode |= S_IFLNK; 400 sb.st_nlink = sb1.st_nlink; 401 sb.st_size = sb1.st_size; 402 sb.st_blocks = sb1.st_blocks; 403 } 404 sunos32_from___stat13(&sb, &sb32); 405 error = copyout((caddr_t)&sb32, (caddr_t)(u_long)SCARG(uap, ub), sizeof (sb32)); 406 return (error); 407 } 408 409 static int 410 sunos32_execve_fetch_element(char * const *array, size_t index, char **value) 411 { 412 int error; 413 netbsd32_charp const *a32 = (void const *)array; 414 netbsd32_charp e; 415 416 error = copyin(a32 + index, &e, sizeof(e)); 417 if (error) 418 return error; 419 *value = (char *)(u_long)(u_int)e; 420 return 0; 421 } 422 423 int 424 sunos32_sys_execv(l, v, retval) 425 struct lwp *l; 426 void *v; 427 register_t *retval; 428 { 429 struct sunos32_sys_execv_args /* { 430 syscallarg(const char *) path; 431 syscallarg(char **) argv; 432 } */ *uap = v; 433 struct proc *p = l->l_proc; 434 const char *path = (const char *)(u_long)(u_int)SCARG(uap, path); 435 caddr_t sg; 436 437 sg = stackgap_init(p, 0); 438 SUNOS32_CHECK_ALT_EXIST(l, &sg, path); 439 440 return execve1(l, path, (char **)(u_long)(u_int)SCARG(uap, argp), NULL, 441 sunos32_execve_fetch_element); 442 } 443 444 int 445 sunos32_sys_execve(l, v, retval) 446 struct lwp *l; 447 void *v; 448 register_t *retval; 449 { 450 struct sunos32_sys_execve_args /* { 451 syscallarg(const char *) path; 452 syscallarg(char **) argv; 453 syscallarg(char **) envp; 454 } */ *uap = v; 455 struct proc *p = l->l_proc; 456 const char *path = (const char *)(u_long)(u_int)SCARG(uap, path); 457 caddr_t sg; 458 459 sg = stackgap_init(p, 0); 460 SUNOS32_CHECK_ALT_EXIST(l, &sg, path); 461 462 return execve1(l, path, (char **)(u_long)(u_int)SCARG(uap, argp), 463 (char **)(u_long)(u_int)SCARG(uap, envp), 464 sunos32_execve_fetch_element); 465 } 466 467 int 468 sunos32_sys_omsync(l, v, retval) 469 struct lwp *l; 470 void *v; 471 register_t *retval; 472 { 473 struct sunos32_sys_omsync_args /* { 474 syscallarg(netbsd32_caddr_t) addr; 475 syscallarg(netbsd32_size_t) len; 476 syscallarg(int) flags; 477 } */ *uap = v; 478 struct netbsd32___msync13_args ouap; 479 480 SCARG(&ouap, addr) = SCARG(uap, addr); 481 SCARG(&ouap, len) = SCARG(uap, len); 482 SCARG(&ouap, flags) = SCARG(uap, flags); 483 484 return (netbsd32___msync13(l, &ouap, retval)); 485 } 486 487 int 488 sunos32_sys_unmount(l, v, retval) 489 struct lwp *l; 490 void *v; 491 register_t *retval; 492 { 493 struct sunos32_sys_unmount_args /* { 494 syscallarg(netbsd32_charp) path; 495 } */ *uap = v; 496 struct sys_unmount_args ua; 497 498 SUNOS32TOP_UAP(path, const char); 499 SCARG(&ua, flags) = 0; 500 501 return (sys_unmount(l, &ua, retval)); 502 } 503 504 /* 505 * Conversion table for SunOS NFS mount flags. 506 */ 507 static struct { 508 int sun_flg; 509 int bsd_flg; 510 } sunnfs_flgtab[] = { 511 { SUNNFS_SOFT, NFSMNT_SOFT }, 512 { SUNNFS_WSIZE, NFSMNT_WSIZE }, 513 { SUNNFS_RSIZE, NFSMNT_RSIZE }, 514 { SUNNFS_TIMEO, NFSMNT_TIMEO }, 515 { SUNNFS_RETRANS, NFSMNT_RETRANS }, 516 { SUNNFS_HOSTNAME, 0 }, /* Ignored */ 517 { SUNNFS_INT, NFSMNT_INT }, 518 { SUNNFS_NOAC, 0 }, /* Ignored */ 519 { SUNNFS_ACREGMIN, 0 }, /* Ignored */ 520 { SUNNFS_ACREGMAX, 0 }, /* Ignored */ 521 { SUNNFS_ACDIRMIN, 0 }, /* Ignored */ 522 { SUNNFS_ACDIRMAX, 0 }, /* Ignored */ 523 { SUNNFS_SECURE, 0 }, /* Ignored */ 524 { SUNNFS_NOCTO, 0 }, /* Ignored */ 525 { SUNNFS_POSIX, 0 } /* Ignored */ 526 }; 527 528 int 529 sunos32_sys_mount(l, v, retval) 530 struct lwp *l; 531 void *v; 532 register_t *retval; 533 { 534 struct sunos32_sys_mount_args /* { 535 syscallarg(netbsd32_charp) type; 536 syscallarg(netbsd32_charp) path; 537 syscallarg(int) flags; 538 syscallarg(netbsd32_caddr_t) data; 539 } */ *uap = v; 540 struct proc *p = l->l_proc; 541 struct sys_mount_args ua; 542 int oflags = SCARG(uap, flags), nflags, error; 543 char fsname[MFSNAMELEN]; 544 caddr_t sg = stackgap_init(p, 0); 545 546 if (oflags & (SUNM_NOSUB | SUNM_SYS5)) 547 return (EINVAL); 548 if ((oflags & SUNM_NEWTYPE) == 0) 549 return (EINVAL); 550 nflags = 0; 551 if (oflags & SUNM_RDONLY) 552 nflags |= MNT_RDONLY; 553 if (oflags & SUNM_NOSUID) 554 nflags |= MNT_NOSUID; 555 if (oflags & SUNM_REMOUNT) 556 nflags |= MNT_UPDATE; 557 SCARG(uap, flags) = nflags; 558 559 error = copyinstr((caddr_t)(u_long)SCARG(uap, type), fsname, 560 sizeof fsname, (size_t *)0); 561 if (error) 562 return (error); 563 564 if (strncmp(fsname, "4.2", sizeof fsname) == 0) { 565 SCARG(uap, type) = (netbsd32_charp)(u_long)stackgap_alloc(p, &sg, sizeof("ffs")); 566 error = copyout("ffs", (caddr_t)(u_long)SCARG(uap, type), sizeof("ffs")); 567 if (error) 568 return (error); 569 } else if (strncmp(fsname, "nfs", sizeof fsname) == 0) { 570 struct sunos_nfs_args sna; 571 struct sockaddr_in sain; 572 struct nfs_args na; /* XXX */ 573 struct sockaddr sa; 574 int n; 575 576 error = copyin((caddr_t)(u_long)SCARG(uap, data), &sna, sizeof sna); 577 if (error) 578 return (error); 579 error = copyin(sna.addr, &sain, sizeof sain); 580 if (error) 581 return (error); 582 memcpy(&sa, &sain, sizeof sa); 583 sa.sa_len = sizeof(sain); 584 SCARG(uap, data) = (netbsd32_charp)(u_long)stackgap_alloc(p, &sg, sizeof(na)); 585 na.version = NFS_ARGSVERSION; 586 na.addr = stackgap_alloc(p, &sg, sizeof(struct sockaddr)); 587 na.addrlen = sizeof(struct sockaddr); 588 na.sotype = SOCK_DGRAM; 589 na.proto = IPPROTO_UDP; 590 na.fh = (void *)sna.fh; 591 na.fhsize = NFSX_V2FH; 592 na.flags = 0; 593 n = sizeof(sunnfs_flgtab) / sizeof(sunnfs_flgtab[0]); 594 while (--n >= 0) 595 if (sna.flags & sunnfs_flgtab[n].sun_flg) 596 na.flags |= sunnfs_flgtab[n].bsd_flg; 597 na.wsize = sna.wsize; 598 na.rsize = sna.rsize; 599 if (na.flags & NFSMNT_RSIZE) { 600 na.flags |= NFSMNT_READDIRSIZE; 601 na.readdirsize = na.rsize; 602 } 603 na.timeo = sna.timeo; 604 na.retrans = sna.retrans; 605 na.hostname = (char *)(u_long)sna.hostname; 606 607 error = copyout(&sa, na.addr, sizeof sa); 608 if (error) 609 return (error); 610 error = copyout(&na, (caddr_t)(u_long)SCARG(uap, data), sizeof na); 611 if (error) 612 return (error); 613 } 614 SUNOS32TOP_UAP(type, const char); 615 SUNOS32TOP_UAP(path, const char); 616 SUNOS32TO64_UAP(flags); 617 SUNOS32TOP_UAP(data, void); 618 return (sys_mount(l, &ua, retval)); 619 } 620 621 #if defined(NFS) 622 int 623 async_daemon(l, v, retval) 624 struct lwp *l; 625 void *v; 626 register_t *retval; 627 { 628 struct netbsd32_nfssvc_args ouap; 629 630 SCARG(&ouap, flag) = NFSSVC_BIOD; 631 SCARG(&ouap, argp) = 0; 632 633 return (netbsd32_nfssvc(l, &ouap, retval)); 634 } 635 #endif /* NFS */ 636 637 void native_to_sunos_sigset __P((const sigset_t *, int *)); 638 void sunos_to_native_sigset __P((const int, sigset_t *)); 639 640 inline void 641 native_to_sunos_sigset(ss, mask) 642 const sigset_t *ss; 643 int *mask; 644 { 645 *mask = ss->__bits[0]; 646 } 647 648 inline void 649 sunos_to_native_sigset(mask, ss) 650 const int mask; 651 sigset_t *ss; 652 { 653 654 ss->__bits[0] = mask; 655 ss->__bits[1] = 0; 656 ss->__bits[2] = 0; 657 ss->__bits[3] = 0; 658 } 659 660 int 661 sunos32_sys_sigpending(l, v, retval) 662 struct lwp *l; 663 void *v; 664 register_t *retval; 665 { 666 struct sunos32_sys_sigpending_args /* { 667 syscallarg(netbsd32_intp) mask; 668 } */ *uap = v; 669 struct proc *p = l->l_proc; 670 sigset_t ss; 671 int mask; 672 673 sigpending1(p, &ss); 674 native_to_sunos_sigset(&ss, &mask); 675 676 return (copyout((caddr_t)(u_long)&mask, (caddr_t)(u_long)SCARG(uap, mask), sizeof(int))); 677 } 678 679 int 680 sunos32_sys_sigsuspend(l, v, retval) 681 struct lwp *l; 682 void *v; 683 register_t *retval; 684 { 685 struct sunos32_sys_sigsuspend_args /* { 686 syscallarg(int) mask; 687 } */ *uap = v; 688 int mask; 689 struct proc *p = l->l_proc; 690 sigset_t ss; 691 692 mask = SCARG(uap, mask); 693 sunos_to_native_sigset(mask, &ss); 694 return (sigsuspend1(p, &ss)); 695 } 696 697 /* 698 * Read Sun-style directory entries. We suck them into kernel space so 699 * that they can be massaged before being copied out to user code. Like 700 * SunOS, we squish out `empty' entries. 701 * 702 * This is quite ugly, but what do you expect from compatibility code? 703 */ 704 int 705 sunos32_sys_getdents(l, v, retval) 706 struct lwp *l; 707 void *v; 708 register_t *retval; 709 { 710 struct sunos32_sys_getdents_args /* { 711 syscallarg(int) fd; 712 syscallarg(netbsd32_charp) buf; 713 syscallarg(int) nbytes; 714 } */ *uap = v; 715 struct proc *p = l->l_proc; 716 struct dirent *bdp; 717 struct vnode *vp; 718 caddr_t inp, sbuf; /* BSD-format */ 719 int len, reclen; /* BSD-format */ 720 caddr_t outp; /* Sun-format */ 721 int resid, sunos_reclen;/* Sun-format */ 722 struct file *fp; 723 struct uio auio; 724 struct iovec aiov; 725 struct sunos32_dirent idb; 726 off_t off; /* true file offset */ 727 int buflen, error, eofflag; 728 off_t *cookiebuf, *cookie; 729 int ncookies; 730 731 /* getvnode() will use the descriptor for us */ 732 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 733 return (error); 734 735 if ((fp->f_flag & FREAD) == 0) { 736 error = EBADF; 737 goto out1; 738 } 739 740 vp = (struct vnode *)fp->f_data; 741 if (vp->v_type != VDIR) { 742 error = EINVAL; 743 goto out1; 744 } 745 746 buflen = min(MAXBSIZE, SCARG(uap, nbytes)); 747 sbuf = malloc(buflen, M_TEMP, M_WAITOK); 748 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 749 off = fp->f_offset; 750 again: 751 aiov.iov_base = sbuf; 752 aiov.iov_len = buflen; 753 auio.uio_iov = &aiov; 754 auio.uio_iovcnt = 1; 755 auio.uio_rw = UIO_READ; 756 auio.uio_resid = buflen; 757 auio.uio_offset = off; 758 UIO_SETUP_SYSSPACE(&auio); 759 /* 760 * First we read into the malloc'ed buffer, then 761 * we massage it into user space, one record at a time. 762 */ 763 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf, 764 &ncookies); 765 if (error) 766 goto out; 767 768 inp = sbuf; 769 outp = (caddr_t)(u_long)SCARG(uap, buf); 770 resid = SCARG(uap, nbytes); 771 if ((len = buflen - auio.uio_resid) == 0) 772 goto eof; 773 774 for (cookie = cookiebuf; len > 0; len -= reclen) { 775 bdp = (struct dirent *)inp; 776 reclen = bdp->d_reclen; 777 if (reclen & 3) 778 panic("sunos_getdents"); 779 if (cookie && (*cookie >> 32) != 0) { 780 compat_offseterr(vp, "sunos_getdents"); 781 error = EINVAL; 782 goto out; 783 } 784 if (bdp->d_fileno == 0) { 785 inp += reclen; /* it is a hole; squish it out */ 786 if (cookie) 787 off = *cookie++; 788 else 789 off += reclen; 790 continue; 791 } 792 sunos_reclen = SUNOS32_RECLEN(&idb, bdp->d_namlen); 793 if (reclen > len || resid < sunos_reclen) { 794 /* entry too big for buffer, so just stop */ 795 outp++; 796 break; 797 } 798 if (cookie) 799 off = *cookie++; /* each entry points to next */ 800 else 801 off += reclen; 802 /* 803 * Massage in place to make a Sun-shaped dirent (otherwise 804 * we have to worry about touching user memory outside of 805 * the copyout() call). 806 */ 807 idb.d_fileno = bdp->d_fileno; 808 idb.d_off = off; 809 idb.d_reclen = sunos_reclen; 810 idb.d_namlen = bdp->d_namlen; 811 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name)); 812 if ((error = copyout((caddr_t)&idb, outp, sunos_reclen)) != 0) 813 goto out; 814 /* advance past this real entry */ 815 inp += reclen; 816 /* advance output past Sun-shaped entry */ 817 outp += sunos_reclen; 818 resid -= sunos_reclen; 819 } 820 821 /* if we squished out the whole block, try again */ 822 if (outp == (caddr_t)(u_long)SCARG(uap, buf)) 823 goto again; 824 fp->f_offset = off; /* update the vnode offset */ 825 826 eof: 827 *retval = SCARG(uap, nbytes) - resid; 828 out: 829 VOP_UNLOCK(vp, 0); 830 free(cookiebuf, M_TEMP); 831 free(sbuf, M_TEMP); 832 out1: 833 FILE_UNUSE(fp, l); 834 return (error); 835 } 836 837 #define SUNOS32__MAP_NEW 0x80000000 /* if not, old mmap & cannot handle */ 838 839 int 840 sunos32_sys_mmap(l, v, retval) 841 struct lwp *l; 842 void *v; 843 register_t *retval; 844 { 845 struct sunos32_sys_mmap_args /* { 846 syscallarg(netbsd32_voidp) addr; 847 syscallarg(netbsd32_size_t) len; 848 syscallarg(int) prot; 849 syscallarg(int) flags; 850 syscallarg(int) fd; 851 syscallarg(netbsd32_long) pos; 852 } */ *uap = v; 853 struct sys_mmap_args ua; 854 int error; 855 856 /* 857 * Verify the arguments. 858 */ 859 if (SCARG(uap, prot) & ~(PROT_READ|PROT_WRITE|PROT_EXEC)) 860 return (EINVAL); /* XXX still needed? */ 861 862 if ((SCARG(uap, flags) & SUNOS32__MAP_NEW) == 0) 863 return (EINVAL); 864 865 SUNOS32TOP_UAP(addr, void); 866 SUNOS32TOX_UAP(len, size_t); 867 SUNOS32TO64_UAP(prot); 868 SCARG(&ua, flags) = SCARG(uap, flags) & ~SUNOS32__MAP_NEW; 869 SUNOS32TO64_UAP(fd); 870 SCARG(&ua, pad) = 0; 871 SUNOS32TOX_UAP(pos, off_t); 872 873 error = sys_mmap(l, &ua, retval); 874 if ((u_long)*retval > (u_long)UINT_MAX) { 875 printf("sunos32_mmap: retval out of range: 0x%lx", 876 (u_long)*retval); 877 /* Should try to recover and return an error here. */ 878 } 879 return (error); 880 } 881 882 #define MC_SYNC 1 883 #define MC_LOCK 2 884 #define MC_UNLOCK 3 885 #define MC_ADVISE 4 886 #define MC_LOCKAS 5 887 #define MC_UNLOCKAS 6 888 889 int 890 sunos32_sys_mctl(l, v, retval) 891 struct lwp *l; 892 void *v; 893 register_t *retval; 894 { 895 struct sunos32_sys_mctl_args /* { 896 syscallarg(netbsd32_voidp) addr; 897 syscallarg(int) len; 898 syscallarg(int) func; 899 syscallarg(netbsd32_voidp) arg; 900 } */ *uap = v; 901 902 switch (SCARG(uap, func)) { 903 case MC_ADVISE: /* ignore for now */ 904 return (0); 905 case MC_SYNC: /* translate to msync */ 906 return (netbsd32___msync13(l, uap, retval)); 907 default: 908 return (EINVAL); 909 } 910 } 911 912 int 913 sunos32_sys_setsockopt(l, v, retval) 914 struct lwp *l; 915 void *v; 916 register_t *retval; 917 { 918 struct sunos32_sys_setsockopt_args /* { 919 syscallarg(int) s; 920 syscallarg(int) level; 921 syscallarg(int) name; 922 syscallarg(netbsd32_caddr_t) val; 923 syscallarg(int) valsize; 924 } */ *uap = v; 925 struct proc *p = l->l_proc; 926 struct file *fp; 927 struct mbuf *m = NULL; 928 int error; 929 930 /* getsock() will use the descriptor for us */ 931 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 932 return (error); 933 #define SO_DONTLINGER (~SO_LINGER) 934 if (SCARG(uap, name) == SO_DONTLINGER) { 935 m = m_get(M_WAIT, MT_SOOPTS); 936 mtod(m, struct linger *)->l_onoff = 0; 937 m->m_len = sizeof(struct linger); 938 error = sosetopt((struct socket *)fp->f_data, SCARG(uap, level), 939 SO_LINGER, m); 940 goto out; 941 } 942 if (SCARG(uap, level) == IPPROTO_IP) { 943 #define SUNOS_IP_MULTICAST_IF 2 944 #define SUNOS_IP_MULTICAST_TTL 3 945 #define SUNOS_IP_MULTICAST_LOOP 4 946 #define SUNOS_IP_ADD_MEMBERSHIP 5 947 #define SUNOS_IP_DROP_MEMBERSHIP 6 948 static const int ipoptxlat[] = { 949 IP_MULTICAST_IF, 950 IP_MULTICAST_TTL, 951 IP_MULTICAST_LOOP, 952 IP_ADD_MEMBERSHIP, 953 IP_DROP_MEMBERSHIP 954 }; 955 if (SCARG(uap, name) >= SUNOS_IP_MULTICAST_IF && 956 SCARG(uap, name) <= SUNOS_IP_DROP_MEMBERSHIP) { 957 SCARG(uap, name) = 958 ipoptxlat[SCARG(uap, name) - SUNOS_IP_MULTICAST_IF]; 959 } 960 } 961 if (SCARG(uap, valsize) > MLEN) { 962 error = EINVAL; 963 goto out; 964 } 965 if (SCARG(uap, val)) { 966 m = m_get(M_WAIT, MT_SOOPTS); 967 error = copyin((caddr_t)(u_long)SCARG(uap, val), mtod(m, caddr_t), 968 (u_int)SCARG(uap, valsize)); 969 if (error) { 970 (void) m_free(m); 971 goto out; 972 } 973 m->m_len = SCARG(uap, valsize); 974 } 975 error = sosetopt((struct socket *)fp->f_data, SCARG(uap, level), 976 SCARG(uap, name), m); 977 out: 978 FILE_UNUSE(fp, l); 979 return (error); 980 } 981 982 static inline int sunos32_sys_socket_common(struct lwp *, register_t *, 983 int type); 984 static inline int 985 sunos32_sys_socket_common(l, retval, type) 986 struct lwp *l; 987 register_t *retval; 988 int type; 989 { 990 struct socket *so; 991 struct proc *p = l->l_proc; 992 struct file *fp; 993 int error, fd; 994 995 /* getsock() will use the descriptor for us */ 996 fd = (int)*retval; 997 if ((error = getsock(p->p_fd, fd, &fp)) == 0) { 998 so = (struct socket *)fp->f_data; 999 if (type == SOCK_DGRAM) 1000 so->so_options |= SO_BROADCAST; 1001 } 1002 FILE_UNUSE(fp, l); 1003 return (error); 1004 } 1005 1006 int 1007 sunos32_sys_socket(l, v, retval) 1008 struct lwp *l; 1009 void *v; 1010 register_t *retval; 1011 { 1012 struct sunos32_sys_socket_args /* { 1013 syscallarg(int) domain; 1014 syscallarg(int) type; 1015 syscallarg(int) protocol; 1016 } */ *uap = v; 1017 int error; 1018 1019 error = netbsd32_sys___socket30(l, v, retval); 1020 if (error) 1021 return (error); 1022 return sunos32_sys_socket_common(l, retval, SCARG(uap, type)); 1023 } 1024 1025 int 1026 sunos32_sys_socketpair(l, v, retval) 1027 struct lwp *l; 1028 void *v; 1029 register_t *retval; 1030 { 1031 struct sunos32_sys_socketpair_args /* { 1032 syscallarg(int) domain; 1033 syscallarg(int) type; 1034 syscallarg(int) protocol; 1035 syscallarg(int *) rsv; 1036 } */ *uap = v; 1037 int error; 1038 1039 error = netbsd32_socketpair(l, v, retval); 1040 if (error) 1041 return (error); 1042 return sunos32_sys_socket_common(l, retval, SCARG(uap, type)); 1043 } 1044 1045 1046 /* 1047 * XXX: This needs cleaning up. 1048 */ 1049 int 1050 sunos32_sys_auditsys(l, v, retval) 1051 struct lwp *l; 1052 void *v; 1053 register_t *retval; 1054 { 1055 return 0; 1056 } 1057 1058 int 1059 sunos32_sys_uname(l, v, retval) 1060 struct lwp *l; 1061 void *v; 1062 register_t *retval; 1063 { 1064 struct sunos32_sys_uname_args /* { 1065 syscallarg(sunos32_utsnamep_t) name; 1066 } */ *uap = v; 1067 struct sunos_utsname sut; 1068 1069 memset(&sut, 0, sizeof(sut)); 1070 1071 memcpy(sut.sysname, ostype, sizeof(sut.sysname) - 1); 1072 memcpy(sut.nodename, hostname, sizeof(sut.nodename)); 1073 sut.nodename[sizeof(sut.nodename)-1] = '\0'; 1074 memcpy(sut.release, osrelease, sizeof(sut.release) - 1); 1075 memcpy(sut.version, "1", sizeof(sut.version) - 1); 1076 memcpy(sut.machine, machine, sizeof(sut.machine) - 1); 1077 1078 return copyout((caddr_t)&sut, (caddr_t)(u_long)SCARG(uap, name), 1079 sizeof(struct sunos_utsname)); 1080 } 1081 1082 int 1083 sunos32_sys_setpgrp(l, v, retval) 1084 struct lwp *l; 1085 void *v; 1086 register_t *retval; 1087 { 1088 struct sunos32_sys_setpgrp_args /* { 1089 syscallarg(int) pid; 1090 syscallarg(int) pgid; 1091 } */ *uap = v; 1092 struct proc *p = l->l_proc; 1093 1094 /* 1095 * difference to our setpgid call is to include backwards 1096 * compatibility to pre-setsid() binaries. Do setsid() 1097 * instead of setpgid() in those cases where the process 1098 * tries to create a new session the old way. 1099 */ 1100 if (!SCARG(uap, pgid) && 1101 (!SCARG(uap, pid) || SCARG(uap, pid) == p->p_pid)) 1102 return sys_setsid(l, uap, retval); 1103 else 1104 return netbsd32_setpgid(l, uap, retval); 1105 } 1106 1107 int 1108 sunos32_sys_open(l, v, retval) 1109 struct lwp *l; 1110 void *v; 1111 register_t *retval; 1112 { 1113 struct sunos32_sys_open_args /* { 1114 syscallarg(const netbsd32_charp) path; 1115 syscallarg(int) flags; 1116 syscallarg(int) mode; 1117 } */ *uap = v; 1118 struct proc *p = l->l_proc; 1119 struct sys_open_args ua; 1120 int lf, r; 1121 int noctty; 1122 int ret; 1123 caddr_t sg = stackgap_init(p, 0); 1124 1125 /* convert mode into NetBSD mode */ 1126 lf = SCARG(uap, flags); 1127 noctty = lf & 0x8000; 1128 r = (lf & (0x0001 | 0x0002 | 0x0008 | 0x0040 | 0x0200 | 0x0400 | 0x0800)); 1129 r |= ((lf & (0x0004 | 0x1000 | 0x4000)) ? O_NONBLOCK : 0); 1130 r |= ((lf & 0x0080) ? O_SHLOCK : 0); 1131 r |= ((lf & 0x0100) ? O_EXLOCK : 0); 1132 r |= ((lf & 0x2000) ? O_FSYNC : 0); 1133 1134 SUNOS32TOP_UAP(path, const char); 1135 SCARG(&ua, flags) = r; 1136 SUNOS32TO64_UAP(mode); 1137 1138 if (r & O_CREAT) 1139 SUNOS32_CHECK_ALT_CREAT(l, &sg, SCARG(&ua, path)); 1140 else 1141 SUNOS32_CHECK_ALT_EXIST(l, &sg, SCARG(&ua, path)); 1142 1143 ret = sys_open(l, &ua, retval); 1144 1145 if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 1146 struct filedesc *fdp = p->p_fd; 1147 struct file *fp; 1148 1149 fp = fd_getfile(fdp, *retval); 1150 1151 /* ignore any error, just give it a try */ 1152 if (fp != NULL && fp->f_type == DTYPE_VNODE) 1153 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t)0, l); 1154 } 1155 return ret; 1156 } 1157 1158 #if defined (NFSSERVER) 1159 int 1160 sunos32_sys_nfssvc(l, v, retval) 1161 struct lwp *l; 1162 void *v; 1163 register_t *retval; 1164 { 1165 #if 0 1166 struct sunos32_sys_nfssvc_args *uap = v; 1167 struct emul *e = p->p_emul; 1168 struct sys_nfssvc_args outuap; 1169 struct sockaddr sa; 1170 int error; 1171 caddr_t sg = stackgap_init(p, 0); 1172 1173 memset(&outuap, 0, sizeof outuap); 1174 SCARG(&outuap, fd) = SCARG(uap, fd); 1175 SCARG(&outuap, mskval) = stackgap_alloc(p, &sg, sizeof(sa)); 1176 SCARG(&outuap, msklen) = sizeof(sa); 1177 SCARG(&outuap, mtchval) = stackgap_alloc(p, &sg, sizeof(sa)); 1178 SCARG(&outuap, mtchlen) = sizeof(sa); 1179 1180 memset(&sa, 0, sizeof sa); 1181 if (error = copyout(&sa, SCARG(&outuap, mskval), SCARG(&outuap, msklen))) 1182 return (error); 1183 if (error = copyout(&sa, SCARG(&outuap, mtchval), SCARG(&outuap, mtchlen))) 1184 return (error); 1185 1186 return nfssvc(l, &outuap, retval); 1187 #else 1188 return (ENOSYS); 1189 #endif 1190 } 1191 #endif /* NFSSERVER */ 1192 1193 int 1194 sunos32_sys_ustat(l, v, retval) 1195 struct lwp *l; 1196 void *v; 1197 register_t *retval; 1198 { 1199 struct sunos32_sys_ustat_args /* { 1200 syscallarg(int) dev; 1201 syscallarg(sunos32_ustatp_t) buf; 1202 } */ *uap = v; 1203 struct sunos_ustat us; 1204 int error; 1205 1206 memset(&us, 0, sizeof us); 1207 1208 /* 1209 * XXX: should set f_tfree and f_tinode at least 1210 * How do we translate dev -> fstat? (and then to sunos_ustat) 1211 */ 1212 1213 if ((error = copyout(&us, (caddr_t)(u_long)SCARG(uap, buf), sizeof us)) != 0) 1214 return (error); 1215 return 0; 1216 } 1217 1218 int 1219 sunos32_sys_quotactl(l, v, retval) 1220 struct lwp *l; 1221 void *v; 1222 register_t *retval; 1223 { 1224 1225 return EINVAL; 1226 } 1227 1228 int 1229 sunos32_sys_vhangup(l, v, retval) 1230 struct lwp *l; 1231 void *v; 1232 register_t *retval; 1233 { 1234 struct proc *p = l->l_proc; 1235 struct session *sp = p->p_session; 1236 1237 if (sp->s_ttyvp == 0) 1238 return 0; 1239 1240 if (sp->s_ttyp && sp->s_ttyp->t_session == sp && sp->s_ttyp->t_pgrp) 1241 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); 1242 1243 (void) ttywait(sp->s_ttyp); 1244 if (sp->s_ttyvp) 1245 VOP_REVOKE(sp->s_ttyvp, REVOKEALL); 1246 if (sp->s_ttyvp) 1247 vrele(sp->s_ttyvp); 1248 sp->s_ttyvp = NULL; 1249 1250 return 0; 1251 } 1252 1253 static int 1254 sunstatfs(sp, sbuf) 1255 struct statvfs *sp; 1256 caddr_t sbuf; 1257 { 1258 struct sunos_statfs ssfs; 1259 1260 memset(&ssfs, 0, sizeof ssfs); 1261 ssfs.f_type = 0; 1262 ssfs.f_bsize = sp->f_bsize; 1263 ssfs.f_blocks = sp->f_blocks; 1264 ssfs.f_bfree = sp->f_bfree; 1265 ssfs.f_bavail = sp->f_bavail; 1266 ssfs.f_files = sp->f_files; 1267 ssfs.f_ffree = sp->f_ffree; 1268 ssfs.f_fsid = sp->f_fsidx; 1269 return copyout((caddr_t)&ssfs, sbuf, sizeof ssfs); 1270 } 1271 1272 int 1273 sunos32_sys_statfs(l, v, retval) 1274 struct lwp *l; 1275 void *v; 1276 register_t *retval; 1277 { 1278 struct sunos32_sys_statfs_args /* { 1279 syscallarg(const netbsd32_charp) path; 1280 syscallarg(sunos32_statfsp_t) buf; 1281 } */ *uap = v; 1282 struct proc *p = l->l_proc; 1283 struct mount *mp; 1284 struct statvfs *sp; 1285 int error; 1286 struct nameidata nd; 1287 struct sys_statvfs1_args ua; 1288 caddr_t sg; 1289 1290 sg = stackgap_init(p, 0); 1291 SUNOS32TOP_UAP(path, const char); 1292 SUNOS32_CHECK_ALT_EXIST(l, &sg, SCARG(&ua, path)); 1293 1294 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(&ua, path), l); 1295 if ((error = namei(&nd)) != 0) 1296 return (error); 1297 mp = nd.ni_vp->v_mount; 1298 sp = &mp->mnt_stat; 1299 vrele(nd.ni_vp); 1300 if ((error = VFS_STATVFS(mp, sp, l)) != 0) 1301 return (error); 1302 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; 1303 return sunstatfs(sp, (caddr_t)(u_long)SCARG(uap, buf)); 1304 } 1305 1306 int 1307 sunos32_sys_fstatfs(l, v, retval) 1308 struct lwp *l; 1309 void *v; 1310 register_t *retval; 1311 { 1312 struct sunos32_sys_fstatfs_args /* { 1313 syscallarg(int) fd; 1314 syscallarg(sunos32_statfsp_t) buf; 1315 } */ *uap = v; 1316 struct proc *p = l->l_proc; 1317 struct file *fp; 1318 struct mount *mp; 1319 struct statvfs *sp; 1320 int error; 1321 1322 /* getvnode() will use the descriptor for us */ 1323 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 1324 return (error); 1325 mp = ((struct vnode *)fp->f_data)->v_mount; 1326 sp = &mp->mnt_stat; 1327 if ((error = VFS_STATVFS(mp, sp, l)) != 0) 1328 goto out; 1329 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; 1330 error = sunstatfs(sp, (caddr_t)(u_long)SCARG(uap, buf)); 1331 out: 1332 FILE_UNUSE(fp, l); 1333 return (error); 1334 } 1335 1336 int 1337 sunos32_sys_exportfs(l, v, retval) 1338 struct lwp *l; 1339 void *v; 1340 register_t *retval; 1341 { 1342 /* 1343 * XXX: should perhaps translate into a mount(2) 1344 * with MOUNT_EXPORT? 1345 */ 1346 return 0; 1347 } 1348 1349 int 1350 sunos32_sys_mknod(l, v, retval) 1351 struct lwp *l; 1352 void *v; 1353 register_t *retval; 1354 { 1355 struct sunos32_sys_mknod_args /* { 1356 syscallarg(const netbsd32_charp) path; 1357 syscallarg(int) mode; 1358 syscallarg(int) dev; 1359 } */ *uap = v; 1360 struct proc *p = l->l_proc; 1361 struct sys_mknod_args ua; 1362 caddr_t sg; 1363 1364 sg = stackgap_init(p, 0); 1365 SUNOS32TOP_UAP(path, const char); 1366 SUNOS32TO64_UAP(mode); 1367 SUNOS32TO64_UAP(dev); 1368 SUNOS32_CHECK_ALT_CREAT(l, &sg, SCARG(&ua, path)); 1369 1370 /* netbsd32_mkfifo/mknod to not do alt checking */ 1371 if (S_ISFIFO(SCARG(uap, mode))) 1372 return netbsd32_mkfifo(l, (struct netbsd32_mkfifo_args *)uap, retval); 1373 1374 return netbsd32_mknod(l, (struct netbsd32_mknod_args *)uap, retval); 1375 } 1376 1377 #define SUNOS_SC_ARG_MAX 1 1378 #define SUNOS_SC_CHILD_MAX 2 1379 #define SUNOS_SC_CLK_TCK 3 1380 #define SUNOS_SC_NGROUPS_MAX 4 1381 #define SUNOS_SC_OPEN_MAX 5 1382 #define SUNOS_SC_JOB_CONTROL 6 1383 #define SUNOS_SC_SAVED_IDS 7 1384 #define SUNOS_SC_VERSION 8 1385 1386 int 1387 sunos32_sys_sysconf(l, v, retval) 1388 struct lwp *l; 1389 void *v; 1390 register_t *retval; 1391 { 1392 struct sunos32_sys_sysconf_args /* { 1393 syscallarg(int) name; 1394 } */ *uap = v; 1395 extern int maxfiles; 1396 1397 switch(SCARG(uap, name)) { 1398 case SUNOS_SC_ARG_MAX: 1399 *retval = ARG_MAX; 1400 break; 1401 case SUNOS_SC_CHILD_MAX: 1402 *retval = maxproc; 1403 break; 1404 case SUNOS_SC_CLK_TCK: 1405 *retval = 60; /* should this be `hz', ie. 100? */ 1406 break; 1407 case SUNOS_SC_NGROUPS_MAX: 1408 *retval = NGROUPS_MAX; 1409 break; 1410 case SUNOS_SC_OPEN_MAX: 1411 *retval = maxfiles; 1412 break; 1413 case SUNOS_SC_JOB_CONTROL: 1414 *retval = 1; 1415 break; 1416 case SUNOS_SC_SAVED_IDS: 1417 #ifdef _POSIX_SAVED_IDS 1418 *retval = 1; 1419 #else 1420 *retval = 0; 1421 #endif 1422 break; 1423 case SUNOS_SC_VERSION: 1424 *retval = 198808; 1425 break; 1426 default: 1427 return EINVAL; 1428 } 1429 return 0; 1430 } 1431 1432 #define SUNOS_RLIMIT_NOFILE 6 /* Other RLIMIT_* are the same */ 1433 #define SUNOS_RLIM_NLIMITS 7 1434 1435 int 1436 sunos32_sys_getrlimit(l, v, retval) 1437 struct lwp *l; 1438 void *v; 1439 register_t *retval; 1440 { 1441 struct sunos32_sys_getrlimit_args /* { 1442 syscallarg(u_int) which; 1443 syscallarg(netbsd32_orlimitp_t) rlp; 1444 } */ *uap = v; 1445 1446 if (SCARG(uap, which) >= SUNOS_RLIM_NLIMITS) 1447 return EINVAL; 1448 1449 if (SCARG(uap, which) == SUNOS_RLIMIT_NOFILE) 1450 SCARG(uap, which) = RLIMIT_NOFILE; 1451 1452 return compat_43_netbsd32_ogetrlimit(l, uap, retval); 1453 } 1454 1455 int 1456 sunos32_sys_setrlimit(l, v, retval) 1457 struct lwp *l; 1458 void *v; 1459 register_t *retval; 1460 { 1461 struct sunos32_sys_setrlimit_args /* { 1462 syscallarg(u_int) which; 1463 syscallarg(netbsd32_orlimitp_t) rlp; 1464 } */ *uap = v; 1465 1466 if (SCARG(uap, which) >= SUNOS_RLIM_NLIMITS) 1467 return EINVAL; 1468 1469 if (SCARG(uap, which) == SUNOS_RLIMIT_NOFILE) 1470 SCARG(uap, which) = RLIMIT_NOFILE; 1471 1472 return compat_43_netbsd32_osetrlimit(l, uap, retval); 1473 } 1474 1475 /* for the m68k machines */ 1476 #ifndef PT_GETFPREGS 1477 #define PT_GETFPREGS -1 1478 #endif 1479 #ifndef PT_SETFPREGS 1480 #define PT_SETFPREGS -1 1481 #endif 1482 1483 static const int sreq2breq[] = { 1484 PT_TRACE_ME, PT_READ_I, PT_READ_D, -1, 1485 PT_WRITE_I, PT_WRITE_D, -1, PT_CONTINUE, 1486 PT_KILL, -1, PT_ATTACH, PT_DETACH, 1487 PT_GETREGS, PT_SETREGS, PT_GETFPREGS, PT_SETFPREGS 1488 }; 1489 static const int nreqs = sizeof(sreq2breq) / sizeof(sreq2breq[0]); 1490 1491 int 1492 sunos32_sys_ptrace(l, v, retval) 1493 struct lwp *l; 1494 void *v; 1495 register_t *retval; 1496 { 1497 struct sunos32_sys_ptrace_args /* { 1498 syscallarg(int) req; 1499 syscallarg(pid_t) pid; 1500 syscallarg(netbsd32_caddr_t) addr; 1501 syscallarg(int) data; 1502 syscallarg(netbsd32_charp) addr2; 1503 } */ *uap = v; 1504 struct netbsd32_ptrace_args pa; 1505 int req; 1506 1507 req = SCARG(uap, req); 1508 1509 if (req < 0 || req >= nreqs) 1510 return (EINVAL); 1511 1512 req = sreq2breq[req]; 1513 if (req == -1) 1514 return (EINVAL); 1515 1516 SCARG(&pa, req) = req; 1517 SCARG(&pa, pid) = (pid_t)SCARG(uap, pid); 1518 SCARG(&pa, addr) = SCARG(uap, addr); 1519 SCARG(&pa, data) = SCARG(uap, data); 1520 1521 return netbsd32_ptrace(l, &pa, retval); 1522 } 1523 1524 /* 1525 * SunOS reboot system call (for compatibility). 1526 * Sun lets you pass in a boot string which the PROM 1527 * saves and provides to the next boot program. 1528 */ 1529 1530 #define SUNOS_RB_ASKNAME 0x001 1531 #define SUNOS_RB_SINGLE 0x002 1532 #define SUNOS_RB_NOSYNC 0x004 1533 #define SUNOS_RB_HALT 0x008 1534 #define SUNOS_RB_DUMP 0x080 1535 #define SUNOS_RB_STRING 0x200 1536 1537 static struct sunos_howto_conv { 1538 int sun_howto; 1539 int bsd_howto; 1540 } sunos_howto_conv[] = { 1541 { SUNOS_RB_ASKNAME, RB_ASKNAME }, 1542 { SUNOS_RB_SINGLE, RB_SINGLE }, 1543 { SUNOS_RB_NOSYNC, RB_NOSYNC }, 1544 { SUNOS_RB_HALT, RB_HALT }, 1545 { SUNOS_RB_DUMP, RB_DUMP }, 1546 { SUNOS_RB_STRING, RB_STRING }, 1547 { 0x000, 0 }, 1548 }; 1549 1550 int 1551 sunos32_sys_reboot(l, v, retval) 1552 struct lwp *l; 1553 void *v; 1554 register_t *retval; 1555 { 1556 struct sunos32_sys_reboot_args /* { 1557 syscallarg(int) howto; 1558 syscallarg(netbsd32_charp) bootstr; 1559 } */ *uap = v; 1560 struct proc *p = l->l_proc; 1561 struct sys_reboot_args ua; 1562 struct sunos_howto_conv *convp; 1563 int error, bsd_howto, sun_howto; 1564 char *bootstr; 1565 1566 if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, &p->p_acflag)) != 0) 1567 return (error); 1568 1569 /* 1570 * Convert howto bits to BSD format. 1571 */ 1572 sun_howto = SCARG(uap, howto); 1573 bsd_howto = 0; 1574 convp = sunos_howto_conv; 1575 while (convp->sun_howto) { 1576 if (sun_howto & convp->sun_howto) 1577 bsd_howto |= convp->bsd_howto; 1578 convp++; 1579 } 1580 1581 /* 1582 * Sun RB_STRING (Get user supplied bootstring.) 1583 * If the machine supports passing a string to the 1584 * next booted kernel. 1585 */ 1586 if (sun_howto & SUNOS_RB_STRING) 1587 bootstr = (char *)(u_long)SCARG(uap, bootstr); 1588 else 1589 bootstr = NULL; 1590 1591 SCARG(&ua, opt) = bsd_howto; 1592 SCARG(&ua, bootstr) = bootstr; 1593 return (sys_reboot(l, &ua, retval)); 1594 } 1595 1596 /* 1597 * Generalized interface signal handler, 4.3-compatible. 1598 */ 1599 /* ARGSUSED */ 1600 int 1601 sunos32_sys_sigvec(l, v, retval) 1602 struct lwp *l; 1603 void *v; 1604 register_t *retval; 1605 { 1606 struct sunos32_sys_sigvec_args /* { 1607 syscallarg(int) signum; 1608 syscallarg(struct sigvec *) nsv; 1609 syscallarg(struct sigvec *) osv; 1610 } */ *uap = v; 1611 struct proc *p = l->l_proc; 1612 struct netbsd32_sigvec sv; 1613 struct sigaction nsa, osa; 1614 int error; 1615 1616 if (SCARG(uap, nsv)) { 1617 error = copyin((caddr_t)(u_long)SCARG(uap, nsv), &sv, sizeof(sv)); 1618 if (error != 0) 1619 return (error); 1620 1621 /* 1622 * SunOS uses the mask 0x0004 as SV_RESETHAND 1623 * meaning: `reset to SIG_DFL on delivery'. 1624 * We support only the bits in: 0xF 1625 * (those bits are the same as ours) 1626 */ 1627 if (sv.sv_flags & ~0xF) 1628 return (EINVAL); 1629 1630 sunos32_sigvec_to_sigaction(&sv, &nsa); 1631 } 1632 error = sigaction1(p, SCARG(uap, signum), 1633 SCARG(uap, nsv) ? &nsa : 0, 1634 SCARG(uap, osv) ? &osa : 0, 1635 NULL, 0); 1636 if (error != 0) 1637 return (error); 1638 1639 if (SCARG(uap, osv)) { 1640 sunos32_sigvec_from_sigaction(&sv, &osa); 1641 error = copyout(&sv, (caddr_t)(u_long)SCARG(uap, osv), sizeof(sv)); 1642 if (error != 0) 1643 return (error); 1644 } 1645 1646 return (0); 1647 } 1648