1 /*- 2 * Copyright (c) 1994-1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 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 withough 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 * $Id: linux_misc.c,v 1.15 1996/03/10 23:25:17 peter Exp $ 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/sysproto.h> 34 #include <sys/kernel.h> 35 #include <sys/exec.h> 36 #include <sys/mman.h> 37 #include <sys/proc.h> 38 #include <sys/dirent.h> 39 #include <sys/file.h> 40 #include <sys/filedesc.h> 41 #include <sys/ioctl.h> 42 #include <sys/imgact_aout.h> 43 #include <sys/mount.h> 44 #include <sys/namei.h> 45 #include <sys/resource.h> 46 #include <sys/resourcevar.h> 47 #include <sys/stat.h> 48 #include <sys/sysctl.h> 49 #include <sys/times.h> 50 #include <sys/utsname.h> 51 #include <sys/vnode.h> 52 #include <sys/wait.h> 53 #include <sys/time.h> 54 55 #include <vm/vm.h> 56 #include <vm/vm_param.h> 57 #include <vm/pmap.h> 58 #include <vm/lock.h> 59 #include <vm/vm_kern.h> 60 #include <vm/vm_prot.h> 61 #include <vm/vm_map.h> 62 #include <vm/vm_extern.h> 63 64 #include <machine/cpu.h> 65 #include <machine/psl.h> 66 67 #include <i386/linux/linux.h> 68 #include <i386/linux/linux_proto.h> 69 #include <i386/linux/linux_util.h> 70 71 int 72 linux_alarm(struct proc *p, struct linux_alarm_args *args, int *retval) 73 { 74 struct itimerval it, old_it; 75 struct timeval tv; 76 int s; 77 78 #ifdef DEBUG 79 printf("Linux-emul(%d): alarm(%d)\n", p->p_pid, args->secs); 80 #endif 81 it.it_value.tv_sec = (long)args->secs; 82 it.it_value.tv_usec = 0; 83 it.it_interval.tv_sec = 0; 84 it.it_interval.tv_usec = 0; 85 s = splclock(); 86 old_it = p->p_realtimer; 87 tv = time; 88 if (timerisset(&old_it.it_value)) 89 if (timercmp(&old_it.it_value, &tv, <)) 90 timerclear(&old_it.it_value); 91 else 92 timevalsub(&old_it.it_value, &tv); 93 splx(s); 94 if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) 95 return EINVAL; 96 s = splclock(); 97 untimeout(realitexpire, (caddr_t)p); 98 tv = time; 99 if (timerisset(&it.it_value)) { 100 timevaladd(&it.it_value, &tv); 101 timeout(realitexpire, (caddr_t)p, hzto(&it.it_value)); 102 } 103 p->p_realtimer = it; 104 splx(s); 105 if (old_it.it_value.tv_usec) 106 old_it.it_value.tv_sec++; 107 *retval = old_it.it_value.tv_sec; 108 return 0; 109 } 110 111 int 112 linux_brk(struct proc *p, struct linux_brk_args *args, int *retval) 113 { 114 #if 0 115 struct vmspace *vm = p->p_vmspace; 116 vm_offset_t new, old; 117 int error; 118 119 if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr) 120 return EINVAL; 121 if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr) 122 > p->p_rlimit[RLIMIT_DATA].rlim_cur) 123 return ENOMEM; 124 125 old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize); 126 new = round_page((vm_offset_t)args->dsend); 127 *retval = old; 128 if ((new-old) > 0) { 129 if (swap_pager_full) 130 return ENOMEM; 131 error = vm_map_find(&vm->vm_map, NULL, 0, &old, (new-old), FALSE, 132 VM_PROT_ALL, VM_PROT_ALL, 0); 133 if (error) 134 return error; 135 vm->vm_dsize += btoc((new-old)); 136 *retval = (int)(vm->vm_daddr + ctob(vm->vm_dsize)); 137 } 138 return 0; 139 #else 140 struct vmspace *vm = p->p_vmspace; 141 vm_offset_t new, old; 142 struct obreak_args /* { 143 char * nsize; 144 } */ tmp; 145 146 #ifdef DEBUG 147 printf("Linux-emul(%d): brk(%08x)\n", p->p_pid, args->dsend); 148 #endif 149 old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize); 150 new = (vm_offset_t)args->dsend; 151 tmp.nsize = (char *) new; 152 if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp, retval)) 153 retval[0] = (int)new; 154 else 155 retval[0] = (int)old; 156 157 return 0; 158 #endif 159 } 160 161 int 162 linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval) 163 { 164 struct nameidata ni; 165 struct vnode *vp; 166 struct exec *a_out; 167 struct vattr attr; 168 unsigned long vmaddr, file_offset; 169 unsigned long buffer, bss_size; 170 char *ptr; 171 int error; 172 caddr_t sg; 173 int locked; 174 175 sg = stackgap_init(); 176 CHECKALTEXIST(p, &sg, args->library); 177 178 #ifdef DEBUG 179 printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, args->library); 180 #endif 181 182 a_out = NULL; 183 locked = 0; 184 vp = NULL; 185 186 NDINIT(&ni, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, args->library, p); 187 if (error = namei(&ni)) 188 goto cleanup; 189 190 vp = ni.ni_vp; 191 if (vp == NULL) { 192 error = ENOEXEC; /* ?? */ 193 goto cleanup; 194 } 195 196 /* 197 * From here on down, we have a locked vnode that must be unlocked. 198 */ 199 locked++; 200 201 /* 202 * Writable? 203 */ 204 if (vp->v_writecount) { 205 error = ETXTBSY; 206 goto cleanup; 207 } 208 209 /* 210 * Executable? 211 */ 212 if (error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) 213 goto cleanup; 214 215 if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || 216 ((attr.va_mode & 0111) == 0) || 217 (attr.va_type != VREG)) { 218 error = ENOEXEC; 219 goto cleanup; 220 } 221 222 /* 223 * Sensible size? 224 */ 225 if (attr.va_size == 0) { 226 error = ENOEXEC; 227 goto cleanup; 228 } 229 230 /* 231 * Can we access it? 232 */ 233 if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) 234 goto cleanup; 235 236 if (error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) 237 goto cleanup; 238 239 /* 240 * Lock no longer needed 241 */ 242 VOP_UNLOCK(vp); 243 locked = 0; 244 245 /* 246 * Pull in executable header into kernel_map 247 */ 248 error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, 249 VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0); 250 if (error) 251 goto cleanup; 252 253 /* 254 * Is it a Linux binary ? 255 */ 256 if (((a_out->a_magic >> 16) & 0xff) != 0x64) { 257 error = ENOEXEC; 258 goto cleanup; 259 } 260 261 /* While we are here, we should REALLY do some more checks */ 262 263 /* 264 * Set file/virtual offset based on a.out variant. 265 */ 266 switch ((int)(a_out->a_magic & 0xffff)) { 267 case 0413: /* ZMAGIC */ 268 file_offset = 1024; 269 break; 270 case 0314: /* QMAGIC */ 271 file_offset = 0; 272 break; 273 default: 274 error = ENOEXEC; 275 goto cleanup; 276 } 277 278 bss_size = round_page(a_out->a_bss); 279 280 /* 281 * Check various fields in header for validity/bounds. 282 */ 283 if (a_out->a_text % NBPG || a_out->a_data % NBPG) { 284 error = ENOEXEC; 285 goto cleanup; 286 } 287 288 /* text + data can't exceed file size */ 289 if (a_out->a_data + a_out->a_text > attr.va_size) { 290 error = EFAULT; 291 goto cleanup; 292 } 293 294 /* 295 * text/data/bss must not exceed limits 296 * XXX: this is not complete. it should check current usage PLUS 297 * the resources needed by this library. 298 */ 299 if (a_out->a_text > MAXTSIZ || a_out->a_data + bss_size > MAXDSIZ || 300 a_out->a_data+bss_size > p->p_rlimit[RLIMIT_DATA].rlim_cur) { 301 error = ENOMEM; 302 goto cleanup; 303 } 304 305 /* 306 * prevent more writers 307 */ 308 vp->v_flag |= VTEXT; 309 310 /* 311 * Check if file_offset page aligned,. 312 * Currently we cannot handle misalinged file offsets, 313 * and so we read in the entire image (what a waste). 314 */ 315 if (file_offset & PGOFSET) { 316 #ifdef DEBUG 317 printf("uselib: Non page aligned binary %d\n", file_offset); 318 #endif 319 /* 320 * Map text+data read/write/execute 321 */ 322 323 /* a_entry is the load address and is page aligned */ 324 vmaddr = trunc_page(a_out->a_entry); 325 326 /* get anon user mapping, read+write+execute */ 327 error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, 328 a_out->a_text + a_out->a_data, FALSE, 329 VM_PROT_ALL, VM_PROT_ALL, 0); 330 if (error) 331 goto cleanup; 332 333 /* map file into kernel_map */ 334 error = vm_mmap(kernel_map, &buffer, 335 round_page(a_out->a_text + a_out->a_data + file_offset), 336 VM_PROT_READ, VM_PROT_READ, 0, 337 (caddr_t)vp, trunc_page(file_offset)); 338 if (error) 339 goto cleanup; 340 341 /* copy from kernel VM space to user space */ 342 error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr, 343 a_out->a_text + a_out->a_data); 344 345 /* release temporary kernel space */ 346 vm_map_remove(kernel_map, buffer, 347 buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); 348 349 if (error) 350 goto cleanup; 351 } 352 else { 353 #ifdef DEBUG 354 printf("uselib: Page aligned binary %d\n", file_offset); 355 #endif 356 /* 357 * for QMAGIC, a_entry is 20 bytes beyond the load address 358 * to skip the executable header 359 */ 360 vmaddr = trunc_page(a_out->a_entry); 361 362 /* 363 * Map it all into the process's space as a single copy-on-write 364 * "data" segment. 365 */ 366 error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr, 367 a_out->a_text + a_out->a_data, 368 VM_PROT_ALL, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, 369 (caddr_t)vp, file_offset); 370 if (error) 371 goto cleanup; 372 } 373 #ifdef DEBUG 374 printf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]); 375 #endif 376 if (bss_size != 0) { 377 /* 378 * Calculate BSS start address 379 */ 380 vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + a_out->a_data; 381 382 /* 383 * allocate some 'anon' space 384 */ 385 error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, 386 bss_size, FALSE, 387 VM_PROT_ALL, VM_PROT_ALL, 0); 388 if (error) 389 goto cleanup; 390 } 391 392 cleanup: 393 /* 394 * Unlock vnode if needed 395 */ 396 if (locked) 397 VOP_UNLOCK(vp); 398 399 /* 400 * Release the kernel mapping. 401 */ 402 if (a_out) 403 vm_map_remove(kernel_map, (vm_offset_t)a_out, (vm_offset_t)a_out + PAGE_SIZE); 404 405 return error; 406 } 407 408 /* XXX move */ 409 struct linux_select_argv { 410 int nfds; 411 fd_set *readfds; 412 fd_set *writefds; 413 fd_set *exceptfds; 414 struct timeval *timeout; 415 }; 416 417 int 418 linux_select(struct proc *p, struct linux_select_args *args, int *retval) 419 { 420 struct linux_select_argv linux_args; 421 struct linux_newselect_args newsel; 422 int error; 423 424 #ifdef SELECT_DEBUG 425 printf("Linux-emul(%d): select(%x)\n", 426 p->p_pid, args->ptr); 427 #endif 428 if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args, 429 sizeof(linux_args)))) 430 return error; 431 432 newsel.nfds = linux_args.nfds; 433 newsel.readfds = linux_args.readfds; 434 newsel.writefds = linux_args.writefds; 435 newsel.exceptfds = linux_args.exceptfds; 436 newsel.timeout = linux_args.timeout; 437 438 return linux_newselect(p, &newsel, retval); 439 } 440 441 int 442 linux_newselect(struct proc *p, struct linux_newselect_args *args, int *retval) 443 { 444 struct select_args bsa; 445 struct timeval tv0, tv1, utv, *tvp; 446 caddr_t sg; 447 int error; 448 449 #ifdef DEBUG 450 printf("Linux-emul(%d): newselect(%d, %x, %x, %x, %x)\n", 451 p->p_pid, args->nfds, args->readfds, args->writefds, 452 args->exceptfds, args->timeout); 453 #endif 454 error = 0; 455 bsa.nd = args->nfds; 456 bsa.in = args->readfds; 457 bsa.ou = args->writefds; 458 bsa.ex = args->exceptfds; 459 bsa.tv = args->timeout; 460 461 /* 462 * Store current time for computation of the amount of 463 * time left. 464 */ 465 if (args->timeout) { 466 if ((error = copyin(args->timeout, &utv, sizeof(utv)))) 467 goto select_out; 468 #ifdef DEBUG 469 printf("Linux-emul(%d): incoming timeout (%d/%d)\n", 470 p->p_pid, utv.tv_sec, utv.tv_usec); 471 #endif 472 if (itimerfix(&utv)) { 473 /* 474 * The timeval was invalid. Convert it to something 475 * valid that will act as it does under Linux. 476 */ 477 sg = stackgap_init(); 478 tvp = stackgap_alloc(&sg, sizeof(utv)); 479 utv.tv_sec += utv.tv_usec / 1000000; 480 utv.tv_usec %= 1000000; 481 if (utv.tv_usec < 0) { 482 utv.tv_sec -= 1; 483 utv.tv_usec += 1000000; 484 } 485 if (utv.tv_sec < 0) 486 timerclear(&utv); 487 if ((error = copyout(&utv, tvp, sizeof(utv)))) 488 goto select_out; 489 bsa.tv = tvp; 490 } 491 microtime(&tv0); 492 } 493 494 error = select(p, &bsa, retval); 495 #ifdef DEBUG 496 printf("Linux-emul(%d): real select returns %d\n", 497 p->p_pid, error); 498 #endif 499 500 if (error) { 501 /* 502 * See fs/select.c in the Linux kernel. Without this, 503 * Maelstrom doesn't work. 504 */ 505 if (error == ERESTART) 506 error = EINTR; 507 goto select_out; 508 } 509 510 if (args->timeout) { 511 if (*retval) { 512 /* 513 * Compute how much time was left of the timeout, 514 * by subtracting the current time and the time 515 * before we started the call, and subtracting 516 * that result from the user-supplied value. 517 */ 518 microtime(&tv1); 519 timevalsub(&tv1, &tv0); 520 timevalsub(&utv, &tv1); 521 if (utv.tv_sec < 0) 522 timerclear(&utv); 523 } else 524 timerclear(&utv); 525 #ifdef DEBUG 526 printf("Linux-emul(%d): outgoing timeout (%d/%d)\n", 527 p->p_pid, utv.tv_sec, utv.tv_usec); 528 #endif 529 if ((error = copyout(&utv, args->timeout, sizeof(utv)))) 530 goto select_out; 531 } 532 533 select_out: 534 #ifdef DEBUG 535 printf("Linux-emul(%d): newselect_out -> %d\n", 536 p->p_pid, error); 537 #endif 538 return error; 539 } 540 541 int 542 linux_getpgid(struct proc *p, struct linux_getpgid_args *args, int *retval) 543 { 544 struct proc *curproc; 545 546 #ifdef DEBUG 547 printf("Linux-emul(%d): getpgid(%d)\n", p->p_pid, args->pid); 548 #endif 549 if (args->pid != p->p_pid) { 550 if (!(curproc = pfind(args->pid))) 551 return ESRCH; 552 } 553 else 554 curproc = p; 555 *retval = curproc->p_pgid; 556 return 0; 557 } 558 559 int 560 linux_fork(struct proc *p, struct linux_fork_args *args, int *retval) 561 { 562 int error; 563 564 #ifdef DEBUG 565 printf("Linux-emul(%d): fork()\n", p->p_pid); 566 #endif 567 if (error = fork(p, (struct fork_args *)args, retval)) 568 return error; 569 if (retval[1] == 1) 570 retval[0] = 0; 571 return 0; 572 } 573 574 /* XXX move */ 575 struct linux_mmap_argv { 576 linux_caddr_t addr; 577 int len; 578 int prot; 579 int flags; 580 int fd; 581 int pos; 582 }; 583 584 int 585 linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval) 586 { 587 struct mmap_args /* { 588 caddr_t addr; 589 size_t len; 590 int prot; 591 int flags; 592 int fd; 593 long pad; 594 off_t pos; 595 } */ bsd_args; 596 int error; 597 struct linux_mmap_argv linux_args; 598 599 if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args, 600 sizeof(linux_args)))) 601 return error; 602 #ifdef DEBUG 603 printf("Linux-emul(%d): mmap(%08x, %d, %d, %08x, %d, %d)\n", 604 p->p_pid, linux_args.addr, linux_args.len, linux_args.prot, 605 linux_args.flags, linux_args.fd, linux_args.pos); 606 #endif 607 bsd_args.flags = 0; 608 if (linux_args.flags & LINUX_MAP_SHARED) 609 bsd_args.flags |= MAP_SHARED; 610 if (linux_args.flags & LINUX_MAP_PRIVATE) 611 bsd_args.flags |= MAP_PRIVATE; 612 if (linux_args.flags & LINUX_MAP_FIXED) 613 bsd_args.flags |= MAP_FIXED; 614 if (linux_args.flags & LINUX_MAP_ANON) 615 bsd_args.flags |= MAP_ANON; 616 bsd_args.addr = linux_args.addr; 617 bsd_args.len = linux_args.len; 618 bsd_args.prot = linux_args.prot; 619 bsd_args.fd = linux_args.fd; 620 bsd_args.pos = linux_args.pos; 621 bsd_args.pad = 0; 622 return mmap(p, &bsd_args, retval); 623 } 624 625 int 626 linux_msync(struct proc *p, struct linux_msync_args *args, int *retval) 627 { 628 struct msync_args bsd_args; 629 630 bsd_args.addr = args->addr; 631 bsd_args.len = args->len; 632 bsd_args.flags = 0; /* XXX ignore */ 633 634 return msync(p, &bsd_args, retval); 635 } 636 637 int 638 linux_pipe(struct proc *p, struct linux_pipe_args *args, int *retval) 639 { 640 int error; 641 642 #ifdef DEBUG 643 printf("Linux-emul(%d): pipe(*)\n", p->p_pid); 644 #endif 645 if (error = pipe(p, 0, retval)) 646 return error; 647 if (error = copyout(retval, args->pipefds, 2*sizeof(int))) 648 return error; 649 *retval = 0; 650 return 0; 651 } 652 653 int 654 linux_time(struct proc *p, struct linux_time_args *args, int *retval) 655 { 656 struct timeval tv; 657 linux_time_t tm; 658 int error; 659 660 #ifdef DEBUG 661 printf("Linux-emul(%d): time(*)\n", p->p_pid); 662 #endif 663 microtime(&tv); 664 tm = tv.tv_sec; 665 if (args->tm && (error = copyout(&tm, args->tm, sizeof(linux_time_t)))) 666 return error; 667 *retval = tm; 668 return 0; 669 } 670 671 struct linux_times_argv { 672 long tms_utime; 673 long tms_stime; 674 long tms_cutime; 675 long tms_cstime; 676 }; 677 678 #define CLK_TCK 100 /* Linux uses 100 */ 679 #define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) 680 681 int 682 linux_times(struct proc *p, struct linux_times_args *args, int *retval) 683 { 684 struct timeval tv; 685 struct linux_times_argv tms; 686 struct rusage ru; 687 int error, s; 688 689 #ifdef DEBUG 690 printf("Linux-emul(%d): times(*)\n", p->p_pid); 691 #endif 692 calcru(p, &ru.ru_utime, &ru.ru_stime, NULL); 693 694 tms.tms_utime = CONVTCK(ru.ru_utime); 695 tms.tms_stime = CONVTCK(ru.ru_stime); 696 697 tms.tms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime); 698 tms.tms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime); 699 700 if ((error = copyout((caddr_t)&tms, (caddr_t)args->buf, 701 sizeof(struct linux_times_argv)))) 702 return error; 703 704 microtime(&tv); 705 timevalsub(&tv, &boottime); 706 *retval = (int)CONVTCK(tv); 707 return 0; 708 } 709 710 /* XXX move */ 711 struct linux_newuname_t { 712 char sysname[65]; 713 char nodename[65]; 714 char release[65]; 715 char version[65]; 716 char machine[65]; 717 char domainname[65]; 718 }; 719 720 int 721 linux_newuname(struct proc *p, struct linux_newuname_args *args, int *retval) 722 { 723 struct linux_newuname_t linux_newuname; 724 725 #ifdef DEBUG 726 printf("Linux-emul(%d): newuname(*)\n", p->p_pid); 727 #endif 728 bzero(&linux_newuname, sizeof(struct linux_newuname_args)); 729 strncpy(linux_newuname.sysname, ostype, 64); 730 strncpy(linux_newuname.nodename, hostname, 64); 731 strncpy(linux_newuname.release, osrelease, 64); 732 strncpy(linux_newuname.version, version, 64); 733 strncpy(linux_newuname.machine, machine, 64); 734 strncpy(linux_newuname.domainname, domainname, 64); 735 return (copyout((caddr_t)&linux_newuname, (caddr_t)args->buf, 736 sizeof(struct linux_newuname_t))); 737 } 738 739 struct linux_utimbuf { 740 linux_time_t l_actime; 741 linux_time_t l_modtime; 742 }; 743 744 int 745 linux_utime(struct proc *p, struct linux_utime_args *args, int *retval) 746 { 747 struct utimes_args /* { 748 char *path; 749 struct timeval *tptr; 750 } */ bsdutimes; 751 struct timeval tv[2], *tvp; 752 struct linux_utimbuf lut; 753 int error; 754 caddr_t sg; 755 756 sg = stackgap_init(); 757 CHECKALTEXIST(p, &sg, args->fname); 758 759 #ifdef DEBUG 760 printf("Linux-emul(%d): utime(%s, *)\n", p->p_pid, args->fname); 761 #endif 762 if (args->times) { 763 if ((error = copyin(args->times, &lut, sizeof lut))) 764 return error; 765 tv[0].tv_sec = lut.l_actime; 766 tv[0].tv_usec = 0; 767 tv[1].tv_sec = lut.l_modtime; 768 tv[1].tv_usec = 0; 769 /* so that utimes can copyin */ 770 tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv)); 771 if ((error = copyout(tv, tvp, sizeof(tv)))) 772 return error; 773 bsdutimes.tptr = tvp; 774 } else 775 bsdutimes.tptr = NULL; 776 777 bsdutimes.path = args->fname; 778 return utimes(p, &bsdutimes, retval); 779 } 780 781 int 782 linux_waitpid(struct proc *p, struct linux_waitpid_args *args, int *retval) 783 { 784 struct wait_args /* { 785 int pid; 786 int *status; 787 int options; 788 struct rusage *rusage; 789 } */ tmp; 790 int error, tmpstat; 791 792 #ifdef DEBUG 793 printf("Linux-emul(%d): waitpid(%d, 0x%x, %d)\n", 794 p->p_pid, args->pid, args->status, args->options); 795 #endif 796 tmp.pid = args->pid; 797 tmp.status = args->status; 798 tmp.options = args->options; 799 tmp.rusage = NULL; 800 801 if (error = wait4(p, &tmp, retval)) 802 return error; 803 if (args->status) { 804 if (error = copyin(args->status, &tmpstat, sizeof(int))) 805 return error; 806 if (WIFSIGNALED(tmpstat)) 807 tmpstat = (tmpstat & 0xffffff80) | 808 bsd_to_linux_signal[WTERMSIG(tmpstat)]; 809 else if (WIFSTOPPED(tmpstat)) 810 tmpstat = (tmpstat & 0xffff00ff) | 811 (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8); 812 return copyout(&tmpstat, args->status, sizeof(int)); 813 } else 814 return 0; 815 } 816 817 int 818 linux_wait4(struct proc *p, struct linux_wait4_args *args, int *retval) 819 { 820 struct wait_args /* { 821 int pid; 822 int *status; 823 int options; 824 struct rusage *rusage; 825 } */ tmp; 826 int error, tmpstat; 827 828 #ifdef DEBUG 829 printf("Linux-emul(%d): wait4(%d, 0x%x, %d, 0x%x)\n", 830 p->p_pid, args->pid, args->status, args->options, args->rusage); 831 #endif 832 tmp.pid = args->pid; 833 tmp.status = args->status; 834 tmp.options = args->options; 835 tmp.rusage = args->rusage; 836 837 if (error = wait4(p, &tmp, retval)) 838 return error; 839 840 p->p_siglist &= ~sigmask(SIGCHLD); 841 842 if (args->status) { 843 if (error = copyin(args->status, &tmpstat, sizeof(int))) 844 return error; 845 if (WIFSIGNALED(tmpstat)) 846 tmpstat = (tmpstat & 0xffffff80) | 847 bsd_to_linux_signal[WTERMSIG(tmpstat)]; 848 else if (WIFSTOPPED(tmpstat)) 849 tmpstat = (tmpstat & 0xffff00ff) | 850 (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8); 851 return copyout(&tmpstat, args->status, sizeof(int)); 852 } else 853 return 0; 854 } 855 856 int 857 linux_mknod(struct proc *p, struct linux_mknod_args *args, int *retval) 858 { 859 caddr_t sg; 860 struct mknod_args bsd_mknod; 861 struct mkfifo_args bsd_mkfifo; 862 863 sg = stackgap_init(); 864 865 CHECKALTCREAT(p, &sg, args->path); 866 867 #ifdef DEBUG 868 printf("Linux-emul(%d): mknod(%s, %d, %d)\n", 869 p->p_pid, args->path, args->mode, args->dev); 870 #endif 871 872 if (args->mode & S_IFIFO) { 873 bsd_mkfifo.path = args->path; 874 bsd_mkfifo.mode = args->mode; 875 return mkfifo(p, &bsd_mkfifo, retval); 876 } else { 877 bsd_mknod.path = args->path; 878 bsd_mknod.mode = args->mode; 879 bsd_mknod.dev = args->dev; 880 return mknod(p, &bsd_mknod, retval); 881 } 882 } 883 884 /* 885 * UGH! This is just about the dumbest idea I've ever heard!! 886 */ 887 int 888 linux_personality(struct proc *p, struct linux_personality_args *args, 889 int *retval) 890 { 891 #ifdef DEBUG 892 printf("Linux-emul(%d): personality(%d)\n", 893 p->p_pid, args->per); 894 #endif 895 if (args->per != 0) 896 return EINVAL; 897 898 /* Yes Jim, it's still a Linux... */ 899 retval[0] = 0; 900 return 0; 901 } 902 903 /* 904 * Wrappers for get/setitimer for debugging.. 905 */ 906 int 907 linux_setitimer(struct proc *p, struct linux_setitimer_args *args, int *retval) 908 { 909 struct setitimer_args bsa; 910 struct itimerval foo; 911 int error; 912 913 #ifdef DEBUG 914 printf("Linux-emul(%d): setitimer(%08x, %08x)\n", 915 p->p_pid, args->itv, args->oitv); 916 #endif 917 bsa.which = args->which; 918 bsa.itv = args->itv; 919 bsa.oitv = args->oitv; 920 if (args->itv) { 921 if ((error = copyin((caddr_t)args->itv, (caddr_t)&foo, 922 sizeof(foo)))) 923 return error; 924 #ifdef DEBUG 925 printf("setitimer: value: sec: %d, usec: %d\n", foo.it_value.tv_sec, foo.it_value.tv_usec); 926 printf("setitimer: interval: sec: %d, usec: %d\n", foo.it_interval.tv_sec, foo.it_interval.tv_usec); 927 #endif 928 } 929 return setitimer(p, &bsa, retval); 930 } 931 932 int 933 linux_getitimer(struct proc *p, struct linux_getitimer_args *args, int *retval) 934 { 935 struct getitimer_args bsa; 936 #ifdef DEBUG 937 printf("Linux-emul(%d): getitimer(%08x)\n", 938 p->p_pid, args->itv); 939 #endif 940 bsa.which = args->which; 941 bsa.itv = args->itv; 942 return getitimer(p, &bsa, retval); 943 } 944