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