svr4_misc.c revision 71452
1/* 2 * Copyright (c) 1998 Mark Newton 3 * Copyright (c) 1994 Christos Zoulas 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission 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, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD: head/sys/compat/svr4/svr4_misc.c 71452 2001-01-23 21:30:25Z jhb $ 29 */ 30 31/* 32 * SVR4 compatibility module. 33 * 34 * SVR4 system calls that are implemented differently in BSD are 35 * handled here. 36 */ 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/namei.h> 41#include <sys/dirent.h> 42#include <sys/malloc.h> 43#include <sys/proc.h> 44#include <sys/file.h> 45#include <sys/stat.h> 46#include <sys/time.h> 47#include <sys/file.h> 48#include <sys/filedesc.h> 49#include <sys/kernel.h> 50#include <sys/mman.h> 51#include <sys/mount.h> 52#include <sys/resource.h> 53#include <sys/resourcevar.h> 54#include <sys/vnode.h> 55#include <sys/uio.h> 56#include <sys/wait.h> 57#include <sys/times.h> 58#include <sys/fcntl.h> 59#include <sys/sem.h> 60#include <sys/msg.h> 61#include <sys/ptrace.h> 62 63#include <sys/sysproto.h> 64 65#include <compat/svr4/svr4.h> 66#include <compat/svr4/svr4_types.h> 67#include <compat/svr4/svr4_signal.h> 68#include <compat/svr4/svr4_proto.h> 69#include <compat/svr4/svr4_util.h> 70#include <compat/svr4/svr4_sysconfig.h> 71#include <compat/svr4/svr4_dirent.h> 72#include <compat/svr4/svr4_acl.h> 73#include <compat/svr4/svr4_ulimit.h> 74#include <compat/svr4/svr4_statvfs.h> 75#include <compat/svr4/svr4_hrt.h> 76#include <compat/svr4/svr4_mman.h> 77#include <compat/svr4/svr4_wait.h> 78 79#include <machine/vmparam.h> 80#include <vm/vm.h> 81#include <vm/vm_param.h> 82#include <vm/vm_map.h> 83#if defined(__FreeBSD__) 84#include <vm/vm_zone.h> 85#endif 86 87#if defined(NetBSD) 88# if defined(UVM) 89# include <uvm/uvm_extern.h> 90# endif 91#endif 92 93#define BSD_DIRENT(cp) ((struct dirent *)(cp)) 94 95static int svr4_mknod __P((struct proc *, register_t *, char *, 96 svr4_mode_t, svr4_dev_t)); 97 98static __inline clock_t timeval_to_clock_t __P((struct timeval *)); 99static int svr4_setinfo __P((struct proc *, int, svr4_siginfo_t *)); 100 101struct svr4_hrtcntl_args; 102static int svr4_hrtcntl __P((struct proc *, struct svr4_hrtcntl_args *, 103 register_t *)); 104static void bsd_statfs_to_svr4_statvfs __P((const struct statfs *, 105 struct svr4_statvfs *)); 106static void bsd_statfs_to_svr4_statvfs64 __P((const struct statfs *, 107 struct svr4_statvfs64 *)); 108static struct proc *svr4_pfind __P((pid_t pid)); 109 110/* BOGUS noop */ 111#if defined(BOGUS) 112int 113svr4_sys_setitimer(p, uap) 114 register struct proc *p; 115 struct svr4_sys_setitimer_args *uap; 116{ 117 p->p_retval[0] = 0; 118 return 0; 119} 120#endif 121 122int 123svr4_sys_wait(p, uap) 124 struct proc *p; 125 struct svr4_sys_wait_args *uap; 126{ 127 struct wait_args w4; 128 int error, *retval = p->p_retval, st, sig; 129 size_t sz = sizeof(*SCARG(&w4, status)); 130 131 SCARG(&w4, rusage) = NULL; 132 SCARG(&w4, options) = 0; 133 134 if (SCARG(uap, status) == NULL) { 135 caddr_t sg = stackgap_init(); 136 137 SCARG(&w4, status) = stackgap_alloc(&sg, sz); 138 } 139 else 140 SCARG(&w4, status) = SCARG(uap, status); 141 142 SCARG(&w4, pid) = WAIT_ANY; 143 144 if ((error = wait4(p, &w4)) != 0) 145 return error; 146 147 if ((error = copyin(SCARG(&w4, status), &st, sizeof(st))) != 0) 148 return error; 149 150 if (WIFSIGNALED(st)) { 151 sig = WTERMSIG(st); 152 if (sig >= 0 && sig < NSIG) 153 st = (st & ~0177) | SVR4_BSD2SVR4_SIG(sig); 154 } else if (WIFSTOPPED(st)) { 155 sig = WSTOPSIG(st); 156 if (sig >= 0 && sig < NSIG) 157 st = (st & ~0xff00) | (SVR4_BSD2SVR4_SIG(sig) << 8); 158 } 159 160 /* 161 * It looks like wait(2) on svr4/solaris/2.4 returns 162 * the status in retval[1], and the pid on retval[0]. 163 */ 164 retval[1] = st; 165 166 if (SCARG(uap, status)) 167 if ((error = copyout(&st, SCARG(uap, status), sizeof(st))) != 0) 168 return error; 169 170 return 0; 171} 172 173int 174svr4_sys_execv(p, uap) 175 struct proc *p; 176 struct svr4_sys_execv_args *uap; 177{ 178 struct execve_args ap; 179 caddr_t sg; 180 181 sg = stackgap_init(); 182 CHECKALTEXIST(p, &sg, SCARG(uap, path)); 183 184 SCARG(&ap, fname) = SCARG(uap, path); 185 SCARG(&ap, argv) = SCARG(uap, argp); 186 SCARG(&ap, envv) = NULL; 187 188 return execve(p, &ap); 189} 190 191int 192svr4_sys_execve(p, uap) 193 struct proc *p; 194 struct svr4_sys_execve_args *uap; 195{ 196 struct execve_args ap; 197 caddr_t sg; 198 199 sg = stackgap_init(); 200 CHECKALTEXIST(p, &sg, uap->path); 201 202 SCARG(&ap, fname) = SCARG(uap, path); 203 SCARG(&ap, argv) = SCARG(uap, argp); 204 SCARG(&ap, envv) = SCARG(uap, envp); 205 206 return execve(p, &ap); 207} 208 209int 210svr4_sys_time(p, v) 211 struct proc *p; 212 struct svr4_sys_time_args *v; 213{ 214 struct svr4_sys_time_args *uap = v; 215 int error = 0; 216 struct timeval tv; 217 218 microtime(&tv); 219 if (SCARG(uap, t)) 220 error = copyout(&tv.tv_sec, SCARG(uap, t), 221 sizeof(*(SCARG(uap, t)))); 222 p->p_retval[0] = (int) tv.tv_sec; 223 224 return error; 225} 226 227 228/* 229 * Read SVR4-style directory entries. We suck them into kernel space so 230 * that they can be massaged before being copied out to user code. 231 * 232 * This code is ported from the Linux emulator: Changes to the VFS interface 233 * between FreeBSD and NetBSD have made it simpler to port it from there than 234 * to adapt the NetBSD version. 235 */ 236int 237svr4_sys_getdents64(p, uap) 238 struct proc *p; 239 struct svr4_sys_getdents64_args *uap; 240{ 241 register struct dirent *bdp; 242 struct vnode *vp; 243 caddr_t inp, buf; /* BSD-format */ 244 int len, reclen; /* BSD-format */ 245 caddr_t outp; /* SVR4-format */ 246 int resid, svr4reclen=0; /* SVR4-format */ 247 struct file *fp; 248 struct uio auio; 249 struct iovec aiov; 250 struct vattr va; 251 struct ucred *uc; 252 off_t off; 253 struct svr4_dirent64 svr4_dirent; 254 int buflen, error, eofflag, nbytes, justone; 255 u_long *cookies = NULL, *cookiep; 256 int ncookies; 257 258 DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n", 259 p->p_pid, SCARG(uap, fd), SCARG(uap, nbytes))); 260 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) { 261 return (error); 262 } 263 264 if ((fp->f_flag & FREAD) == 0) 265 return (EBADF); 266 267 vp = (struct vnode *) fp->f_data; 268 269 if (vp->v_type != VDIR) 270 return (EINVAL); 271 272 PROC_LOCK(p); 273 uc = p->p_ucred; 274 crhold(uc); 275 PROC_UNLOCK(p); 276 error = VOP_GETATTR(vp, &va, uc, p); 277 crfree(uc); 278 if (error != 0) { 279 return error; 280 } 281 282 nbytes = SCARG(uap, nbytes); 283 if (nbytes == 1) { 284 nbytes = sizeof (struct svr4_dirent64); 285 justone = 1; 286 } 287 else 288 justone = 0; 289 290 off = fp->f_offset; 291#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ 292 buflen = max(DIRBLKSIZ, nbytes); 293 buflen = min(buflen, MAXBSIZE); 294 buf = malloc(buflen, M_TEMP, M_WAITOK); 295 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 296again: 297 aiov.iov_base = buf; 298 aiov.iov_len = buflen; 299 auio.uio_iov = &aiov; 300 auio.uio_iovcnt = 1; 301 auio.uio_rw = UIO_READ; 302 auio.uio_segflg = UIO_SYSSPACE; 303 auio.uio_procp = p; 304 auio.uio_resid = buflen; 305 auio.uio_offset = off; 306 307 if (cookies) { 308 free(cookies, M_TEMP); 309 cookies = NULL; 310 } 311 312 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 313 &ncookies, &cookies); 314 if (error) { 315 goto out; 316 } 317 318 inp = buf; 319 outp = (caddr_t) SCARG(uap, dp); 320 resid = nbytes; 321 if ((len = buflen - auio.uio_resid) <= 0) { 322 goto eof; 323 } 324 325 cookiep = cookies; 326 327 if (cookies) { 328 /* 329 * When using cookies, the vfs has the option of reading from 330 * a different offset than that supplied (UFS truncates the 331 * offset to a block boundary to make sure that it never reads 332 * partway through a directory entry, even if the directory 333 * has been compacted). 334 */ 335 while (len > 0 && ncookies > 0 && *cookiep <= off) { 336 bdp = (struct dirent *) inp; 337 len -= bdp->d_reclen; 338 inp += bdp->d_reclen; 339 cookiep++; 340 ncookies--; 341 } 342 } 343 344 while (len > 0) { 345 if (cookiep && ncookies == 0) 346 break; 347 bdp = (struct dirent *) inp; 348 reclen = bdp->d_reclen; 349 if (reclen & 3) { 350 DPRINTF(("svr4_readdir: reclen=%d\n", reclen)); 351 error = EFAULT; 352 goto out; 353 } 354 355 if (bdp->d_fileno == 0) { 356 inp += reclen; 357 if (cookiep) { 358 off = *cookiep++; 359 ncookies--; 360 } else 361 off += reclen; 362 len -= reclen; 363 continue; 364 } 365 svr4reclen = SVR4_RECLEN(&svr4_dirent, bdp->d_namlen); 366 if (reclen > len || resid < svr4reclen) { 367 outp++; 368 break; 369 } 370 svr4_dirent.d_ino = (long) bdp->d_fileno; 371 if (justone) { 372 /* 373 * old svr4-style readdir usage. 374 */ 375 svr4_dirent.d_off = (svr4_off_t) svr4reclen; 376 svr4_dirent.d_reclen = (u_short) bdp->d_namlen; 377 } else { 378 svr4_dirent.d_off = (svr4_off_t)(off + reclen); 379 svr4_dirent.d_reclen = (u_short) svr4reclen; 380 } 381 strcpy(svr4_dirent.d_name, bdp->d_name); 382 if ((error = copyout((caddr_t)&svr4_dirent, outp, svr4reclen))) 383 goto out; 384 inp += reclen; 385 if (cookiep) { 386 off = *cookiep++; 387 ncookies--; 388 } else 389 off += reclen; 390 outp += svr4reclen; 391 resid -= svr4reclen; 392 len -= reclen; 393 if (justone) 394 break; 395 } 396 397 if (outp == (caddr_t) SCARG(uap, dp)) 398 goto again; 399 fp->f_offset = off; 400 401 if (justone) 402 nbytes = resid + svr4reclen; 403 404eof: 405 p->p_retval[0] = nbytes - resid; 406out: 407 if (cookies) 408 free(cookies, M_TEMP); 409 VOP_UNLOCK(vp, 0, p); 410 free(buf, M_TEMP); 411 return error; 412} 413 414 415int 416svr4_sys_getdents(p, uap) 417 struct proc *p; 418 struct svr4_sys_getdents_args *uap; 419{ 420 struct dirent *bdp; 421 struct vnode *vp; 422 caddr_t inp, buf; /* BSD-format */ 423 int len, reclen; /* BSD-format */ 424 caddr_t outp; /* SVR4-format */ 425 int resid, svr4_reclen; /* SVR4-format */ 426 struct file *fp; 427 struct uio auio; 428 struct iovec aiov; 429 struct svr4_dirent idb; 430 off_t off; /* true file offset */ 431 int buflen, error, eofflag; 432 u_long *cookiebuf = NULL, *cookie; 433 int ncookies = 0, *retval = p->p_retval; 434 435 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 436 return (error); 437 438 if ((fp->f_flag & FREAD) == 0) 439 return (EBADF); 440 441 vp = (struct vnode *)fp->f_data; 442 if (vp->v_type != VDIR) 443 return (EINVAL); 444 445 buflen = min(MAXBSIZE, SCARG(uap, nbytes)); 446 buf = malloc(buflen, M_TEMP, M_WAITOK); 447 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 448 off = fp->f_offset; 449again: 450 aiov.iov_base = buf; 451 aiov.iov_len = buflen; 452 auio.uio_iov = &aiov; 453 auio.uio_iovcnt = 1; 454 auio.uio_rw = UIO_READ; 455 auio.uio_segflg = UIO_SYSSPACE; 456 auio.uio_procp = p; 457 auio.uio_resid = buflen; 458 auio.uio_offset = off; 459 /* 460 * First we read into the malloc'ed buffer, then 461 * we massage it into user space, one record at a time. 462 */ 463 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, 464 &cookiebuf); 465 if (error) 466 goto out; 467 468 inp = buf; 469 outp = SCARG(uap, buf); 470 resid = SCARG(uap, nbytes); 471 if ((len = buflen - auio.uio_resid) == 0) 472 goto eof; 473 474 for (cookie = cookiebuf; len > 0; len -= reclen) { 475 bdp = (struct dirent *)inp; 476 reclen = bdp->d_reclen; 477 if (reclen & 3) 478 panic("svr4_sys_getdents64: bad reclen"); 479 off = *cookie++; /* each entry points to the next */ 480 if ((off >> 32) != 0) { 481 uprintf("svr4_sys_getdents64: dir offset too large for emulated program"); 482 error = EINVAL; 483 goto out; 484 } 485 if (bdp->d_fileno == 0) { 486 inp += reclen; /* it is a hole; squish it out */ 487 continue; 488 } 489 svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen); 490 if (reclen > len || resid < svr4_reclen) { 491 /* entry too big for buffer, so just stop */ 492 outp++; 493 break; 494 } 495 /* 496 * Massage in place to make a SVR4-shaped dirent (otherwise 497 * we have to worry about touching user memory outside of 498 * the copyout() call). 499 */ 500 idb.d_ino = (svr4_ino_t)bdp->d_fileno; 501 idb.d_off = (svr4_off_t)off; 502 idb.d_reclen = (u_short)svr4_reclen; 503 strcpy(idb.d_name, bdp->d_name); 504 if ((error = copyout((caddr_t)&idb, outp, svr4_reclen))) 505 goto out; 506 /* advance past this real entry */ 507 inp += reclen; 508 /* advance output past SVR4-shaped entry */ 509 outp += svr4_reclen; 510 resid -= svr4_reclen; 511 } 512 513 /* if we squished out the whole block, try again */ 514 if (outp == SCARG(uap, buf)) 515 goto again; 516 fp->f_offset = off; /* update the vnode offset */ 517 518eof: 519 *retval = SCARG(uap, nbytes) - resid; 520out: 521 VOP_UNLOCK(vp, 0, p); 522 if (cookiebuf) 523 free(cookiebuf, M_TEMP); 524 free(buf, M_TEMP); 525 return error; 526} 527 528 529int 530svr4_sys_mmap(p, uap) 531 struct proc *p; 532 struct svr4_sys_mmap_args *uap; 533{ 534 struct mmap_args mm; 535 int *retval; 536 537 retval = p->p_retval; 538#define _MAP_NEW 0x80000000 539 /* 540 * Verify the arguments. 541 */ 542 if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) 543 return EINVAL; /* XXX still needed? */ 544 545 if (SCARG(uap, len) == 0) 546 return EINVAL; 547 548 SCARG(&mm, prot) = SCARG(uap, prot); 549 SCARG(&mm, len) = SCARG(uap, len); 550 SCARG(&mm, flags) = SCARG(uap, flags) & ~_MAP_NEW; 551 SCARG(&mm, fd) = SCARG(uap, fd); 552 SCARG(&mm, addr) = SCARG(uap, addr); 553 SCARG(&mm, pos) = SCARG(uap, pos); 554 555 return mmap(p, &mm); 556} 557 558int 559svr4_sys_mmap64(p, uap) 560 struct proc *p; 561 struct svr4_sys_mmap64_args *uap; 562{ 563 struct mmap_args mm; 564 void *rp; 565 566#define _MAP_NEW 0x80000000 567 /* 568 * Verify the arguments. 569 */ 570 if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) 571 return EINVAL; /* XXX still needed? */ 572 573 if (SCARG(uap, len) == 0) 574 return EINVAL; 575 576 SCARG(&mm, prot) = SCARG(uap, prot); 577 SCARG(&mm, len) = SCARG(uap, len); 578 SCARG(&mm, flags) = SCARG(uap, flags) & ~_MAP_NEW; 579 SCARG(&mm, fd) = SCARG(uap, fd); 580 SCARG(&mm, addr) = SCARG(uap, addr); 581 SCARG(&mm, pos) = SCARG(uap, pos); 582 583 rp = (void *) round_page((vm_offset_t)(p->p_vmspace->vm_daddr + MAXDSIZ)); 584 if ((SCARG(&mm, flags) & MAP_FIXED) == 0 && 585 SCARG(&mm, addr) != 0 && (void *)SCARG(&mm, addr) < rp) 586 SCARG(&mm, addr) = rp; 587 588 return mmap(p, &mm); 589} 590 591 592int 593svr4_sys_fchroot(p, uap) 594 struct proc *p; 595 struct svr4_sys_fchroot_args *uap; 596{ 597 struct filedesc *fdp = p->p_fd; 598 struct vnode *vp; 599 struct file *fp; 600 struct ucred *uc; 601 int error; 602 603 if ((error = suser(p)) != 0) 604 return error; 605 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) 606 return error; 607 vp = (struct vnode *) fp->f_data; 608 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 609 if (vp->v_type != VDIR) 610 error = ENOTDIR; 611 else { 612 PROC_LOCK(p); 613 uc = p->p_ucred; 614 crhold(uc); 615 PROC_UNLOCK(p); 616 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 617 crfree(uc); 618 } 619 VOP_UNLOCK(vp, 0, p); 620 if (error) 621 return error; 622 VREF(vp); 623 if (fdp->fd_rdir != NULL) 624 vrele(fdp->fd_rdir); 625 fdp->fd_rdir = vp; 626 return 0; 627} 628 629 630static int 631svr4_mknod(p, retval, path, mode, dev) 632 struct proc *p; 633 register_t *retval; 634 char *path; 635 svr4_mode_t mode; 636 svr4_dev_t dev; 637{ 638 caddr_t sg = stackgap_init(); 639 640 CHECKALTEXIST(p, &sg, path); 641 642 if (S_ISFIFO(mode)) { 643 struct mkfifo_args ap; 644 SCARG(&ap, path) = path; 645 SCARG(&ap, mode) = mode; 646 return mkfifo(p, &ap); 647 } else { 648 struct mknod_args ap; 649 SCARG(&ap, path) = path; 650 SCARG(&ap, mode) = mode; 651 SCARG(&ap, dev) = dev; 652 return mknod(p, &ap); 653 } 654} 655 656 657int 658svr4_sys_mknod(p, uap) 659 register struct proc *p; 660 struct svr4_sys_mknod_args *uap; 661{ 662 int *retval = p->p_retval; 663 return svr4_mknod(p, retval, 664 SCARG(uap, path), SCARG(uap, mode), 665 (svr4_dev_t)svr4_to_bsd_odev_t(SCARG(uap, dev))); 666} 667 668 669int 670svr4_sys_xmknod(p, uap) 671 struct proc *p; 672 struct svr4_sys_xmknod_args *uap; 673{ 674 int *retval = p->p_retval; 675 return svr4_mknod(p, retval, 676 SCARG(uap, path), SCARG(uap, mode), 677 (svr4_dev_t)svr4_to_bsd_dev_t(SCARG(uap, dev))); 678} 679 680 681int 682svr4_sys_vhangup(p, uap) 683 struct proc *p; 684 struct svr4_sys_vhangup_args *uap; 685{ 686 return 0; 687} 688 689 690int 691svr4_sys_sysconfig(p, uap) 692 struct proc *p; 693 struct svr4_sys_sysconfig_args *uap; 694{ 695 int *retval; 696 697 retval = &(p->p_retval[0]); 698 699 switch (SCARG(uap, name)) { 700 case SVR4_CONFIG_UNUSED: 701 *retval = 0; 702 break; 703 case SVR4_CONFIG_NGROUPS: 704 *retval = NGROUPS_MAX; 705 break; 706 case SVR4_CONFIG_CHILD_MAX: 707 *retval = maxproc; 708 break; 709 case SVR4_CONFIG_OPEN_FILES: 710 *retval = maxfiles; 711 break; 712 case SVR4_CONFIG_POSIX_VER: 713 *retval = 198808; 714 break; 715 case SVR4_CONFIG_PAGESIZE: 716 *retval = PAGE_SIZE; 717 break; 718 case SVR4_CONFIG_CLK_TCK: 719 *retval = 60; /* should this be `hz', ie. 100? */ 720 break; 721 case SVR4_CONFIG_XOPEN_VER: 722 *retval = 2; /* XXX: What should that be? */ 723 break; 724 case SVR4_CONFIG_PROF_TCK: 725 *retval = 60; /* XXX: What should that be? */ 726 break; 727 case SVR4_CONFIG_NPROC_CONF: 728 *retval = 1; /* Only one processor for now */ 729 break; 730 case SVR4_CONFIG_NPROC_ONLN: 731 *retval = 1; /* And it better be online */ 732 break; 733 case SVR4_CONFIG_AIO_LISTIO_MAX: 734 case SVR4_CONFIG_AIO_MAX: 735 case SVR4_CONFIG_AIO_PRIO_DELTA_MAX: 736 *retval = 0; /* No aio support */ 737 break; 738 case SVR4_CONFIG_DELAYTIMER_MAX: 739 *retval = 0; /* No delaytimer support */ 740 break; 741 case SVR4_CONFIG_MQ_OPEN_MAX: 742 *retval = msginfo.msgmni; 743 break; 744 case SVR4_CONFIG_MQ_PRIO_MAX: 745 *retval = 0; /* XXX: Don't know */ 746 break; 747 case SVR4_CONFIG_RTSIG_MAX: 748 *retval = 0; 749 break; 750 case SVR4_CONFIG_SEM_NSEMS_MAX: 751 *retval = seminfo.semmni; 752 break; 753 case SVR4_CONFIG_SEM_VALUE_MAX: 754 *retval = seminfo.semvmx; 755 break; 756 case SVR4_CONFIG_SIGQUEUE_MAX: 757 *retval = 0; /* XXX: Don't know */ 758 break; 759 case SVR4_CONFIG_SIGRT_MIN: 760 case SVR4_CONFIG_SIGRT_MAX: 761 *retval = 0; /* No real time signals */ 762 break; 763 case SVR4_CONFIG_TIMER_MAX: 764 *retval = 3; /* XXX: real, virtual, profiling */ 765 break; 766#if defined(NOTYET) 767 case SVR4_CONFIG_PHYS_PAGES: 768#if defined(UVM) 769 *retval = uvmexp.free; /* XXX: free instead of total */ 770#else 771 *retval = cnt.v_free_count; /* XXX: free instead of total */ 772#endif 773 break; 774 case SVR4_CONFIG_AVPHYS_PAGES: 775#if defined(UVM) 776 *retval = uvmexp.active; /* XXX: active instead of avg */ 777#else 778 *retval = cnt.v_active_count; /* XXX: active instead of avg */ 779#endif 780 break; 781#endif /* NOTYET */ 782 783 default: 784 return EINVAL; 785 } 786 return 0; 787} 788 789extern int swap_pager_full; 790 791/* ARGSUSED */ 792int 793svr4_sys_break(p, uap) 794 struct proc *p; 795 struct svr4_sys_break_args *uap; 796{ 797 struct vmspace *vm = p->p_vmspace; 798 vm_offset_t new, old, base, ns; 799 int rv; 800 801 base = round_page((vm_offset_t) vm->vm_daddr); 802 ns = (vm_offset_t)SCARG(uap, nsize); 803 new = round_page(ns); 804 /* For p_rlimit. */ 805 mtx_assert(&Giant, MA_OWNED); 806 if (new > base) { 807 if ((new - base) > (unsigned) p->p_rlimit[RLIMIT_DATA].rlim_cur) { 808 return ENOMEM; 809 } 810 if (new >= VM_MAXUSER_ADDRESS) { 811 return (ENOMEM); 812 } 813 } else if (new < base) { 814 /* 815 * This is simply an invalid value. If someone wants to 816 * do fancy address space manipulations, mmap and munmap 817 * can do most of what the user would want. 818 */ 819 return EINVAL; 820 } 821 822 old = base + ctob(vm->vm_dsize); 823 824 if (new > old) { 825 vm_size_t diff; 826 if (swap_pager_full) { 827 return (ENOMEM); 828 } 829 diff = new - old; 830 rv = vm_map_find(&vm->vm_map, NULL, 0, &old, diff, FALSE, 831 VM_PROT_ALL, VM_PROT_ALL, 0); 832 if (rv != KERN_SUCCESS) { 833 return (ENOMEM); 834 } 835 vm->vm_dsize += btoc(diff); 836 } else if (new < old) { 837 rv = vm_map_remove(&vm->vm_map, new, old); 838 if (rv != KERN_SUCCESS) { 839 return (ENOMEM); 840 } 841 vm->vm_dsize -= btoc(old - new); 842 } 843 844 return (0); 845} 846 847static __inline clock_t 848timeval_to_clock_t(tv) 849 struct timeval *tv; 850{ 851 return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz); 852} 853 854 855int 856svr4_sys_times(p, uap) 857 struct proc *p; 858 struct svr4_sys_times_args *uap; 859{ 860 int error, *retval = p->p_retval; 861 struct tms tms; 862 struct timeval t; 863 struct rusage *ru; 864 struct rusage r; 865 struct getrusage_args ga; 866 867 caddr_t sg = stackgap_init(); 868 ru = stackgap_alloc(&sg, sizeof(struct rusage)); 869 870 SCARG(&ga, who) = RUSAGE_SELF; 871 SCARG(&ga, rusage) = ru; 872 873 error = getrusage(p, &ga); 874 if (error) 875 return error; 876 877 if ((error = copyin(ru, &r, sizeof r)) != 0) 878 return error; 879 880 tms.tms_utime = timeval_to_clock_t(&r.ru_utime); 881 tms.tms_stime = timeval_to_clock_t(&r.ru_stime); 882 883 SCARG(&ga, who) = RUSAGE_CHILDREN; 884 error = getrusage(p, &ga); 885 if (error) 886 return error; 887 888 if ((error = copyin(ru, &r, sizeof r)) != 0) 889 return error; 890 891 tms.tms_cutime = timeval_to_clock_t(&r.ru_utime); 892 tms.tms_cstime = timeval_to_clock_t(&r.ru_stime); 893 894 microtime(&t); 895 *retval = timeval_to_clock_t(&t); 896 897 return copyout(&tms, SCARG(uap, tp), sizeof(tms)); 898} 899 900 901int 902svr4_sys_ulimit(p, uap) 903 struct proc *p; 904 struct svr4_sys_ulimit_args *uap; 905{ 906 int *retval = p->p_retval; 907 908 switch (SCARG(uap, cmd)) { 909 case SVR4_GFILLIM: 910 /* For p_rlimit below. */ 911 mtx_assert(&Giant, MA_OWNED); 912 *retval = p->p_rlimit[RLIMIT_FSIZE].rlim_cur / 512; 913 if (*retval == -1) 914 *retval = 0x7fffffff; 915 return 0; 916 917 case SVR4_SFILLIM: 918 { 919 int error; 920 struct __setrlimit_args srl; 921 struct rlimit krl; 922 caddr_t sg = stackgap_init(); 923 struct rlimit *url = (struct rlimit *) 924 stackgap_alloc(&sg, sizeof *url); 925 926 krl.rlim_cur = SCARG(uap, newlimit) * 512; 927 mtx_assert(&Giant, MA_OWNED); 928 krl.rlim_max = p->p_rlimit[RLIMIT_FSIZE].rlim_max; 929 930 error = copyout(&krl, url, sizeof(*url)); 931 if (error) 932 return error; 933 934 SCARG(&srl, which) = RLIMIT_FSIZE; 935 SCARG(&srl, rlp) = (struct orlimit *)url; 936 937 error = setrlimit(p, &srl); 938 if (error) 939 return error; 940 941 mtx_assert(&Giant, MA_OWNED); 942 *retval = p->p_rlimit[RLIMIT_FSIZE].rlim_cur; 943 if (*retval == -1) 944 *retval = 0x7fffffff; 945 return 0; 946 } 947 948 case SVR4_GMEMLIM: 949 { 950 struct vmspace *vm = p->p_vmspace; 951 register_t r; 952 953 mtx_assert(&Giant, MA_OWNED); 954 r = p->p_rlimit[RLIMIT_DATA].rlim_cur; 955 956 if (r == -1) 957 r = 0x7fffffff; 958 r += (long) vm->vm_daddr; 959 if (r < 0) 960 r = 0x7fffffff; 961 *retval = r; 962 return 0; 963 } 964 965 case SVR4_GDESLIM: 966 mtx_assert(&Giant, MA_OWNED); 967 *retval = p->p_rlimit[RLIMIT_NOFILE].rlim_cur; 968 if (*retval == -1) 969 *retval = 0x7fffffff; 970 return 0; 971 972 default: 973 return EINVAL; 974 } 975} 976 977static struct proc * 978svr4_pfind(pid) 979 pid_t pid; 980{ 981 struct proc *p; 982 983 /* look in the live processes */ 984 if ((p = pfind(pid)) == NULL) 985 /* look in the zombies */ 986 p = zpfind(pid); 987 988 return p; 989} 990 991 992int 993svr4_sys_pgrpsys(p, uap) 994 struct proc *p; 995 struct svr4_sys_pgrpsys_args *uap; 996{ 997 int *retval = p->p_retval; 998 999 switch (SCARG(uap, cmd)) { 1000 case 1: /* setpgrp() */ 1001 /* 1002 * SVR4 setpgrp() (which takes no arguments) has the 1003 * semantics that the session ID is also created anew, so 1004 * in almost every sense, setpgrp() is identical to 1005 * setsid() for SVR4. (Under BSD, the difference is that 1006 * a setpgid(0,0) will not create a new session.) 1007 */ 1008 setsid(p, NULL); 1009 /*FALLTHROUGH*/ 1010 1011 case 0: /* getpgrp() */ 1012 *retval = p->p_pgrp->pg_id; 1013 return 0; 1014 1015 case 2: /* getsid(pid) */ 1016 if (SCARG(uap, pid) != 0 && 1017 (p = svr4_pfind(SCARG(uap, pid))) == NULL) 1018 return ESRCH; 1019 /* 1020 * This has already been initialized to the pid of 1021 * the session leader. 1022 */ 1023 *retval = (register_t) p->p_session->s_leader->p_pid; 1024 return 0; 1025 1026 case 3: /* setsid() */ 1027 return setsid(p, NULL); 1028 1029 case 4: /* getpgid(pid) */ 1030 1031 if (SCARG(uap, pid) != 0 && 1032 (p = svr4_pfind(SCARG(uap, pid))) == NULL) 1033 return ESRCH; 1034 1035 *retval = (int) p->p_pgrp->pg_id; 1036 return 0; 1037 1038 case 5: /* setpgid(pid, pgid); */ 1039 { 1040 struct setpgid_args sa; 1041 1042 SCARG(&sa, pid) = SCARG(uap, pid); 1043 SCARG(&sa, pgid) = SCARG(uap, pgid); 1044 return setpgid(p, &sa); 1045 } 1046 1047 default: 1048 return EINVAL; 1049 } 1050} 1051 1052#define syscallarg(x) union { x datum; register_t pad; } 1053 1054struct svr4_hrtcntl_args { 1055 int cmd; 1056 int fun; 1057 int clk; 1058 svr4_hrt_interval_t * iv; 1059 svr4_hrt_time_t * ti; 1060}; 1061 1062 1063static int 1064svr4_hrtcntl(p, uap, retval) 1065 struct proc *p; 1066 struct svr4_hrtcntl_args *uap; 1067 register_t *retval; 1068{ 1069 switch (SCARG(uap, fun)) { 1070 case SVR4_HRT_CNTL_RES: 1071 DPRINTF(("htrcntl(RES)\n")); 1072 *retval = SVR4_HRT_USEC; 1073 return 0; 1074 1075 case SVR4_HRT_CNTL_TOFD: 1076 DPRINTF(("htrcntl(TOFD)\n")); 1077 { 1078 struct timeval tv; 1079 svr4_hrt_time_t t; 1080 if (SCARG(uap, clk) != SVR4_HRT_CLK_STD) { 1081 DPRINTF(("clk == %d\n", SCARG(uap, clk))); 1082 return EINVAL; 1083 } 1084 if (SCARG(uap, ti) == NULL) { 1085 DPRINTF(("ti NULL\n")); 1086 return EINVAL; 1087 } 1088 microtime(&tv); 1089 t.h_sec = tv.tv_sec; 1090 t.h_rem = tv.tv_usec; 1091 t.h_res = SVR4_HRT_USEC; 1092 return copyout(&t, SCARG(uap, ti), sizeof(t)); 1093 } 1094 1095 case SVR4_HRT_CNTL_START: 1096 DPRINTF(("htrcntl(START)\n")); 1097 return ENOSYS; 1098 1099 case SVR4_HRT_CNTL_GET: 1100 DPRINTF(("htrcntl(GET)\n")); 1101 return ENOSYS; 1102 default: 1103 DPRINTF(("Bad htrcntl command %d\n", SCARG(uap, fun))); 1104 return ENOSYS; 1105 } 1106} 1107 1108 1109int 1110svr4_sys_hrtsys(p, uap) 1111 struct proc *p; 1112 struct svr4_sys_hrtsys_args *uap; 1113{ 1114 int *retval = p->p_retval; 1115 1116 switch (SCARG(uap, cmd)) { 1117 case SVR4_HRT_CNTL: 1118 return svr4_hrtcntl(p, (struct svr4_hrtcntl_args *) uap, 1119 retval); 1120 1121 case SVR4_HRT_ALRM: 1122 DPRINTF(("hrtalarm\n")); 1123 return ENOSYS; 1124 1125 case SVR4_HRT_SLP: 1126 DPRINTF(("hrtsleep\n")); 1127 return ENOSYS; 1128 1129 case SVR4_HRT_CAN: 1130 DPRINTF(("hrtcancel\n")); 1131 return ENOSYS; 1132 1133 default: 1134 DPRINTF(("Bad hrtsys command %d\n", SCARG(uap, cmd))); 1135 return EINVAL; 1136 } 1137} 1138 1139 1140static int 1141svr4_setinfo(p, st, s) 1142 struct proc *p; 1143 int st; 1144 svr4_siginfo_t *s; 1145{ 1146 svr4_siginfo_t i; 1147 int sig; 1148 1149 memset(&i, 0, sizeof(i)); 1150 1151 i.si_signo = SVR4_SIGCHLD; 1152 i.si_errno = 0; /* XXX? */ 1153 1154 if (p) { 1155 i.si_pid = p->p_pid; 1156 mtx_enter(&sched_lock, MTX_SPIN); 1157 if (p->p_stat == SZOMB) { 1158 i.si_stime = p->p_ru->ru_stime.tv_sec; 1159 i.si_utime = p->p_ru->ru_utime.tv_sec; 1160 } 1161 else { 1162 i.si_stime = p->p_stats->p_ru.ru_stime.tv_sec; 1163 i.si_utime = p->p_stats->p_ru.ru_utime.tv_sec; 1164 } 1165 mtx_exit(&sched_lock, MTX_SPIN); 1166 } 1167 1168 if (WIFEXITED(st)) { 1169 i.si_status = WEXITSTATUS(st); 1170 i.si_code = SVR4_CLD_EXITED; 1171 } else if (WIFSTOPPED(st)) { 1172 sig = WSTOPSIG(st); 1173 if (sig >= 0 && sig < NSIG) 1174 i.si_status = SVR4_BSD2SVR4_SIG(sig); 1175 1176 if (i.si_status == SVR4_SIGCONT) 1177 i.si_code = SVR4_CLD_CONTINUED; 1178 else 1179 i.si_code = SVR4_CLD_STOPPED; 1180 } else { 1181 sig = WTERMSIG(st); 1182 if (sig >= 0 && sig < NSIG) 1183 i.si_status = SVR4_BSD2SVR4_SIG(sig); 1184 1185 if (WCOREDUMP(st)) 1186 i.si_code = SVR4_CLD_DUMPED; 1187 else 1188 i.si_code = SVR4_CLD_KILLED; 1189 } 1190 1191 DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n", 1192 i.si_pid, i.si_signo, i.si_code, i.si_errno, i.si_status)); 1193 1194 return copyout(&i, s, sizeof(i)); 1195} 1196 1197 1198int 1199svr4_sys_waitsys(p, uap) 1200 struct proc *p; 1201 struct svr4_sys_waitsys_args *uap; 1202{ 1203 int nfound; 1204 int error, *retval = p->p_retval; 1205 struct proc *q, *t; 1206 1207 1208 switch (SCARG(uap, grp)) { 1209 case SVR4_P_PID: 1210 break; 1211 1212 case SVR4_P_PGID: 1213 SCARG(uap, id) = -p->p_pgid; 1214 break; 1215 1216 case SVR4_P_ALL: 1217 SCARG(uap, id) = WAIT_ANY; 1218 break; 1219 1220 default: 1221 return EINVAL; 1222 } 1223 1224 DPRINTF(("waitsys(%d, %d, %p, %x)\n", 1225 SCARG(uap, grp), SCARG(uap, id), 1226 SCARG(uap, info), SCARG(uap, options))); 1227 1228loop: 1229 nfound = 0; 1230 PROCTREE_LOCK(PT_SHARED); 1231 LIST_FOREACH(q, &p->p_children, p_sibling) { 1232 if (SCARG(uap, id) != WAIT_ANY && 1233 q->p_pid != SCARG(uap, id) && 1234 q->p_pgid != -SCARG(uap, id)) { 1235 DPRINTF(("pid %d pgid %d != %d\n", q->p_pid, 1236 q->p_pgid, SCARG(uap, id))); 1237 continue; 1238 } 1239 nfound++; 1240 PROC_LOCK(q); 1241 mtx_enter(&sched_lock, MTX_SPIN); 1242 if (q->p_stat == SZOMB && 1243 ((SCARG(uap, options) & (SVR4_WEXITED|SVR4_WTRAPPED)))) { 1244 mtx_exit(&sched_lock, MTX_SPIN); 1245 PROC_UNLOCK(q); 1246 PROCTREE_LOCK(PT_RELEASE); 1247 *retval = 0; 1248 DPRINTF(("found %d\n", q->p_pid)); 1249 error = svr4_setinfo(q, q->p_xstat, SCARG(uap, info)); 1250 if (error != 0) 1251 return error; 1252 1253 1254 if ((SCARG(uap, options) & SVR4_WNOWAIT)) { 1255 DPRINTF(("Don't wait\n")); 1256 return 0; 1257 } 1258 1259 /* 1260 * If we got the child via ptrace(2) or procfs, and 1261 * the parent is different (meaning the process was 1262 * attached, rather than run as a child), then we need 1263 * to give it back to the old parent, and send the 1264 * parent a SIGCHLD. The rest of the cleanup will be 1265 * done when the old parent waits on the child. 1266 */ 1267 PROC_LOCK(q); 1268 if (q->p_flag & P_TRACED) { 1269 PROC_UNLOCK(q); 1270 PROCTREE_LOCK(PT_EXCLUSIVE); 1271 if (q->p_oppid != q->p_pptr->p_pid) { 1272 t = pfind(q->p_oppid); 1273 proc_reparent(q, t ? t : initproc); 1274 PROCTREE_LOCK(PT_RELEASE); 1275 PROC_LOCK(q); 1276 q->p_oppid = 0; 1277 q->p_flag &= ~(P_TRACED | P_WAITED); 1278 PROC_UNLOCK(q); 1279 PROCTREE_LOCK(PT_SHARED); 1280 wakeup((caddr_t)q->p_pptr); 1281 PROCTREE_LOCK(PT_RELEASE); 1282 return 0; 1283 } 1284 PROCTREE_LOCK(PT_RELEASE); 1285 } else 1286 PROC_UNLOCK(q); 1287 q->p_xstat = 0; 1288 ruadd(&p->p_stats->p_cru, q->p_ru); 1289 FREE(q->p_ru, M_ZOMBIE); 1290 q->p_ru = 0; 1291 1292 /* 1293 * Decrement the count of procs running with this uid. 1294 */ 1295 (void)chgproccnt(q->p_cred->p_uidinfo, -1, 0); 1296 1297 /* 1298 * Release reference to text vnode. 1299 */ 1300 if (q->p_textvp) 1301 vrele(q->p_textvp); 1302 1303 /* 1304 * Free up credentials. 1305 */ 1306 PROC_LOCK(q); 1307 if (--q->p_cred->p_refcnt == 0) { 1308 crfree(q->p_ucred); 1309 uifree(q->p_cred->p_uidinfo); 1310 FREE(q->p_cred, M_SUBPROC); 1311 q->p_cred = NULL; 1312 } 1313 1314 /* 1315 * Destroy empty prisons 1316 */ 1317 if (q->p_prison && !--q->p_prison->pr_ref) { 1318 if (q->p_prison->pr_linux != NULL) 1319 FREE(q->p_prison->pr_linux, M_PRISON); 1320 FREE(q->p_prison, M_PRISON); 1321 } 1322 1323 /* 1324 * Remove unused arguments 1325 */ 1326 if (q->p_args && --q->p_args->ar_ref == 0) 1327 FREE(q->p_args, M_PARGS); 1328 PROC_UNLOCK(q); 1329 1330 /* 1331 * Finally finished with old proc entry. 1332 * Unlink it from its process group and free it. 1333 */ 1334 leavepgrp(q); 1335 1336 ALLPROC_LOCK(AP_EXCLUSIVE); 1337 LIST_REMOVE(q, p_list); /* off zombproc */ 1338 ALLPROC_LOCK(AP_RELEASE); 1339 1340 PROCTREE_LOCK(PT_EXCLUSIVE); 1341 LIST_REMOVE(q, p_sibling); 1342 PROCTREE_LOCK(PT_RELEASE); 1343 1344 PROC_LOCK(q); 1345 if (--q->p_procsig->ps_refcnt == 0) { 1346 if (q->p_sigacts != &q->p_addr->u_sigacts) 1347 FREE(p->q_sigacts, M_SUBPROC); 1348 FREE(q->p_procsig, M_SUBPROC); 1349 q->p_procsig = NULL; 1350 } 1351 PROC_UNLOCK(q); 1352 1353 /* 1354 * Give machine-dependent layer a chance 1355 * to free anything that cpu_exit couldn't 1356 * release while still running in process context. 1357 */ 1358 cpu_wait(q); 1359#if defined(__NetBSD__) 1360 pool_put(&proc_pool, q); 1361#endif 1362#ifdef __FreeBSD__ 1363 mtx_destroy(&q->p_mtx); 1364 zfree(proc_zone, q); 1365#endif 1366 nprocs--; 1367 return 0; 1368 } 1369 if (q->p_stat == SSTOP && (q->p_flag & P_WAITED) == 0 && 1370 (q->p_flag & P_TRACED || 1371 (SCARG(uap, options) & (SVR4_WSTOPPED|SVR4_WCONTINUED)))) { 1372 mtx_exit(&sched_lock, MTX_SPIN); 1373 DPRINTF(("jobcontrol %d\n", q->p_pid)); 1374 if (((SCARG(uap, options) & SVR4_WNOWAIT)) == 0) 1375 q->p_flag |= P_WAITED; 1376 PROC_UNLOCK(q); 1377 *retval = 0; 1378 return svr4_setinfo(q, W_STOPCODE(q->p_xstat), 1379 SCARG(uap, info)); 1380 } 1381 mtx_exit(&sched_lock, MTX_SPIN); 1382 PROC_UNLOCK(q); 1383 } 1384 1385 if (nfound == 0) 1386 return ECHILD; 1387 1388 if (SCARG(uap, options) & SVR4_WNOHANG) { 1389 *retval = 0; 1390 if ((error = svr4_setinfo(NULL, 0, SCARG(uap, info))) != 0) 1391 return error; 1392 return 0; 1393 } 1394 1395 if ((error = tsleep((caddr_t)p, PWAIT | PCATCH, "svr4_wait", 0)) != 0) 1396 return error; 1397 goto loop; 1398} 1399 1400 1401static void 1402bsd_statfs_to_svr4_statvfs(bfs, sfs) 1403 const struct statfs *bfs; 1404 struct svr4_statvfs *sfs; 1405{ 1406 sfs->f_bsize = bfs->f_iosize; /* XXX */ 1407 sfs->f_frsize = bfs->f_bsize; 1408 sfs->f_blocks = bfs->f_blocks; 1409 sfs->f_bfree = bfs->f_bfree; 1410 sfs->f_bavail = bfs->f_bavail; 1411 sfs->f_files = bfs->f_files; 1412 sfs->f_ffree = bfs->f_ffree; 1413 sfs->f_favail = bfs->f_ffree; 1414 sfs->f_fsid = bfs->f_fsid.val[0]; 1415 memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype)); 1416 sfs->f_flag = 0; 1417 if (bfs->f_flags & MNT_RDONLY) 1418 sfs->f_flag |= SVR4_ST_RDONLY; 1419 if (bfs->f_flags & MNT_NOSUID) 1420 sfs->f_flag |= SVR4_ST_NOSUID; 1421 sfs->f_namemax = MAXNAMLEN; 1422 memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */ 1423 memset(sfs->f_filler, 0, sizeof(sfs->f_filler)); 1424} 1425 1426 1427static void 1428bsd_statfs_to_svr4_statvfs64(bfs, sfs) 1429 const struct statfs *bfs; 1430 struct svr4_statvfs64 *sfs; 1431{ 1432 sfs->f_bsize = bfs->f_iosize; /* XXX */ 1433 sfs->f_frsize = bfs->f_bsize; 1434 sfs->f_blocks = bfs->f_blocks; 1435 sfs->f_bfree = bfs->f_bfree; 1436 sfs->f_bavail = bfs->f_bavail; 1437 sfs->f_files = bfs->f_files; 1438 sfs->f_ffree = bfs->f_ffree; 1439 sfs->f_favail = bfs->f_ffree; 1440 sfs->f_fsid = bfs->f_fsid.val[0]; 1441 memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype)); 1442 sfs->f_flag = 0; 1443 if (bfs->f_flags & MNT_RDONLY) 1444 sfs->f_flag |= SVR4_ST_RDONLY; 1445 if (bfs->f_flags & MNT_NOSUID) 1446 sfs->f_flag |= SVR4_ST_NOSUID; 1447 sfs->f_namemax = MAXNAMLEN; 1448 memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */ 1449 memset(sfs->f_filler, 0, sizeof(sfs->f_filler)); 1450} 1451 1452 1453int 1454svr4_sys_statvfs(p, uap) 1455 struct proc *p; 1456 struct svr4_sys_statvfs_args *uap; 1457{ 1458 struct statfs_args fs_args; 1459 caddr_t sg = stackgap_init(); 1460 struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs)); 1461 struct statfs bfs; 1462 struct svr4_statvfs sfs; 1463 int error; 1464 1465 CHECKALTEXIST(p, &sg, SCARG(uap, path)); 1466 SCARG(&fs_args, path) = SCARG(uap, path); 1467 SCARG(&fs_args, buf) = fs; 1468 1469 if ((error = statfs(p, &fs_args)) != 0) 1470 return error; 1471 1472 if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0) 1473 return error; 1474 1475 bsd_statfs_to_svr4_statvfs(&bfs, &sfs); 1476 1477 return copyout(&sfs, SCARG(uap, fs), sizeof(sfs)); 1478} 1479 1480 1481int 1482svr4_sys_fstatvfs(p, uap) 1483 struct proc *p; 1484 struct svr4_sys_fstatvfs_args *uap; 1485{ 1486 struct fstatfs_args fs_args; 1487 caddr_t sg = stackgap_init(); 1488 struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs)); 1489 struct statfs bfs; 1490 struct svr4_statvfs sfs; 1491 int error; 1492 1493 SCARG(&fs_args, fd) = SCARG(uap, fd); 1494 SCARG(&fs_args, buf) = fs; 1495 1496 if ((error = fstatfs(p, &fs_args)) != 0) 1497 return error; 1498 1499 if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0) 1500 return error; 1501 1502 bsd_statfs_to_svr4_statvfs(&bfs, &sfs); 1503 1504 return copyout(&sfs, SCARG(uap, fs), sizeof(sfs)); 1505} 1506 1507 1508int 1509svr4_sys_statvfs64(p, uap) 1510 struct proc *p; 1511 struct svr4_sys_statvfs64_args *uap; 1512{ 1513 struct statfs_args fs_args; 1514 caddr_t sg = stackgap_init(); 1515 struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs)); 1516 struct statfs bfs; 1517 struct svr4_statvfs64 sfs; 1518 int error; 1519 1520 CHECKALTEXIST(p, &sg, SCARG(uap, path)); 1521 SCARG(&fs_args, path) = SCARG(uap, path); 1522 SCARG(&fs_args, buf) = fs; 1523 1524 if ((error = statfs(p, &fs_args)) != 0) 1525 return error; 1526 1527 if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0) 1528 return error; 1529 1530 bsd_statfs_to_svr4_statvfs64(&bfs, &sfs); 1531 1532 return copyout(&sfs, SCARG(uap, fs), sizeof(sfs)); 1533} 1534 1535 1536int 1537svr4_sys_fstatvfs64(p, uap) 1538 struct proc *p; 1539 struct svr4_sys_fstatvfs64_args *uap; 1540{ 1541 struct fstatfs_args fs_args; 1542 caddr_t sg = stackgap_init(); 1543 struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs)); 1544 struct statfs bfs; 1545 struct svr4_statvfs64 sfs; 1546 int error; 1547 1548 SCARG(&fs_args, fd) = SCARG(uap, fd); 1549 SCARG(&fs_args, buf) = fs; 1550 1551 if ((error = fstatfs(p, &fs_args)) != 0) 1552 return error; 1553 1554 if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0) 1555 return error; 1556 1557 bsd_statfs_to_svr4_statvfs64(&bfs, &sfs); 1558 1559 return copyout(&sfs, SCARG(uap, fs), sizeof(sfs)); 1560} 1561 1562int 1563svr4_sys_alarm(p, uap) 1564 struct proc *p; 1565 struct svr4_sys_alarm_args *uap; 1566{ 1567 int error; 1568 struct itimerval *itp, *oitp; 1569 struct setitimer_args sa; 1570 caddr_t sg = stackgap_init(); 1571 1572 itp = stackgap_alloc(&sg, sizeof(*itp)); 1573 oitp = stackgap_alloc(&sg, sizeof(*oitp)); 1574 timevalclear(&itp->it_interval); 1575 itp->it_value.tv_sec = SCARG(uap, sec); 1576 itp->it_value.tv_usec = 0; 1577 1578 SCARG(&sa, which) = ITIMER_REAL; 1579 SCARG(&sa, itv) = itp; 1580 SCARG(&sa, oitv) = oitp; 1581 error = setitimer(p, &sa); 1582 if (error) 1583 return error; 1584 if (oitp->it_value.tv_usec) 1585 oitp->it_value.tv_sec++; 1586 p->p_retval[0] = oitp->it_value.tv_sec; 1587 return 0; 1588 1589} 1590 1591int 1592svr4_sys_gettimeofday(p, uap) 1593 struct proc *p; 1594 struct svr4_sys_gettimeofday_args *uap; 1595{ 1596 if (SCARG(uap, tp)) { 1597 struct timeval atv; 1598 1599 microtime(&atv); 1600 return copyout(&atv, SCARG(uap, tp), sizeof (atv)); 1601 } 1602 1603 return 0; 1604} 1605 1606int 1607svr4_sys_facl(p, uap) 1608 struct proc *p; 1609 struct svr4_sys_facl_args *uap; 1610{ 1611 int *retval; 1612 1613 retval = p->p_retval; 1614 *retval = 0; 1615 1616 switch (SCARG(uap, cmd)) { 1617 case SVR4_SYS_SETACL: 1618 /* We don't support acls on any filesystem */ 1619 return ENOSYS; 1620 1621 case SVR4_SYS_GETACL: 1622 return copyout(retval, &SCARG(uap, num), 1623 sizeof(SCARG(uap, num))); 1624 1625 case SVR4_SYS_GETACLCNT: 1626 return 0; 1627 1628 default: 1629 return EINVAL; 1630 } 1631} 1632 1633 1634int 1635svr4_sys_acl(p, uap) 1636 struct proc *p; 1637 struct svr4_sys_acl_args *uap; 1638{ 1639 /* XXX: for now the same */ 1640 return svr4_sys_facl(p, (struct svr4_sys_facl_args *)uap); 1641} 1642 1643int 1644svr4_sys_auditsys(p, uap) 1645 struct proc *p; 1646 struct svr4_sys_auditsys_args *uap; 1647{ 1648 /* 1649 * XXX: Big brother is *not* watching. 1650 */ 1651 return 0; 1652} 1653 1654int 1655svr4_sys_memcntl(p, uap) 1656 struct proc *p; 1657 struct svr4_sys_memcntl_args *uap; 1658{ 1659 switch (SCARG(uap, cmd)) { 1660 case SVR4_MC_SYNC: 1661 { 1662 struct msync_args msa; 1663 1664 SCARG(&msa, addr) = SCARG(uap, addr); 1665 SCARG(&msa, len) = SCARG(uap, len); 1666 SCARG(&msa, flags) = (int)SCARG(uap, arg); 1667 1668 return msync(p, &msa); 1669 } 1670 case SVR4_MC_ADVISE: 1671 { 1672 struct madvise_args maa; 1673 1674 SCARG(&maa, addr) = SCARG(uap, addr); 1675 SCARG(&maa, len) = SCARG(uap, len); 1676 SCARG(&maa, behav) = (int)SCARG(uap, arg); 1677 1678 return madvise(p, &maa); 1679 } 1680 case SVR4_MC_LOCK: 1681 case SVR4_MC_UNLOCK: 1682 case SVR4_MC_LOCKAS: 1683 case SVR4_MC_UNLOCKAS: 1684 return EOPNOTSUPP; 1685 default: 1686 return ENOSYS; 1687 } 1688} 1689 1690 1691int 1692svr4_sys_nice(p, uap) 1693 struct proc *p; 1694 struct svr4_sys_nice_args *uap; 1695{ 1696 struct setpriority_args ap; 1697 int error; 1698 1699 SCARG(&ap, which) = PRIO_PROCESS; 1700 SCARG(&ap, who) = 0; 1701 SCARG(&ap, prio) = SCARG(uap, prio); 1702 1703 if ((error = setpriority(p, &ap)) != 0) 1704 return error; 1705 1706 /* the cast is stupid, but the structures are the same */ 1707 if ((error = getpriority(p, (struct getpriority_args *)&ap)) != 0) 1708 return error; 1709 1710 return 0; 1711} 1712 1713int 1714svr4_sys_resolvepath(p, uap) 1715 struct proc *p; 1716 struct svr4_sys_resolvepath_args *uap; 1717{ 1718 struct nameidata nd; 1719 int error, *retval = p->p_retval; 1720 1721 NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME, UIO_USERSPACE, 1722 SCARG(uap, path), p); 1723 1724 if ((error = namei(&nd)) != 0) 1725 return error; 1726 1727 if ((error = copyout(nd.ni_cnd.cn_pnbuf, SCARG(uap, buf), 1728 SCARG(uap, bufsiz))) != 0) 1729 goto bad; 1730 1731 *retval = strlen(nd.ni_cnd.cn_pnbuf) < SCARG(uap, bufsiz) ? 1732 strlen(nd.ni_cnd.cn_pnbuf) + 1 : SCARG(uap, bufsiz); 1733bad: 1734 NDFREE(&nd, NDF_ONLY_PNBUF); 1735 vput(nd.ni_vp); 1736 return error; 1737} 1738