1 /* $NetBSD: sunos32_misc.c,v 1.35 2005/12/24 23:41:33 perry 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.35 2005/12/24 23:41:33 perry 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 127 #include <compat/netbsd32/netbsd32.h> 128 #include <compat/netbsd32/netbsd32_syscallargs.h> 129 #include <compat/sunos32/sunos32.h> 130 #include <compat/sunos32/sunos32_dirent.h> 131 #include <compat/sunos32/sunos32_syscallargs.h> 132 #include <compat/common/compat_util.h> 133 134 #include <netinet/in.h> 135 136 #include <miscfs/specfs/specdev.h> 137 138 #include <nfs/rpcv2.h> 139 #include <nfs/nfsproto.h> 140 #include <nfs/nfs.h> 141 #include <nfs/nfsmount.h> 142 143 static void sunos32_sigvec_to_sigaction(const struct netbsd32_sigvec *, struct sigaction *); 144 static void sunos32_sigvec_from_sigaction(struct netbsd32_sigvec *, const struct sigaction *); 145 146 static int sunstatfs __P((struct statvfs *, caddr_t)); 147 148 static void 149 sunos32_sigvec_to_sigaction(sv, sa) 150 const struct netbsd32_sigvec *sv; 151 struct sigaction *sa; 152 { 153 /*XXX*/ extern void compat_43_sigmask_to_sigset __P((const int *, sigset_t *)); 154 155 sa->sa_handler = (void *)(u_long)sv->sv_handler; 156 compat_43_sigmask_to_sigset(&sv->sv_mask, &sa->sa_mask); 157 sa->sa_flags = sv->sv_flags ^ SA_RESTART; 158 } 159 160 static 161 void sunos32_sigvec_from_sigaction(sv, sa) 162 struct netbsd32_sigvec *sv; 163 const struct sigaction *sa; 164 { 165 /*XXX*/ extern void compat_43_sigset_to_sigmask __P((const sigset_t *, int *)); 166 167 sv->sv_handler = (netbsd32_voidp)(u_long)sa->sa_handler; 168 compat_43_sigset_to_sigmask(&sa->sa_mask, &sv->sv_mask); 169 sv->sv_flags = sa->sa_flags ^ SA_RESTART; 170 } 171 172 int 173 sunos32_sys_stime(l, v, retval) 174 struct lwp *l; 175 void *v; 176 register_t *retval; 177 { 178 struct sunos32_sys_stime_args /* { 179 syscallarg(sunos32_time_tp) tp; 180 } */ *uap = v; 181 struct proc *p = l->l_proc; 182 struct sys_settimeofday_args ap; 183 caddr_t sg = stackgap_init(p, 0); 184 struct netbsd32_timeval ntv; 185 struct timeval tv, *sgtvp; 186 int error; 187 188 error = copyin((caddr_t)(u_long)SCARG(uap, tp), &ntv.tv_sec, sizeof(ntv.tv_sec)); 189 if (error) 190 return error; 191 tv.tv_sec = ntv.tv_sec; 192 tv.tv_usec = 0; 193 194 SCARG(&ap, tv) = sgtvp = stackgap_alloc(p, &sg, sizeof(struct timeval)); 195 SCARG(&ap, tzp) = NULL; 196 197 error = copyout(&tv, sgtvp, sizeof(struct timeval)); 198 if (error) 199 return error; 200 201 return sys_settimeofday(l, &ap, retval); 202 } 203 204 int 205 sunos32_sys_wait4(l, v, retval) 206 struct lwp *l; 207 void *v; 208 register_t *retval; 209 { 210 struct sunos32_sys_wait4_args /* { 211 syscallarg(int) pid; 212 syscallarg(netbsd32_intp) status; 213 syscallarg(int) options; 214 syscallarg(netbsd32_rusagep_t) rusage; 215 } */ *uap = v; 216 217 if (SCARG(uap, pid) == 0) 218 SCARG(uap, pid) = WAIT_ANY; 219 return (netbsd32_wait4(l, uap, retval)); 220 } 221 222 int 223 sunos32_sys_creat(l, v, retval) 224 struct lwp *l; 225 void *v; 226 register_t *retval; 227 { 228 struct sunos32_sys_creat_args /* { 229 syscallarg(const netbsd32_charp) path; 230 syscallarg(int) mode; 231 } */ *uap = v; 232 struct proc *p = l->l_proc; 233 struct sys_open_args ua; 234 caddr_t sg = stackgap_init(p, 0); 235 236 SUNOS32TOP_UAP(path, const char); 237 SCARG(&ua, flags) = O_WRONLY | O_CREAT | O_TRUNC; 238 SUNOS32TO64_UAP(mode); 239 240 SUNOS32_CHECK_ALT_CREAT(l, &sg, SCARG(&ua, path)); 241 242 return (sys_open(l, &ua, retval)); 243 } 244 245 int 246 sunos32_sys_access(l, v, retval) 247 struct lwp *l; 248 void *v; 249 register_t *retval; 250 { 251 struct sunos32_sys_access_args /* { 252 syscallarg(const netbsd32_charp) path; 253 syscallarg(int) flags; 254 } */ *uap = v; 255 struct proc *p = l->l_proc; 256 struct sys_access_args ua; 257 caddr_t sg = stackgap_init(p, 0); 258 259 SUNOS32TOP_UAP(path, const char); 260 SUNOS32TO64_UAP(flags); 261 SUNOS32_CHECK_ALT_EXIST(l, &sg, SCARG(&ua, path)); 262 263 return (sys_access(l, &ua, retval)); 264 } 265 266 static inline void sunos32_from___stat13 __P((struct stat *, struct netbsd32_stat43 *)); 267 268 static inline void 269 sunos32_from___stat13(sbp, sb32p) 270 struct stat *sbp; 271 struct netbsd32_stat43 *sb32p; 272 { 273 sb32p->st_dev = sbp->st_dev; 274 sb32p->st_ino = sbp->st_ino; 275 sb32p->st_mode = sbp->st_mode; 276 sb32p->st_nlink = sbp->st_nlink; 277 sb32p->st_uid = sbp->st_uid; 278 sb32p->st_gid = sbp->st_gid; 279 sb32p->st_rdev = sbp->st_rdev; 280 if (sbp->st_size < (quad_t)1 << 32) 281 sb32p->st_size = sbp->st_size; 282 else 283 sb32p->st_size = -2; 284 sb32p->st_atimespec.tv_sec = (netbsd32_time_t)sbp->st_atimespec.tv_sec; 285 sb32p->st_atimespec.tv_nsec = (netbsd32_long)sbp->st_atimespec.tv_nsec; 286 sb32p->st_mtimespec.tv_sec = (netbsd32_time_t)sbp->st_mtimespec.tv_sec; 287 sb32p->st_mtimespec.tv_nsec = (netbsd32_long)sbp->st_mtimespec.tv_nsec; 288 sb32p->st_ctimespec.tv_sec = (netbsd32_time_t)sbp->st_ctimespec.tv_sec; 289 sb32p->st_ctimespec.tv_nsec = (netbsd32_long)sbp->st_ctimespec.tv_nsec; 290 sb32p->st_blksize = sbp->st_blksize; 291 sb32p->st_blocks = sbp->st_blocks; 292 sb32p->st_flags = sbp->st_flags; 293 sb32p->st_gen = sbp->st_gen; 294 } 295 296 297 int 298 sunos32_sys_stat(l, v, retval) 299 struct lwp *l; 300 void *v; 301 register_t *retval; 302 { 303 struct sunos32_sys_stat_args /* { 304 syscallarg(const netbsd32_charp) path; 305 syscallarg(netbsd32_stat43p_t) ub; 306 } */ *uap = v; 307 struct proc *p = l->l_proc; 308 struct netbsd32_stat43 sb32; 309 struct stat sb; 310 struct nameidata nd; 311 caddr_t sg; 312 const char *path; 313 int error; 314 315 path = (char *)(u_long)SCARG(uap, path); 316 sg = stackgap_init(p, 0); 317 SUNOS32_CHECK_ALT_EXIST(l, &sg, path); 318 319 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, path, l); 320 if ((error = namei(&nd)) != 0) 321 return (error); 322 error = vn_stat(nd.ni_vp, &sb, l); 323 vput(nd.ni_vp); 324 if (error) 325 return (error); 326 sunos32_from___stat13(&sb, &sb32); 327 error = copyout((caddr_t)&sb32, (caddr_t)(u_long)SCARG(uap, ub), sizeof (sb32)); 328 return (error); 329 } 330 331 int 332 sunos32_sys_lstat(l, v, retval) 333 struct lwp *l; 334 void *v; 335 register_t *retval; 336 { 337 struct sunos32_sys_lstat_args /* { 338 syscallarg(const netbsd32_charp) path; 339 syscallarg(netbsd32_stat43p_t) ub; 340 } */ *uap = v; 341 struct vnode *vp, *dvp; 342 struct proc *p = l->l_proc; 343 struct stat sb, sb1; 344 struct netbsd32_stat43 sb32; 345 int error; 346 struct nameidata nd; 347 int ndflags; 348 const char *path; 349 caddr_t sg; 350 351 path = (char *)(u_long)SCARG(uap, path); 352 sg = stackgap_init(p, 0); 353 SUNOS32_CHECK_ALT_EXIST(l, &sg, path); 354 355 ndflags = NOFOLLOW | LOCKLEAF | LOCKPARENT; 356 again: 357 NDINIT(&nd, LOOKUP, ndflags, UIO_USERSPACE, path, l); 358 if ((error = namei(&nd))) { 359 if (error == EISDIR && (ndflags & LOCKPARENT) != 0) { 360 /* 361 * Should only happen on '/'. Retry without LOCKPARENT; 362 * this is safe since the vnode won't be a VLNK. 363 */ 364 ndflags &= ~LOCKPARENT; 365 goto again; 366 } 367 return (error); 368 } 369 /* 370 * For symbolic links, always return the attributes of its 371 * containing directory, except for mode, size, and links. 372 */ 373 vp = nd.ni_vp; 374 dvp = nd.ni_dvp; 375 if (vp->v_type != VLNK) { 376 if ((ndflags & LOCKPARENT) != 0) { 377 if (dvp == vp) 378 vrele(dvp); 379 else 380 vput(dvp); 381 } 382 error = vn_stat(vp, &sb, l); 383 vput(vp); 384 if (error) 385 return (error); 386 } else { 387 error = vn_stat(dvp, &sb, l); 388 vput(dvp); 389 if (error) { 390 vput(vp); 391 return (error); 392 } 393 error = vn_stat(vp, &sb1, l); 394 vput(vp); 395 if (error) 396 return (error); 397 sb.st_mode &= ~S_IFDIR; 398 sb.st_mode |= S_IFLNK; 399 sb.st_nlink = sb1.st_nlink; 400 sb.st_size = sb1.st_size; 401 sb.st_blocks = sb1.st_blocks; 402 } 403 sunos32_from___stat13(&sb, &sb32); 404 error = copyout((caddr_t)&sb32, (caddr_t)(u_long)SCARG(uap, ub), sizeof (sb32)); 405 return (error); 406 } 407 408 static int 409 sunos32_execve_fetch_element(char * const *array, size_t index, char **value) 410 { 411 int error; 412 netbsd32_charp const *a32 = (void const *)array; 413 netbsd32_charp e; 414 415 error = copyin(a32 + index, &e, sizeof(e)); 416 if (error) 417 return error; 418 *value = (char *)(u_long)(u_int)e; 419 return 0; 420 } 421 422 int 423 sunos32_sys_execv(l, v, retval) 424 struct lwp *l; 425 void *v; 426 register_t *retval; 427 { 428 struct sunos32_sys_execv_args /* { 429 syscallarg(const char *) path; 430 syscallarg(char **) argv; 431 } */ *uap = v; 432 struct proc *p = l->l_proc; 433 const char *path = (const char *)(u_long)(u_int)SCARG(uap, path); 434 caddr_t sg; 435 436 sg = stackgap_init(p, 0); 437 SUNOS32_CHECK_ALT_EXIST(l, &sg, path); 438 439 return execve1(l, path, (char **)(u_long)(u_int)SCARG(uap, argp), NULL, 440 sunos32_execve_fetch_element); 441 } 442 443 int 444 sunos32_sys_execve(l, v, retval) 445 struct lwp *l; 446 void *v; 447 register_t *retval; 448 { 449 struct sunos32_sys_execve_args /* { 450 syscallarg(const char *) path; 451 syscallarg(char **) argv; 452 syscallarg(char **) envp; 453 } */ *uap = v; 454 struct proc *p = l->l_proc; 455 const char *path = (const char *)(u_long)(u_int)SCARG(uap, path); 456 caddr_t sg; 457 458 sg = stackgap_init(p, 0); 459 SUNOS32_CHECK_ALT_EXIST(l, &sg, path); 460 461 return execve1(l, path, (char **)(u_long)(u_int)SCARG(uap, argp), 462 (char **)(u_long)(u_int)SCARG(uap, envp), 463 sunos32_execve_fetch_element); 464 } 465 466 int 467 sunos32_sys_omsync(l, v, retval) 468 struct lwp *l; 469 void *v; 470 register_t *retval; 471 { 472 struct sunos32_sys_omsync_args /* { 473 syscallarg(netbsd32_caddr_t) addr; 474 syscallarg(netbsd32_size_t) len; 475 syscallarg(int) flags; 476 } */ *uap = v; 477 struct netbsd32___msync13_args ouap; 478 479 SCARG(&ouap, addr) = SCARG(uap, addr); 480 SCARG(&ouap, len) = SCARG(uap, len); 481 SCARG(&ouap, flags) = SCARG(uap, flags); 482 483 return (netbsd32___msync13(l, &ouap, retval)); 484 } 485 486 int 487 sunos32_sys_unmount(l, v, retval) 488 struct lwp *l; 489 void *v; 490 register_t *retval; 491 { 492 struct sunos32_sys_unmount_args /* { 493 syscallarg(netbsd32_charp) path; 494 } */ *uap = v; 495 struct sys_unmount_args ua; 496 497 SUNOS32TOP_UAP(path, const char); 498 SCARG(&ua, flags) = 0; 499 500 return (sys_unmount(l, &ua, retval)); 501 } 502 503 /* 504 * Conversion table for SunOS NFS mount flags. 505 */ 506 static struct { 507 int sun_flg; 508 int bsd_flg; 509 } sunnfs_flgtab[] = { 510 { SUNNFS_SOFT, NFSMNT_SOFT }, 511 { SUNNFS_WSIZE, NFSMNT_WSIZE }, 512 { SUNNFS_RSIZE, NFSMNT_RSIZE }, 513 { SUNNFS_TIMEO, NFSMNT_TIMEO }, 514 { SUNNFS_RETRANS, NFSMNT_RETRANS }, 515 { SUNNFS_HOSTNAME, 0 }, /* Ignored */ 516 { SUNNFS_INT, NFSMNT_INT }, 517 { SUNNFS_NOAC, 0 }, /* Ignored */ 518 { SUNNFS_ACREGMIN, 0 }, /* Ignored */ 519 { SUNNFS_ACREGMAX, 0 }, /* Ignored */ 520 { SUNNFS_ACDIRMIN, 0 }, /* Ignored */ 521 { SUNNFS_ACDIRMAX, 0 }, /* Ignored */ 522 { SUNNFS_SECURE, 0 }, /* Ignored */ 523 { SUNNFS_NOCTO, 0 }, /* Ignored */ 524 { SUNNFS_POSIX, 0 } /* Ignored */ 525 }; 526 527 int 528 sunos32_sys_mount(l, v, retval) 529 struct lwp *l; 530 void *v; 531 register_t *retval; 532 { 533 struct sunos32_sys_mount_args /* { 534 syscallarg(netbsd32_charp) type; 535 syscallarg(netbsd32_charp) path; 536 syscallarg(int) flags; 537 syscallarg(netbsd32_caddr_t) data; 538 } */ *uap = v; 539 struct proc *p = l->l_proc; 540 struct sys_mount_args ua; 541 int oflags = SCARG(uap, flags), nflags, error; 542 char fsname[MFSNAMELEN]; 543 caddr_t sg = stackgap_init(p, 0); 544 545 if (oflags & (SUNM_NOSUB | SUNM_SYS5)) 546 return (EINVAL); 547 if ((oflags & SUNM_NEWTYPE) == 0) 548 return (EINVAL); 549 nflags = 0; 550 if (oflags & SUNM_RDONLY) 551 nflags |= MNT_RDONLY; 552 if (oflags & SUNM_NOSUID) 553 nflags |= MNT_NOSUID; 554 if (oflags & SUNM_REMOUNT) 555 nflags |= MNT_UPDATE; 556 SCARG(uap, flags) = nflags; 557 558 error = copyinstr((caddr_t)(u_long)SCARG(uap, type), fsname, 559 sizeof fsname, (size_t *)0); 560 if (error) 561 return (error); 562 563 if (strncmp(fsname, "4.2", sizeof fsname) == 0) { 564 SCARG(uap, type) = (netbsd32_charp)(u_long)stackgap_alloc(p, &sg, sizeof("ffs")); 565 error = copyout("ffs", (caddr_t)(u_long)SCARG(uap, type), sizeof("ffs")); 566 if (error) 567 return (error); 568 } else if (strncmp(fsname, "nfs", sizeof fsname) == 0) { 569 struct sunos_nfs_args sna; 570 struct sockaddr_in sain; 571 struct nfs_args na; /* XXX */ 572 struct sockaddr sa; 573 int n; 574 575 error = copyin((caddr_t)(u_long)SCARG(uap, data), &sna, sizeof sna); 576 if (error) 577 return (error); 578 error = copyin(sna.addr, &sain, sizeof sain); 579 if (error) 580 return (error); 581 memcpy(&sa, &sain, sizeof sa); 582 sa.sa_len = sizeof(sain); 583 SCARG(uap, data) = (netbsd32_charp)(u_long)stackgap_alloc(p, &sg, sizeof(na)); 584 na.version = NFS_ARGSVERSION; 585 na.addr = stackgap_alloc(p, &sg, sizeof(struct sockaddr)); 586 na.addrlen = sizeof(struct sockaddr); 587 na.sotype = SOCK_DGRAM; 588 na.proto = IPPROTO_UDP; 589 na.fh = (void *)sna.fh; 590 na.fhsize = NFSX_V2FH; 591 na.flags = 0; 592 n = sizeof(sunnfs_flgtab) / sizeof(sunnfs_flgtab[0]); 593 while (--n >= 0) 594 if (sna.flags & sunnfs_flgtab[n].sun_flg) 595 na.flags |= sunnfs_flgtab[n].bsd_flg; 596 na.wsize = sna.wsize; 597 na.rsize = sna.rsize; 598 if (na.flags & NFSMNT_RSIZE) { 599 na.flags |= NFSMNT_READDIRSIZE; 600 na.readdirsize = na.rsize; 601 } 602 na.timeo = sna.timeo; 603 na.retrans = sna.retrans; 604 na.hostname = (char *)(u_long)sna.hostname; 605 606 error = copyout(&sa, na.addr, sizeof sa); 607 if (error) 608 return (error); 609 error = copyout(&na, (caddr_t)(u_long)SCARG(uap, data), sizeof na); 610 if (error) 611 return (error); 612 } 613 SUNOS32TOP_UAP(type, const char); 614 SUNOS32TOP_UAP(path, const char); 615 SUNOS32TO64_UAP(flags); 616 SUNOS32TOP_UAP(data, void); 617 return (sys_mount(l, &ua, retval)); 618 } 619 620 #if defined(NFS) 621 int 622 async_daemon(l, v, retval) 623 struct lwp *l; 624 void *v; 625 register_t *retval; 626 { 627 struct netbsd32_nfssvc_args ouap; 628 629 SCARG(&ouap, flag) = NFSSVC_BIOD; 630 SCARG(&ouap, argp) = 0; 631 632 return (netbsd32_nfssvc(l, &ouap, retval)); 633 } 634 #endif /* NFS */ 635 636 void native_to_sunos_sigset __P((const sigset_t *, int *)); 637 void sunos_to_native_sigset __P((const int, sigset_t *)); 638 639 inline void 640 native_to_sunos_sigset(ss, mask) 641 const sigset_t *ss; 642 int *mask; 643 { 644 *mask = ss->__bits[0]; 645 } 646 647 inline void 648 sunos_to_native_sigset(mask, ss) 649 const int mask; 650 sigset_t *ss; 651 { 652 653 ss->__bits[0] = mask; 654 ss->__bits[1] = 0; 655 ss->__bits[2] = 0; 656 ss->__bits[3] = 0; 657 } 658 659 int 660 sunos32_sys_sigpending(l, v, retval) 661 struct lwp *l; 662 void *v; 663 register_t *retval; 664 { 665 struct sunos32_sys_sigpending_args /* { 666 syscallarg(netbsd32_intp) mask; 667 } */ *uap = v; 668 struct proc *p = l->l_proc; 669 sigset_t ss; 670 int mask; 671 672 sigpending1(p, &ss); 673 native_to_sunos_sigset(&ss, &mask); 674 675 return (copyout((caddr_t)(u_long)&mask, (caddr_t)(u_long)SCARG(uap, mask), sizeof(int))); 676 } 677 678 int 679 sunos32_sys_sigsuspend(l, v, retval) 680 struct lwp *l; 681 void *v; 682 register_t *retval; 683 { 684 struct sunos32_sys_sigsuspend_args /* { 685 syscallarg(int) mask; 686 } */ *uap = v; 687 int mask; 688 struct proc *p = l->l_proc; 689 sigset_t ss; 690 691 mask = SCARG(uap, mask); 692 sunos_to_native_sigset(mask, &ss); 693 return (sigsuspend1(p, &ss)); 694 } 695 696 /* 697 * Read Sun-style directory entries. We suck them into kernel space so 698 * that they can be massaged before being copied out to user code. Like 699 * SunOS, we squish out `empty' entries. 700 * 701 * This is quite ugly, but what do you expect from compatibility code? 702 */ 703 int 704 sunos32_sys_getdents(l, v, retval) 705 struct lwp *l; 706 void *v; 707 register_t *retval; 708 { 709 struct sunos32_sys_getdents_args /* { 710 syscallarg(int) fd; 711 syscallarg(netbsd32_charp) buf; 712 syscallarg(int) nbytes; 713 } */ *uap = v; 714 struct proc *p = l->l_proc; 715 struct dirent *bdp; 716 struct vnode *vp; 717 caddr_t inp, sbuf; /* BSD-format */ 718 int len, reclen; /* BSD-format */ 719 caddr_t outp; /* Sun-format */ 720 int resid, sunos_reclen;/* Sun-format */ 721 struct file *fp; 722 struct uio auio; 723 struct iovec aiov; 724 struct sunos32_dirent idb; 725 off_t off; /* true file offset */ 726 int buflen, error, eofflag; 727 off_t *cookiebuf, *cookie; 728 int ncookies; 729 730 /* getvnode() will use the descriptor for us */ 731 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 732 return (error); 733 734 if ((fp->f_flag & FREAD) == 0) { 735 error = EBADF; 736 goto out1; 737 } 738 739 vp = (struct vnode *)fp->f_data; 740 if (vp->v_type != VDIR) { 741 error = EINVAL; 742 goto out1; 743 } 744 745 buflen = min(MAXBSIZE, SCARG(uap, nbytes)); 746 sbuf = malloc(buflen, M_TEMP, M_WAITOK); 747 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 748 off = fp->f_offset; 749 again: 750 aiov.iov_base = sbuf; 751 aiov.iov_len = buflen; 752 auio.uio_iov = &aiov; 753 auio.uio_iovcnt = 1; 754 auio.uio_rw = UIO_READ; 755 auio.uio_segflg = UIO_SYSSPACE; 756 auio.uio_lwp = NULL; 757 auio.uio_resid = buflen; 758 auio.uio_offset = off; 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_socket(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 = suser(p->p_ucred, &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