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