freebsd32_misc.c revision 159412
1/*- 2 * Copyright (c) 2002 Doug Rabson 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 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 159412 2006-06-08 18:33:08Z ps $"); 29 30#include "opt_compat.h" 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/bus.h> 35#include <sys/exec.h> 36#include <sys/fcntl.h> 37#include <sys/filedesc.h> 38#include <sys/namei.h> 39#include <sys/imgact.h> 40#include <sys/kernel.h> 41#include <sys/lock.h> 42#include <sys/malloc.h> 43#include <sys/file.h> /* Must come after sys/malloc.h */ 44#include <sys/mbuf.h> 45#include <sys/mman.h> 46#include <sys/module.h> 47#include <sys/mount.h> 48#include <sys/mutex.h> 49#include <sys/namei.h> 50#include <sys/param.h> 51#include <sys/proc.h> 52#include <sys/reboot.h> 53#include <sys/resource.h> 54#include <sys/resourcevar.h> 55#include <sys/selinfo.h> 56#include <sys/eventvar.h> /* Must come after sys/selinfo.h */ 57#include <sys/pipe.h> /* Must come after sys/selinfo.h */ 58#include <sys/signal.h> 59#include <sys/signalvar.h> 60#include <sys/socket.h> 61#include <sys/socketvar.h> 62#include <sys/stat.h> 63#include <sys/syscall.h> 64#include <sys/syscallsubr.h> 65#include <sys/sysctl.h> 66#include <sys/sysent.h> 67#include <sys/sysproto.h> 68#include <sys/systm.h> 69#include <sys/unistd.h> 70#include <sys/vnode.h> 71#include <sys/wait.h> 72#include <sys/ipc.h> 73#include <sys/shm.h> 74 75#include <vm/vm.h> 76#include <vm/vm_kern.h> 77#include <vm/vm_param.h> 78#include <vm/pmap.h> 79#include <vm/vm_map.h> 80#include <vm/vm_object.h> 81#include <vm/vm_extern.h> 82 83#include <machine/cpu.h> 84 85#include <compat/freebsd32/freebsd32_util.h> 86#include <compat/freebsd32/freebsd32.h> 87#include <compat/freebsd32/freebsd32_proto.h> 88 89CTASSERT(sizeof(struct timeval32) == 8); 90CTASSERT(sizeof(struct timespec32) == 8); 91CTASSERT(sizeof(struct statfs32) == 256); 92CTASSERT(sizeof(struct rusage32) == 72); 93 94int 95freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap) 96{ 97 int error, status; 98 struct rusage32 ru32; 99 struct rusage ru, *rup; 100 101 if (uap->rusage != NULL) 102 rup = &ru; 103 else 104 rup = NULL; 105 error = kern_wait(td, uap->pid, &status, uap->options, rup); 106 if (error) 107 return (error); 108 if (uap->status != NULL) 109 error = copyout(&status, uap->status, sizeof(status)); 110 if (uap->rusage != NULL && error == 0) { 111 TV_CP(ru, ru32, ru_utime); 112 TV_CP(ru, ru32, ru_stime); 113 CP(ru, ru32, ru_maxrss); 114 CP(ru, ru32, ru_ixrss); 115 CP(ru, ru32, ru_idrss); 116 CP(ru, ru32, ru_isrss); 117 CP(ru, ru32, ru_minflt); 118 CP(ru, ru32, ru_majflt); 119 CP(ru, ru32, ru_nswap); 120 CP(ru, ru32, ru_inblock); 121 CP(ru, ru32, ru_oublock); 122 CP(ru, ru32, ru_msgsnd); 123 CP(ru, ru32, ru_msgrcv); 124 CP(ru, ru32, ru_nsignals); 125 CP(ru, ru32, ru_nvcsw); 126 CP(ru, ru32, ru_nivcsw); 127 error = copyout(&ru32, uap->rusage, sizeof(ru32)); 128 } 129 return (error); 130} 131 132#ifdef COMPAT_FREEBSD4 133static void 134copy_statfs(struct statfs *in, struct statfs32 *out) 135{ 136 137 bzero(out, sizeof(*out)); 138 CP(*in, *out, f_bsize); 139 CP(*in, *out, f_iosize); 140 CP(*in, *out, f_blocks); 141 CP(*in, *out, f_bfree); 142 CP(*in, *out, f_bavail); 143 CP(*in, *out, f_files); 144 CP(*in, *out, f_ffree); 145 CP(*in, *out, f_fsid); 146 CP(*in, *out, f_owner); 147 CP(*in, *out, f_type); 148 CP(*in, *out, f_flags); 149 CP(*in, *out, f_flags); 150 CP(*in, *out, f_syncwrites); 151 CP(*in, *out, f_asyncwrites); 152 strlcpy(out->f_fstypename, 153 in->f_fstypename, MFSNAMELEN); 154 strlcpy(out->f_mntonname, 155 in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 156 CP(*in, *out, f_syncreads); 157 CP(*in, *out, f_asyncreads); 158 strlcpy(out->f_mntfromname, 159 in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 160} 161#endif 162 163#ifdef COMPAT_FREEBSD4 164int 165freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap) 166{ 167 struct statfs *buf, *sp; 168 struct statfs32 stat32; 169 size_t count, size; 170 int error; 171 172 count = uap->bufsize / sizeof(struct statfs32); 173 size = count * sizeof(struct statfs); 174 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags); 175 if (size > 0) { 176 count = td->td_retval[0]; 177 sp = buf; 178 while (count > 0 && error == 0) { 179 copy_statfs(sp, &stat32); 180 error = copyout(&stat32, uap->buf, sizeof(stat32)); 181 sp++; 182 uap->buf++; 183 count--; 184 } 185 free(buf, M_TEMP); 186 } 187 return (error); 188} 189#endif 190 191struct sigaltstack32 { 192 u_int32_t ss_sp; 193 u_int32_t ss_size; 194 int ss_flags; 195}; 196 197CTASSERT(sizeof(struct sigaltstack32) == 12); 198 199int 200freebsd32_sigaltstack(struct thread *td, 201 struct freebsd32_sigaltstack_args *uap) 202{ 203 struct sigaltstack32 s32; 204 struct sigaltstack ss, oss, *ssp; 205 int error; 206 207 if (uap->ss != NULL) { 208 error = copyin(uap->ss, &s32, sizeof(s32)); 209 if (error) 210 return (error); 211 PTRIN_CP(s32, ss, ss_sp); 212 CP(s32, ss, ss_size); 213 CP(s32, ss, ss_flags); 214 ssp = &ss; 215 } else 216 ssp = NULL; 217 error = kern_sigaltstack(td, ssp, &oss); 218 if (error == 0 && uap->oss != NULL) { 219 PTROUT_CP(oss, s32, ss_sp); 220 CP(oss, s32, ss_size); 221 CP(oss, s32, ss_flags); 222 error = copyout(&s32, uap->oss, sizeof(s32)); 223 } 224 return (error); 225} 226 227/* 228 * Custom version of exec_copyin_args() so that we can translate 229 * the pointers. 230 */ 231static int 232freebsd32_exec_copyin_args(struct image_args *args, char *fname, 233 enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv) 234{ 235 char *argp, *envp; 236 u_int32_t *p32, arg; 237 size_t length; 238 int error; 239 240 bzero(args, sizeof(*args)); 241 if (argv == NULL) 242 return (EFAULT); 243 244 /* 245 * Allocate temporary demand zeroed space for argument and 246 * environment strings 247 */ 248 args->buf = (char *) kmem_alloc_wait(exec_map, 249 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 250 if (args->buf == NULL) 251 return (ENOMEM); 252 args->begin_argv = args->buf; 253 args->endp = args->begin_argv; 254 args->stringspace = ARG_MAX; 255 256 args->fname = args->buf + ARG_MAX; 257 258 /* 259 * Copy the file name. 260 */ 261 error = (segflg == UIO_SYSSPACE) ? 262 copystr(fname, args->fname, PATH_MAX, &length) : 263 copyinstr(fname, args->fname, PATH_MAX, &length); 264 if (error != 0) 265 goto err_exit; 266 267 /* 268 * extract arguments first 269 */ 270 p32 = argv; 271 for (;;) { 272 error = copyin(p32++, &arg, sizeof(arg)); 273 if (error) 274 goto err_exit; 275 if (arg == 0) 276 break; 277 argp = PTRIN(arg); 278 error = copyinstr(argp, args->endp, args->stringspace, &length); 279 if (error) { 280 if (error == ENAMETOOLONG) 281 error = E2BIG; 282 goto err_exit; 283 } 284 args->stringspace -= length; 285 args->endp += length; 286 args->argc++; 287 } 288 289 args->begin_envv = args->endp; 290 291 /* 292 * extract environment strings 293 */ 294 if (envv) { 295 p32 = envv; 296 for (;;) { 297 error = copyin(p32++, &arg, sizeof(arg)); 298 if (error) 299 goto err_exit; 300 if (arg == 0) 301 break; 302 envp = PTRIN(arg); 303 error = copyinstr(envp, args->endp, args->stringspace, 304 &length); 305 if (error) { 306 if (error == ENAMETOOLONG) 307 error = E2BIG; 308 goto err_exit; 309 } 310 args->stringspace -= length; 311 args->endp += length; 312 args->envc++; 313 } 314 } 315 316 return (0); 317 318err_exit: 319 kmem_free_wakeup(exec_map, (vm_offset_t)args->buf, 320 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 321 args->buf = NULL; 322 return (error); 323} 324 325int 326freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) 327{ 328 struct image_args eargs; 329 int error; 330 331 error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE, 332 uap->argv, uap->envv); 333 if (error == 0) 334 error = kern_execve(td, &eargs, NULL); 335 return (error); 336} 337 338#ifdef __ia64__ 339static int 340freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 341 int prot, int fd, off_t pos) 342{ 343 vm_map_t map; 344 vm_map_entry_t entry; 345 int rv; 346 347 map = &td->td_proc->p_vmspace->vm_map; 348 if (fd != -1) 349 prot |= VM_PROT_WRITE; 350 351 if (vm_map_lookup_entry(map, start, &entry)) { 352 if ((entry->protection & prot) != prot) { 353 rv = vm_map_protect(map, 354 trunc_page(start), 355 round_page(end), 356 entry->protection | prot, 357 FALSE); 358 if (rv != KERN_SUCCESS) 359 return (EINVAL); 360 } 361 } else { 362 vm_offset_t addr = trunc_page(start); 363 rv = vm_map_find(map, 0, 0, 364 &addr, PAGE_SIZE, FALSE, prot, 365 VM_PROT_ALL, 0); 366 if (rv != KERN_SUCCESS) 367 return (EINVAL); 368 } 369 370 if (fd != -1) { 371 struct pread_args r; 372 r.fd = fd; 373 r.buf = (void *) start; 374 r.nbyte = end - start; 375 r.offset = pos; 376 return (pread(td, &r)); 377 } else { 378 while (start < end) { 379 subyte((void *) start, 0); 380 start++; 381 } 382 return (0); 383 } 384} 385#endif 386 387int 388freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 389{ 390 struct mmap_args ap; 391 vm_offset_t addr = (vm_offset_t) uap->addr; 392 vm_size_t len = uap->len; 393 int prot = uap->prot; 394 int flags = uap->flags; 395 int fd = uap->fd; 396 off_t pos = (uap->poslo 397 | ((off_t)uap->poshi << 32)); 398#ifdef __ia64__ 399 vm_size_t pageoff; 400 int error; 401 402 /* 403 * Attempt to handle page size hassles. 404 */ 405 pageoff = (pos & PAGE_MASK); 406 if (flags & MAP_FIXED) { 407 vm_offset_t start, end; 408 start = addr; 409 end = addr + len; 410 411 mtx_lock(&Giant); 412 if (start != trunc_page(start)) { 413 error = freebsd32_mmap_partial(td, start, 414 round_page(start), prot, 415 fd, pos); 416 if (fd != -1) 417 pos += round_page(start) - start; 418 start = round_page(start); 419 } 420 if (end != round_page(end)) { 421 vm_offset_t t = trunc_page(end); 422 error = freebsd32_mmap_partial(td, t, end, 423 prot, fd, 424 pos + t - start); 425 end = trunc_page(end); 426 } 427 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 428 /* 429 * We can't map this region at all. The specified 430 * address doesn't have the same alignment as the file 431 * position. Fake the mapping by simply reading the 432 * entire region into memory. First we need to make 433 * sure the region exists. 434 */ 435 vm_map_t map; 436 struct pread_args r; 437 int rv; 438 439 prot |= VM_PROT_WRITE; 440 map = &td->td_proc->p_vmspace->vm_map; 441 rv = vm_map_remove(map, start, end); 442 if (rv != KERN_SUCCESS) { 443 mtx_unlock(&Giant); 444 return (EINVAL); 445 } 446 rv = vm_map_find(map, 0, 0, 447 &start, end - start, FALSE, 448 prot, VM_PROT_ALL, 0); 449 mtx_unlock(&Giant); 450 if (rv != KERN_SUCCESS) 451 return (EINVAL); 452 r.fd = fd; 453 r.buf = (void *) start; 454 r.nbyte = end - start; 455 r.offset = pos; 456 error = pread(td, &r); 457 if (error) 458 return (error); 459 460 td->td_retval[0] = addr; 461 return (0); 462 } 463 mtx_unlock(&Giant); 464 if (end == start) { 465 /* 466 * After dealing with the ragged ends, there 467 * might be none left. 468 */ 469 td->td_retval[0] = addr; 470 return (0); 471 } 472 addr = start; 473 len = end - start; 474 } 475#endif 476 477 ap.addr = (void *) addr; 478 ap.len = len; 479 ap.prot = prot; 480 ap.flags = flags; 481 ap.fd = fd; 482 ap.pos = pos; 483 484 return (mmap(td, &ap)); 485} 486 487struct itimerval32 { 488 struct timeval32 it_interval; 489 struct timeval32 it_value; 490}; 491 492CTASSERT(sizeof(struct itimerval32) == 16); 493 494int 495freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 496{ 497 struct itimerval itv, oitv, *itvp; 498 struct itimerval32 i32; 499 int error; 500 501 if (uap->itv != NULL) { 502 error = copyin(uap->itv, &i32, sizeof(i32)); 503 if (error) 504 return (error); 505 TV_CP(i32, itv, it_interval); 506 TV_CP(i32, itv, it_value); 507 itvp = &itv; 508 } else 509 itvp = NULL; 510 error = kern_setitimer(td, uap->which, itvp, &oitv); 511 if (error || uap->oitv == NULL) 512 return (error); 513 TV_CP(oitv, i32, it_interval); 514 TV_CP(oitv, i32, it_value); 515 return (copyout(&i32, uap->oitv, sizeof(i32))); 516} 517 518int 519freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap) 520{ 521 struct itimerval itv; 522 struct itimerval32 i32; 523 int error; 524 525 error = kern_getitimer(td, uap->which, &itv); 526 if (error || uap->itv == NULL) 527 return (error); 528 TV_CP(itv, i32, it_interval); 529 TV_CP(itv, i32, it_value); 530 return (copyout(&i32, uap->itv, sizeof(i32))); 531} 532 533int 534freebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 535{ 536 struct timeval32 tv32; 537 struct timeval tv, *tvp; 538 int error; 539 540 if (uap->tv != NULL) { 541 error = copyin(uap->tv, &tv32, sizeof(tv32)); 542 if (error) 543 return (error); 544 CP(tv32, tv, tv_sec); 545 CP(tv32, tv, tv_usec); 546 tvp = &tv; 547 } else 548 tvp = NULL; 549 /* 550 * XXX big-endian needs to convert the fd_sets too. 551 * XXX Do pointers need PTRIN()? 552 */ 553 return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp)); 554} 555 556struct kevent32 { 557 u_int32_t ident; /* identifier for this event */ 558 short filter; /* filter for event */ 559 u_short flags; 560 u_int fflags; 561 int32_t data; 562 u_int32_t udata; /* opaque user data identifier */ 563}; 564 565CTASSERT(sizeof(struct kevent32) == 20); 566static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count); 567static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count); 568 569/* 570 * Copy 'count' items into the destination list pointed to by uap->eventlist. 571 */ 572static int 573freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count) 574{ 575 struct freebsd32_kevent_args *uap; 576 struct kevent32 ks32[KQ_NEVENTS]; 577 int i, error = 0; 578 579 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 580 uap = (struct freebsd32_kevent_args *)arg; 581 582 for (i = 0; i < count; i++) { 583 CP(kevp[i], ks32[i], ident); 584 CP(kevp[i], ks32[i], filter); 585 CP(kevp[i], ks32[i], flags); 586 CP(kevp[i], ks32[i], fflags); 587 CP(kevp[i], ks32[i], data); 588 PTROUT_CP(kevp[i], ks32[i], udata); 589 } 590 error = copyout(ks32, uap->eventlist, count * sizeof *ks32); 591 if (error == 0) 592 uap->eventlist += count; 593 return (error); 594} 595 596/* 597 * Copy 'count' items from the list pointed to by uap->changelist. 598 */ 599static int 600freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count) 601{ 602 struct freebsd32_kevent_args *uap; 603 struct kevent32 ks32[KQ_NEVENTS]; 604 int i, error = 0; 605 606 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 607 uap = (struct freebsd32_kevent_args *)arg; 608 609 error = copyin(uap->changelist, ks32, count * sizeof *ks32); 610 if (error) 611 goto done; 612 uap->changelist += count; 613 614 for (i = 0; i < count; i++) { 615 CP(ks32[i], kevp[i], ident); 616 CP(ks32[i], kevp[i], filter); 617 CP(ks32[i], kevp[i], flags); 618 CP(ks32[i], kevp[i], fflags); 619 CP(ks32[i], kevp[i], data); 620 PTRIN_CP(ks32[i], kevp[i], udata); 621 } 622done: 623 return (error); 624} 625 626int 627freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 628{ 629 struct timespec32 ts32; 630 struct timespec ts, *tsp; 631 struct kevent_copyops k_ops = { uap, 632 freebsd32_kevent_copyout, 633 freebsd32_kevent_copyin}; 634 int error; 635 636 637 if (uap->timeout) { 638 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 639 if (error) 640 return (error); 641 CP(ts32, ts, tv_sec); 642 CP(ts32, ts, tv_nsec); 643 tsp = &ts; 644 } else 645 tsp = NULL; 646 error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents, 647 &k_ops, tsp); 648 return (error); 649} 650 651int 652freebsd32_gettimeofday(struct thread *td, 653 struct freebsd32_gettimeofday_args *uap) 654{ 655 struct timeval atv; 656 struct timeval32 atv32; 657 struct timezone rtz; 658 int error = 0; 659 660 if (uap->tp) { 661 microtime(&atv); 662 CP(atv, atv32, tv_sec); 663 CP(atv, atv32, tv_usec); 664 error = copyout(&atv32, uap->tp, sizeof (atv32)); 665 } 666 if (error == 0 && uap->tzp != NULL) { 667 rtz.tz_minuteswest = tz_minuteswest; 668 rtz.tz_dsttime = tz_dsttime; 669 error = copyout(&rtz, uap->tzp, sizeof (rtz)); 670 } 671 return (error); 672} 673 674int 675freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 676{ 677 struct rusage32 s32; 678 struct rusage s; 679 int error; 680 681 error = kern_getrusage(td, uap->who, &s); 682 if (error) 683 return (error); 684 if (uap->rusage != NULL) { 685 TV_CP(s, s32, ru_utime); 686 TV_CP(s, s32, ru_stime); 687 CP(s, s32, ru_maxrss); 688 CP(s, s32, ru_ixrss); 689 CP(s, s32, ru_idrss); 690 CP(s, s32, ru_isrss); 691 CP(s, s32, ru_minflt); 692 CP(s, s32, ru_majflt); 693 CP(s, s32, ru_nswap); 694 CP(s, s32, ru_inblock); 695 CP(s, s32, ru_oublock); 696 CP(s, s32, ru_msgsnd); 697 CP(s, s32, ru_msgrcv); 698 CP(s, s32, ru_nsignals); 699 CP(s, s32, ru_nvcsw); 700 CP(s, s32, ru_nivcsw); 701 error = copyout(&s32, uap->rusage, sizeof(s32)); 702 } 703 return (error); 704} 705 706struct iovec32 { 707 u_int32_t iov_base; 708 int iov_len; 709}; 710 711CTASSERT(sizeof(struct iovec32) == 8); 712 713static int 714freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) 715{ 716 struct iovec32 iov32; 717 struct iovec *iov; 718 struct uio *uio; 719 u_int iovlen; 720 int error, i; 721 722 *uiop = NULL; 723 if (iovcnt > UIO_MAXIOV) 724 return (EINVAL); 725 iovlen = iovcnt * sizeof(struct iovec); 726 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 727 iov = (struct iovec *)(uio + 1); 728 for (i = 0; i < iovcnt; i++) { 729 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); 730 if (error) { 731 free(uio, M_IOV); 732 return (error); 733 } 734 iov[i].iov_base = PTRIN(iov32.iov_base); 735 iov[i].iov_len = iov32.iov_len; 736 } 737 uio->uio_iov = iov; 738 uio->uio_iovcnt = iovcnt; 739 uio->uio_segflg = UIO_USERSPACE; 740 uio->uio_offset = -1; 741 uio->uio_resid = 0; 742 for (i = 0; i < iovcnt; i++) { 743 if (iov->iov_len > INT_MAX - uio->uio_resid) { 744 free(uio, M_IOV); 745 return (EINVAL); 746 } 747 uio->uio_resid += iov->iov_len; 748 iov++; 749 } 750 *uiop = uio; 751 return (0); 752} 753 754int 755freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 756{ 757 struct uio *auio; 758 int error; 759 760 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 761 if (error) 762 return (error); 763 error = kern_readv(td, uap->fd, auio); 764 free(auio, M_IOV); 765 return (error); 766} 767 768int 769freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 770{ 771 struct uio *auio; 772 int error; 773 774 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 775 if (error) 776 return (error); 777 error = kern_writev(td, uap->fd, auio); 778 free(auio, M_IOV); 779 return (error); 780} 781 782int 783freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap) 784{ 785 struct uio *auio; 786 int error; 787 788 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 789 if (error) 790 return (error); 791 error = kern_preadv(td, uap->fd, auio, uap->offset); 792 free(auio, M_IOV); 793 return (error); 794} 795 796int 797freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap) 798{ 799 struct uio *auio; 800 int error; 801 802 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 803 if (error) 804 return (error); 805 error = kern_pwritev(td, uap->fd, auio, uap->offset); 806 free(auio, M_IOV); 807 return (error); 808} 809 810static int 811freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp, 812 int error) 813{ 814 struct iovec32 iov32; 815 struct iovec *iov; 816 u_int iovlen; 817 int i; 818 819 *iovp = NULL; 820 if (iovcnt > UIO_MAXIOV) 821 return (error); 822 iovlen = iovcnt * sizeof(struct iovec); 823 iov = malloc(iovlen, M_IOV, M_WAITOK); 824 for (i = 0; i < iovcnt; i++) { 825 error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32)); 826 if (error) { 827 free(iov, M_IOV); 828 return (error); 829 } 830 iov[i].iov_base = PTRIN(iov32.iov_base); 831 iov[i].iov_len = iov32.iov_len; 832 } 833 *iovp = iov; 834 return (0); 835} 836 837struct msghdr32 { 838 u_int32_t msg_name; 839 socklen_t msg_namelen; 840 u_int32_t msg_iov; 841 int msg_iovlen; 842 u_int32_t msg_control; 843 socklen_t msg_controllen; 844 int msg_flags; 845}; 846CTASSERT(sizeof(struct msghdr32) == 28); 847 848static int 849freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg) 850{ 851 struct msghdr32 m32; 852 int error; 853 854 error = copyin(msg32, &m32, sizeof(m32)); 855 if (error) 856 return (error); 857 msg->msg_name = PTRIN(m32.msg_name); 858 msg->msg_namelen = m32.msg_namelen; 859 msg->msg_iov = PTRIN(m32.msg_iov); 860 msg->msg_iovlen = m32.msg_iovlen; 861 msg->msg_control = PTRIN(m32.msg_control); 862 msg->msg_controllen = m32.msg_controllen; 863 msg->msg_flags = m32.msg_flags; 864 return (0); 865} 866 867static int 868freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32) 869{ 870 struct msghdr32 m32; 871 int error; 872 873 m32.msg_name = PTROUT(msg->msg_name); 874 m32.msg_namelen = msg->msg_namelen; 875 m32.msg_iov = PTROUT(msg->msg_iov); 876 m32.msg_iovlen = msg->msg_iovlen; 877 m32.msg_control = PTROUT(msg->msg_control); 878 m32.msg_controllen = msg->msg_controllen; 879 m32.msg_flags = msg->msg_flags; 880 error = copyout(&m32, msg32, sizeof(m32)); 881 return (error); 882} 883 884#define FREEBSD32_ALIGNBYTES (sizeof(int) - 1) 885#define FREEBSD32_ALIGN(p) \ 886 (((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES) 887#define FREEBSD32_CMSG_SPACE(l) \ 888 (FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l)) 889 890#define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \ 891 FREEBSD32_ALIGN(sizeof(struct cmsghdr))) 892static int 893freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control) 894{ 895 struct cmsghdr *cm; 896 void *data; 897 socklen_t clen, datalen; 898 int error; 899 caddr_t ctlbuf; 900 int len, maxlen, copylen; 901 struct mbuf *m; 902 error = 0; 903 904 len = msg->msg_controllen; 905 maxlen = msg->msg_controllen; 906 msg->msg_controllen = 0; 907 908 m = control; 909 ctlbuf = msg->msg_control; 910 911 while (m && len > 0) { 912 cm = mtod(m, struct cmsghdr *); 913 clen = m->m_len; 914 915 while (cm != NULL) { 916 917 if (sizeof(struct cmsghdr) > clen || 918 cm->cmsg_len > clen) { 919 error = EINVAL; 920 break; 921 } 922 923 data = CMSG_DATA(cm); 924 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 925 926 /* Adjust message length */ 927 cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + 928 datalen; 929 930 931 /* Copy cmsghdr */ 932 copylen = sizeof(struct cmsghdr); 933 if (len < copylen) { 934 msg->msg_flags |= MSG_CTRUNC; 935 copylen = len; 936 } 937 938 error = copyout(cm,ctlbuf,copylen); 939 if (error) 940 goto exit; 941 942 ctlbuf += FREEBSD32_ALIGN(copylen); 943 len -= FREEBSD32_ALIGN(copylen); 944 945 if (len <= 0) 946 break; 947 948 /* Copy data */ 949 copylen = datalen; 950 if (len < copylen) { 951 msg->msg_flags |= MSG_CTRUNC; 952 copylen = len; 953 } 954 955 error = copyout(data,ctlbuf,copylen); 956 if (error) 957 goto exit; 958 959 ctlbuf += FREEBSD32_ALIGN(copylen); 960 len -= FREEBSD32_ALIGN(copylen); 961 962 if (CMSG_SPACE(datalen) < clen) { 963 clen -= CMSG_SPACE(datalen); 964 cm = (struct cmsghdr *) 965 ((caddr_t)cm + CMSG_SPACE(datalen)); 966 } else { 967 clen = 0; 968 cm = NULL; 969 } 970 } 971 m = m->m_next; 972 } 973 974 msg->msg_controllen = (len <= 0) ? maxlen : ctlbuf - (caddr_t)msg->msg_control; 975 976exit: 977 return (error); 978 979} 980 981int 982freebsd32_recvmsg(td, uap) 983 struct thread *td; 984 struct freebsd32_recvmsg_args /* { 985 int s; 986 struct msghdr32 *msg; 987 int flags; 988 } */ *uap; 989{ 990 struct msghdr msg; 991 struct msghdr32 m32; 992 struct iovec *uiov, *iov; 993 struct mbuf *control = NULL; 994 struct mbuf **controlp; 995 996 int error; 997 error = copyin(uap->msg, &m32, sizeof(m32)); 998 if (error) 999 return (error); 1000 error = freebsd32_copyinmsghdr(uap->msg, &msg); 1001 if (error) 1002 return (error); 1003 error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, 1004 m32.msg_iovlen, &iov, EMSGSIZE); 1005 if (error) 1006 return (error); 1007 msg.msg_flags = uap->flags; 1008 uiov = msg.msg_iov; 1009 msg.msg_iov = iov; 1010 1011 controlp = (msg.msg_control != NULL) ? &control : NULL; 1012 error = kern_recvit(td, uap->s, &msg, NULL, UIO_USERSPACE, controlp); 1013 if (error == 0) { 1014 msg.msg_iov = uiov; 1015 1016 if (control != NULL) 1017 error = freebsd32_copy_msg_out(&msg, control); 1018 1019 if (error == 0) 1020 error = freebsd32_copyoutmsghdr(&msg, uap->msg); 1021 } 1022 free(iov, M_IOV); 1023 1024 if (control != NULL) 1025 m_freem(control); 1026 1027 return (error); 1028} 1029 1030 1031static int 1032freebsd32_convert_msg_in(struct mbuf **controlp) 1033{ 1034 struct mbuf *control = *controlp; 1035 struct cmsghdr *cm = mtod(control, struct cmsghdr *); 1036 void *data; 1037 socklen_t clen = control->m_len, datalen; 1038 int error; 1039 1040 error = 0; 1041 *controlp = NULL; 1042 1043 while (cm != NULL) { 1044 if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) { 1045 error = EINVAL; 1046 break; 1047 } 1048 1049 data = FREEBSD32_CMSG_DATA(cm); 1050 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 1051 1052 *controlp = sbcreatecontrol(data, datalen, cm->cmsg_type, 1053 cm->cmsg_level); 1054 controlp = &(*controlp)->m_next; 1055 1056 if (FREEBSD32_CMSG_SPACE(datalen) < clen) { 1057 clen -= FREEBSD32_CMSG_SPACE(datalen); 1058 cm = (struct cmsghdr *) 1059 ((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen)); 1060 } else { 1061 clen = 0; 1062 cm = NULL; 1063 } 1064 } 1065 1066 m_freem(control); 1067 return (error); 1068} 1069 1070 1071int 1072freebsd32_sendmsg(struct thread *td, 1073 struct freebsd32_sendmsg_args *uap) 1074{ 1075 struct msghdr msg; 1076 struct msghdr32 m32; 1077 struct iovec *iov; 1078 struct mbuf *control = NULL; 1079 struct sockaddr *to = NULL; 1080 int error; 1081 1082 error = copyin(uap->msg, &m32, sizeof(m32)); 1083 if (error) 1084 return (error); 1085 error = freebsd32_copyinmsghdr(uap->msg, &msg); 1086 if (error) 1087 return (error); 1088 error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, 1089 m32.msg_iovlen, &iov, EMSGSIZE); 1090 if (error) 1091 return (error); 1092 msg.msg_iov = iov; 1093 if (msg.msg_name != NULL) { 1094 error = getsockaddr(&to, msg.msg_name, msg.msg_namelen); 1095 if (error) { 1096 to = NULL; 1097 goto out; 1098 } 1099 msg.msg_name = to; 1100 } 1101 1102 if (msg.msg_control) { 1103 if (msg.msg_controllen < sizeof(struct cmsghdr)) { 1104 error = EINVAL; 1105 goto out; 1106 } 1107 1108 error = sockargs(&control, msg.msg_control, 1109 msg.msg_controllen, MT_CONTROL); 1110 if (error) 1111 goto out; 1112 1113 error = freebsd32_convert_msg_in(&control); 1114 if (error) 1115 goto out; 1116 } 1117 1118 error = kern_sendit(td, uap->s, &msg, uap->flags, control, 1119 UIO_USERSPACE); 1120 1121out: 1122 free(iov, M_IOV); 1123 if (to) 1124 free(to, M_SONAME); 1125 return (error); 1126} 1127 1128int 1129freebsd32_recvfrom(struct thread *td, 1130 struct freebsd32_recvfrom_args *uap) 1131{ 1132 struct msghdr msg; 1133 struct iovec aiov; 1134 int error; 1135 1136 if (uap->fromlenaddr) { 1137 error = copyin((void *)(uintptr_t)uap->fromlenaddr, 1138 &msg.msg_namelen, sizeof(msg.msg_namelen)); 1139 if (error) 1140 return (error); 1141 } else { 1142 msg.msg_namelen = 0; 1143 } 1144 1145 msg.msg_name = (void *)(uintptr_t)uap->from; 1146 msg.msg_iov = &aiov; 1147 msg.msg_iovlen = 1; 1148 aiov.iov_base = (void *)(uintptr_t)uap->buf; 1149 aiov.iov_len = uap->len; 1150 msg.msg_control = 0; 1151 msg.msg_flags = uap->flags; 1152 error = kern_recvit(td, uap->s, &msg, 1153 (void *)(uintptr_t)uap->fromlenaddr, UIO_USERSPACE, NULL); 1154 return (error); 1155} 1156 1157int 1158freebsd32_settimeofday(struct thread *td, 1159 struct freebsd32_settimeofday_args *uap) 1160{ 1161 struct timeval32 tv32; 1162 struct timeval tv, *tvp; 1163 struct timezone tz, *tzp; 1164 int error; 1165 1166 if (uap->tv) { 1167 error = copyin(uap->tv, &tv32, sizeof(tv32)); 1168 if (error) 1169 return (error); 1170 CP(tv32, tv, tv_sec); 1171 CP(tv32, tv, tv_usec); 1172 tvp = &tv; 1173 } else 1174 tvp = NULL; 1175 if (uap->tzp) { 1176 error = copyin(uap->tzp, &tz, sizeof(tz)); 1177 if (error) 1178 return (error); 1179 tzp = &tz; 1180 } else 1181 tzp = NULL; 1182 return (kern_settimeofday(td, tvp, tzp)); 1183} 1184 1185int 1186freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 1187{ 1188 struct timeval32 s32[2]; 1189 struct timeval s[2], *sp; 1190 int error; 1191 1192 if (uap->tptr != NULL) { 1193 error = copyin(uap->tptr, s32, sizeof(s32)); 1194 if (error) 1195 return (error); 1196 CP(s32[0], s[0], tv_sec); 1197 CP(s32[0], s[0], tv_usec); 1198 CP(s32[1], s[1], tv_sec); 1199 CP(s32[1], s[1], tv_usec); 1200 sp = s; 1201 } else 1202 sp = NULL; 1203 return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 1204} 1205 1206int 1207freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap) 1208{ 1209 struct timeval32 s32[2]; 1210 struct timeval s[2], *sp; 1211 int error; 1212 1213 if (uap->tptr != NULL) { 1214 error = copyin(uap->tptr, s32, sizeof(s32)); 1215 if (error) 1216 return (error); 1217 CP(s32[0], s[0], tv_sec); 1218 CP(s32[0], s[0], tv_usec); 1219 CP(s32[1], s[1], tv_sec); 1220 CP(s32[1], s[1], tv_usec); 1221 sp = s; 1222 } else 1223 sp = NULL; 1224 return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 1225} 1226 1227int 1228freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap) 1229{ 1230 struct timeval32 s32[2]; 1231 struct timeval s[2], *sp; 1232 int error; 1233 1234 if (uap->tptr != NULL) { 1235 error = copyin(uap->tptr, s32, sizeof(s32)); 1236 if (error) 1237 return (error); 1238 CP(s32[0], s[0], tv_sec); 1239 CP(s32[0], s[0], tv_usec); 1240 CP(s32[1], s[1], tv_sec); 1241 CP(s32[1], s[1], tv_usec); 1242 sp = s; 1243 } else 1244 sp = NULL; 1245 return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE)); 1246} 1247 1248 1249int 1250freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 1251{ 1252 struct timeval32 tv32; 1253 struct timeval delta, olddelta, *deltap; 1254 int error; 1255 1256 if (uap->delta) { 1257 error = copyin(uap->delta, &tv32, sizeof(tv32)); 1258 if (error) 1259 return (error); 1260 CP(tv32, delta, tv_sec); 1261 CP(tv32, delta, tv_usec); 1262 deltap = δ 1263 } else 1264 deltap = NULL; 1265 error = kern_adjtime(td, deltap, &olddelta); 1266 if (uap->olddelta && error == 0) { 1267 CP(olddelta, tv32, tv_sec); 1268 CP(olddelta, tv32, tv_usec); 1269 error = copyout(&tv32, uap->olddelta, sizeof(tv32)); 1270 } 1271 return (error); 1272} 1273 1274#ifdef COMPAT_FREEBSD4 1275int 1276freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap) 1277{ 1278 struct statfs32 s32; 1279 struct statfs s; 1280 int error; 1281 1282 error = kern_statfs(td, uap->path, UIO_USERSPACE, &s); 1283 if (error) 1284 return (error); 1285 copy_statfs(&s, &s32); 1286 return (copyout(&s32, uap->buf, sizeof(s32))); 1287} 1288#endif 1289 1290#ifdef COMPAT_FREEBSD4 1291int 1292freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap) 1293{ 1294 struct statfs32 s32; 1295 struct statfs s; 1296 int error; 1297 1298 error = kern_fstatfs(td, uap->fd, &s); 1299 if (error) 1300 return (error); 1301 copy_statfs(&s, &s32); 1302 return (copyout(&s32, uap->buf, sizeof(s32))); 1303} 1304#endif 1305 1306#ifdef COMPAT_FREEBSD4 1307int 1308freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap) 1309{ 1310 struct statfs32 s32; 1311 struct statfs s; 1312 fhandle_t fh; 1313 int error; 1314 1315 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 1316 return (error); 1317 error = kern_fhstatfs(td, fh, &s); 1318 if (error) 1319 return (error); 1320 copy_statfs(&s, &s32); 1321 return (copyout(&s32, uap->buf, sizeof(s32))); 1322} 1323#endif 1324 1325int 1326freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 1327{ 1328 /* 1329 * Vector through to semsys if it is loaded. 1330 */ 1331 return sysent[SYS_semsys].sy_call(td, uap); 1332} 1333 1334int 1335freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 1336{ 1337 /* 1338 * Vector through to msgsys if it is loaded. 1339 */ 1340 return sysent[SYS_msgsys].sy_call(td, uap); 1341} 1342 1343int 1344freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 1345{ 1346 1347 switch (uap->which) { 1348 case 0: { /* shmat */ 1349 struct shmat_args ap; 1350 1351 ap.shmid = uap->a2; 1352 ap.shmaddr = PTRIN(uap->a3); 1353 ap.shmflg = uap->a4; 1354 return (sysent[SYS_shmat].sy_call(td, &ap)); 1355 } 1356 case 2: { /* shmdt */ 1357 struct shmdt_args ap; 1358 1359 ap.shmaddr = PTRIN(uap->a2); 1360 return (sysent[SYS_shmdt].sy_call(td, &ap)); 1361 } 1362 case 3: { /* shmget */ 1363 struct shmget_args ap; 1364 1365 ap.key = uap->a2; 1366 ap.size = uap->a3; 1367 ap.shmflg = uap->a4; 1368 return (sysent[SYS_shmget].sy_call(td, &ap)); 1369 } 1370 case 4: { /* shmctl */ 1371 struct freebsd32_shmctl_args ap; 1372 1373 ap.shmid = uap->a2; 1374 ap.cmd = uap->a3; 1375 ap.buf = PTRIN(uap->a4); 1376 return (freebsd32_shmctl(td, &ap)); 1377 } 1378 case 1: /* oshmctl */ 1379 default: 1380 return (EINVAL); 1381 } 1382} 1383 1384struct ipc_perm32 { 1385 uint16_t cuid; 1386 uint16_t cgid; 1387 uint16_t uid; 1388 uint16_t gid; 1389 uint16_t mode; 1390 uint16_t seq; 1391 uint32_t key; 1392}; 1393struct shmid_ds32 { 1394 struct ipc_perm32 shm_perm; 1395 int32_t shm_segsz; 1396 int32_t shm_lpid; 1397 int32_t shm_cpid; 1398 int16_t shm_nattch; 1399 int32_t shm_atime; 1400 int32_t shm_dtime; 1401 int32_t shm_ctime; 1402 uint32_t shm_internal; 1403}; 1404struct shm_info32 { 1405 int32_t used_ids; 1406 uint32_t shm_tot; 1407 uint32_t shm_rss; 1408 uint32_t shm_swp; 1409 uint32_t swap_attempts; 1410 uint32_t swap_successes; 1411}; 1412struct shminfo32 { 1413 uint32_t shmmax; 1414 uint32_t shmmin; 1415 uint32_t shmmni; 1416 uint32_t shmseg; 1417 uint32_t shmall; 1418}; 1419 1420int 1421freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap) 1422{ 1423 int error = 0; 1424 union { 1425 struct shmid_ds shmid_ds; 1426 struct shm_info shm_info; 1427 struct shminfo shminfo; 1428 } u; 1429 union { 1430 struct shmid_ds32 shmid_ds32; 1431 struct shm_info32 shm_info32; 1432 struct shminfo32 shminfo32; 1433 } u32; 1434 size_t sz; 1435 1436 if (uap->cmd == IPC_SET) { 1437 if ((error = copyin(uap->buf, &u32.shmid_ds32, 1438 sizeof(u32.shmid_ds32)))) 1439 goto done; 1440 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cuid); 1441 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cgid); 1442 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.uid); 1443 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.gid); 1444 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.mode); 1445 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.seq); 1446 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.key); 1447 CP(u32.shmid_ds32, u.shmid_ds, shm_segsz); 1448 CP(u32.shmid_ds32, u.shmid_ds, shm_lpid); 1449 CP(u32.shmid_ds32, u.shmid_ds, shm_cpid); 1450 CP(u32.shmid_ds32, u.shmid_ds, shm_nattch); 1451 CP(u32.shmid_ds32, u.shmid_ds, shm_atime); 1452 CP(u32.shmid_ds32, u.shmid_ds, shm_dtime); 1453 CP(u32.shmid_ds32, u.shmid_ds, shm_ctime); 1454 PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal); 1455 } 1456 1457 error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz); 1458 if (error) 1459 goto done; 1460 1461 /* Cases in which we need to copyout */ 1462 switch (uap->cmd) { 1463 case IPC_INFO: 1464 CP(u.shminfo, u32.shminfo32, shmmax); 1465 CP(u.shminfo, u32.shminfo32, shmmin); 1466 CP(u.shminfo, u32.shminfo32, shmmni); 1467 CP(u.shminfo, u32.shminfo32, shmseg); 1468 CP(u.shminfo, u32.shminfo32, shmall); 1469 error = copyout(&u32.shminfo32, uap->buf, 1470 sizeof(u32.shminfo32)); 1471 break; 1472 case SHM_INFO: 1473 CP(u.shm_info, u32.shm_info32, used_ids); 1474 CP(u.shm_info, u32.shm_info32, shm_rss); 1475 CP(u.shm_info, u32.shm_info32, shm_tot); 1476 CP(u.shm_info, u32.shm_info32, shm_swp); 1477 CP(u.shm_info, u32.shm_info32, swap_attempts); 1478 CP(u.shm_info, u32.shm_info32, swap_successes); 1479 error = copyout(&u32.shm_info32, uap->buf, 1480 sizeof(u32.shm_info32)); 1481 break; 1482 case SHM_STAT: 1483 case IPC_STAT: 1484 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cuid); 1485 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cgid); 1486 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.uid); 1487 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.gid); 1488 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.mode); 1489 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.seq); 1490 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.key); 1491 CP(u.shmid_ds, u32.shmid_ds32, shm_segsz); 1492 CP(u.shmid_ds, u32.shmid_ds32, shm_lpid); 1493 CP(u.shmid_ds, u32.shmid_ds32, shm_cpid); 1494 CP(u.shmid_ds, u32.shmid_ds32, shm_nattch); 1495 CP(u.shmid_ds, u32.shmid_ds32, shm_atime); 1496 CP(u.shmid_ds, u32.shmid_ds32, shm_dtime); 1497 CP(u.shmid_ds, u32.shmid_ds32, shm_ctime); 1498 PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal); 1499 error = copyout(&u32.shmid_ds32, uap->buf, 1500 sizeof(u32.shmid_ds32)); 1501 break; 1502 } 1503 1504done: 1505 if (error) { 1506 /* Invalidate the return value */ 1507 td->td_retval[0] = -1; 1508 } 1509 return (error); 1510} 1511 1512int 1513freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 1514{ 1515 struct pread_args ap; 1516 1517 ap.fd = uap->fd; 1518 ap.buf = uap->buf; 1519 ap.nbyte = uap->nbyte; 1520 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1521 return (pread(td, &ap)); 1522} 1523 1524int 1525freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 1526{ 1527 struct pwrite_args ap; 1528 1529 ap.fd = uap->fd; 1530 ap.buf = uap->buf; 1531 ap.nbyte = uap->nbyte; 1532 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1533 return (pwrite(td, &ap)); 1534} 1535 1536int 1537freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 1538{ 1539 int error; 1540 struct lseek_args ap; 1541 off_t pos; 1542 1543 ap.fd = uap->fd; 1544 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1545 ap.whence = uap->whence; 1546 error = lseek(td, &ap); 1547 /* Expand the quad return into two parts for eax and edx */ 1548 pos = *(off_t *)(td->td_retval); 1549 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1550 td->td_retval[1] = pos >> 32; /* %edx */ 1551 return error; 1552} 1553 1554int 1555freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 1556{ 1557 struct truncate_args ap; 1558 1559 ap.path = uap->path; 1560 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1561 return (truncate(td, &ap)); 1562} 1563 1564int 1565freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 1566{ 1567 struct ftruncate_args ap; 1568 1569 ap.fd = uap->fd; 1570 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1571 return (ftruncate(td, &ap)); 1572} 1573 1574struct sf_hdtr32 { 1575 uint32_t headers; 1576 int hdr_cnt; 1577 uint32_t trailers; 1578 int trl_cnt; 1579}; 1580 1581static int 1582freebsd32_do_sendfile(struct thread *td, 1583 struct freebsd32_sendfile_args *uap, int compat) 1584{ 1585 struct sendfile_args ap; 1586 struct sf_hdtr32 hdtr32; 1587 struct sf_hdtr hdtr; 1588 struct uio *hdr_uio, *trl_uio; 1589 struct iovec32 *iov32; 1590 int error; 1591 1592 hdr_uio = trl_uio = NULL; 1593 1594 ap.fd = uap->fd; 1595 ap.s = uap->s; 1596 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1597 ap.nbytes = uap->nbytes; 1598 ap.hdtr = (struct sf_hdtr *)uap->hdtr; /* XXX not used */ 1599 ap.sbytes = uap->sbytes; 1600 ap.flags = uap->flags; 1601 1602 if (uap->hdtr != NULL) { 1603 error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32)); 1604 if (error) 1605 goto out; 1606 PTRIN_CP(hdtr32, hdtr, headers); 1607 CP(hdtr32, hdtr, hdr_cnt); 1608 PTRIN_CP(hdtr32, hdtr, trailers); 1609 CP(hdtr32, hdtr, trl_cnt); 1610 1611 if (hdtr.headers != NULL) { 1612 iov32 = (struct iovec32 *)(uintptr_t)hdtr32.headers; 1613 error = freebsd32_copyinuio(iov32, 1614 hdtr32.hdr_cnt, &hdr_uio); 1615 if (error) 1616 goto out; 1617 } 1618 if (hdtr.trailers != NULL) { 1619 iov32 = (struct iovec32 *)(uintptr_t)hdtr32.trailers; 1620 error = freebsd32_copyinuio(iov32, 1621 hdtr32.trl_cnt, &trl_uio); 1622 if (error) 1623 goto out; 1624 } 1625 } 1626 1627 error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat); 1628out: 1629 if (hdr_uio) 1630 free(hdr_uio, M_IOV); 1631 if (trl_uio) 1632 free(trl_uio, M_IOV); 1633 return (error); 1634} 1635 1636#ifdef COMPAT_FREEBSD4 1637int 1638freebsd4_freebsd32_sendfile(struct thread *td, 1639 struct freebsd4_freebsd32_sendfile_args *uap) 1640{ 1641 return (freebsd32_do_sendfile(td, 1642 (struct freebsd32_sendfile_args *)uap, 1)); 1643} 1644#endif 1645 1646int 1647freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 1648{ 1649 1650 return (freebsd32_do_sendfile(td, uap, 0)); 1651} 1652 1653struct stat32 { 1654 dev_t st_dev; 1655 ino_t st_ino; 1656 mode_t st_mode; 1657 nlink_t st_nlink; 1658 uid_t st_uid; 1659 gid_t st_gid; 1660 dev_t st_rdev; 1661 struct timespec32 st_atimespec; 1662 struct timespec32 st_mtimespec; 1663 struct timespec32 st_ctimespec; 1664 off_t st_size; 1665 int64_t st_blocks; 1666 u_int32_t st_blksize; 1667 u_int32_t st_flags; 1668 u_int32_t st_gen; 1669 struct timespec32 st_birthtimespec; 1670 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1671 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1672}; 1673 1674 1675CTASSERT(sizeof(struct stat32) == 96); 1676 1677static void 1678copy_stat( struct stat *in, struct stat32 *out) 1679{ 1680 CP(*in, *out, st_dev); 1681 CP(*in, *out, st_ino); 1682 CP(*in, *out, st_mode); 1683 CP(*in, *out, st_nlink); 1684 CP(*in, *out, st_uid); 1685 CP(*in, *out, st_gid); 1686 CP(*in, *out, st_rdev); 1687 TS_CP(*in, *out, st_atimespec); 1688 TS_CP(*in, *out, st_mtimespec); 1689 TS_CP(*in, *out, st_ctimespec); 1690 CP(*in, *out, st_size); 1691 CP(*in, *out, st_blocks); 1692 CP(*in, *out, st_blksize); 1693 CP(*in, *out, st_flags); 1694 CP(*in, *out, st_gen); 1695} 1696 1697int 1698freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 1699{ 1700 struct stat sb; 1701 struct stat32 sb32; 1702 int error; 1703 1704 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); 1705 if (error) 1706 return (error); 1707 copy_stat(&sb, &sb32); 1708 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1709 return (error); 1710} 1711 1712int 1713freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 1714{ 1715 struct stat ub; 1716 struct stat32 ub32; 1717 int error; 1718 1719 error = kern_fstat(td, uap->fd, &ub); 1720 if (error) 1721 return (error); 1722 copy_stat(&ub, &ub32); 1723 error = copyout(&ub32, uap->ub, sizeof(ub32)); 1724 return (error); 1725} 1726 1727int 1728freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 1729{ 1730 struct stat sb; 1731 struct stat32 sb32; 1732 int error; 1733 1734 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); 1735 if (error) 1736 return (error); 1737 copy_stat(&sb, &sb32); 1738 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1739 return (error); 1740} 1741 1742/* 1743 * MPSAFE 1744 */ 1745int 1746freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 1747{ 1748 int error, name[CTL_MAXNAME]; 1749 size_t j, oldlen; 1750 1751 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1752 return (EINVAL); 1753 error = copyin(uap->name, name, uap->namelen * sizeof(int)); 1754 if (error) 1755 return (error); 1756 mtx_lock(&Giant); 1757 if (uap->oldlenp) 1758 oldlen = fuword32(uap->oldlenp); 1759 else 1760 oldlen = 0; 1761 error = userland_sysctl(td, name, uap->namelen, 1762 uap->old, &oldlen, 1, 1763 uap->new, uap->newlen, &j, SCTL_MASK32); 1764 if (error && error != ENOMEM) 1765 goto done2; 1766 if (uap->oldlenp) 1767 suword32(uap->oldlenp, j); 1768done2: 1769 mtx_unlock(&Giant); 1770 return (error); 1771} 1772 1773struct sigaction32 { 1774 u_int32_t sa_u; 1775 int sa_flags; 1776 sigset_t sa_mask; 1777}; 1778 1779CTASSERT(sizeof(struct sigaction32) == 24); 1780 1781int 1782freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 1783{ 1784 struct sigaction32 s32; 1785 struct sigaction sa, osa, *sap; 1786 int error; 1787 1788 if (uap->act) { 1789 error = copyin(uap->act, &s32, sizeof(s32)); 1790 if (error) 1791 return (error); 1792 sa.sa_handler = PTRIN(s32.sa_u); 1793 CP(s32, sa, sa_flags); 1794 CP(s32, sa, sa_mask); 1795 sap = &sa; 1796 } else 1797 sap = NULL; 1798 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 1799 if (error == 0 && uap->oact != NULL) { 1800 s32.sa_u = PTROUT(osa.sa_handler); 1801 CP(osa, s32, sa_flags); 1802 CP(osa, s32, sa_mask); 1803 error = copyout(&s32, uap->oact, sizeof(s32)); 1804 } 1805 return (error); 1806} 1807 1808#ifdef COMPAT_FREEBSD4 1809int 1810freebsd4_freebsd32_sigaction(struct thread *td, 1811 struct freebsd4_freebsd32_sigaction_args *uap) 1812{ 1813 struct sigaction32 s32; 1814 struct sigaction sa, osa, *sap; 1815 int error; 1816 1817 if (uap->act) { 1818 error = copyin(uap->act, &s32, sizeof(s32)); 1819 if (error) 1820 return (error); 1821 sa.sa_handler = PTRIN(s32.sa_u); 1822 CP(s32, sa, sa_flags); 1823 CP(s32, sa, sa_mask); 1824 sap = &sa; 1825 } else 1826 sap = NULL; 1827 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1828 if (error == 0 && uap->oact != NULL) { 1829 s32.sa_u = PTROUT(osa.sa_handler); 1830 CP(osa, s32, sa_flags); 1831 CP(osa, s32, sa_mask); 1832 error = copyout(&s32, uap->oact, sizeof(s32)); 1833 } 1834 return (error); 1835} 1836#endif 1837 1838#ifdef COMPAT_43 1839struct osigaction32 { 1840 u_int32_t sa_u; 1841 osigset_t sa_mask; 1842 int sa_flags; 1843}; 1844 1845#define ONSIG 32 1846 1847int 1848ofreebsd32_sigaction(struct thread *td, 1849 struct ofreebsd32_sigaction_args *uap) 1850{ 1851 struct osigaction32 s32; 1852 struct sigaction sa, osa, *sap; 1853 int error; 1854 1855 if (uap->signum <= 0 || uap->signum >= ONSIG) 1856 return (EINVAL); 1857 1858 if (uap->nsa) { 1859 error = copyin(uap->nsa, &s32, sizeof(s32)); 1860 if (error) 1861 return (error); 1862 sa.sa_handler = PTRIN(s32.sa_u); 1863 CP(s32, sa, sa_flags); 1864 OSIG2SIG(s32.sa_mask, sa.sa_mask); 1865 sap = &sa; 1866 } else 1867 sap = NULL; 1868 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET); 1869 if (error == 0 && uap->osa != NULL) { 1870 s32.sa_u = PTROUT(osa.sa_handler); 1871 CP(osa, s32, sa_flags); 1872 SIG2OSIG(osa.sa_mask, s32.sa_mask); 1873 error = copyout(&s32, uap->osa, sizeof(s32)); 1874 } 1875 return (error); 1876} 1877 1878int 1879ofreebsd32_sigprocmask(struct thread *td, 1880 struct ofreebsd32_sigprocmask_args *uap) 1881{ 1882 sigset_t set, oset; 1883 int error; 1884 1885 OSIG2SIG(uap->mask, set); 1886 error = kern_sigprocmask(td, uap->how, &set, &oset, 1); 1887 SIG2OSIG(oset, td->td_retval[0]); 1888 return (error); 1889} 1890 1891int 1892ofreebsd32_sigpending(struct thread *td, 1893 struct ofreebsd32_sigpending_args *uap) 1894{ 1895 struct proc *p = td->td_proc; 1896 sigset_t siglist; 1897 1898 PROC_LOCK(p); 1899 siglist = p->p_siglist; 1900 SIGSETOR(siglist, td->td_siglist); 1901 PROC_UNLOCK(p); 1902 SIG2OSIG(siglist, td->td_retval[0]); 1903 return (0); 1904} 1905 1906struct sigvec32 { 1907 u_int32_t sv_handler; 1908 int sv_mask; 1909 int sv_flags; 1910}; 1911 1912int 1913ofreebsd32_sigvec(struct thread *td, 1914 struct ofreebsd32_sigvec_args *uap) 1915{ 1916 struct sigvec32 vec; 1917 struct sigaction sa, osa, *sap; 1918 int error; 1919 1920 if (uap->signum <= 0 || uap->signum >= ONSIG) 1921 return (EINVAL); 1922 1923 if (uap->nsv) { 1924 error = copyin(uap->nsv, &vec, sizeof(vec)); 1925 if (error) 1926 return (error); 1927 sa.sa_handler = PTRIN(vec.sv_handler); 1928 OSIG2SIG(vec.sv_mask, sa.sa_mask); 1929 sa.sa_flags = vec.sv_flags; 1930 sa.sa_flags ^= SA_RESTART; 1931 sap = &sa; 1932 } else 1933 sap = NULL; 1934 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET); 1935 if (error == 0 && uap->osv != NULL) { 1936 vec.sv_handler = PTROUT(osa.sa_handler); 1937 SIG2OSIG(osa.sa_mask, vec.sv_mask); 1938 vec.sv_flags = osa.sa_flags; 1939 vec.sv_flags &= ~SA_NOCLDWAIT; 1940 vec.sv_flags ^= SA_RESTART; 1941 error = copyout(&vec, uap->osv, sizeof(vec)); 1942 } 1943 return (error); 1944} 1945 1946int 1947ofreebsd32_sigblock(struct thread *td, 1948 struct ofreebsd32_sigblock_args *uap) 1949{ 1950 struct proc *p = td->td_proc; 1951 sigset_t set; 1952 1953 OSIG2SIG(uap->mask, set); 1954 SIG_CANTMASK(set); 1955 PROC_LOCK(p); 1956 SIG2OSIG(td->td_sigmask, td->td_retval[0]); 1957 SIGSETOR(td->td_sigmask, set); 1958 PROC_UNLOCK(p); 1959 return (0); 1960} 1961 1962int 1963ofreebsd32_sigsetmask(struct thread *td, 1964 struct ofreebsd32_sigsetmask_args *uap) 1965{ 1966 struct proc *p = td->td_proc; 1967 sigset_t set; 1968 1969 OSIG2SIG(uap->mask, set); 1970 SIG_CANTMASK(set); 1971 PROC_LOCK(p); 1972 SIG2OSIG(td->td_sigmask, td->td_retval[0]); 1973 SIGSETLO(td->td_sigmask, set); 1974 signotify(td); 1975 PROC_UNLOCK(p); 1976 return (0); 1977} 1978 1979int 1980ofreebsd32_sigsuspend(struct thread *td, 1981 struct ofreebsd32_sigsuspend_args *uap) 1982{ 1983 struct proc *p = td->td_proc; 1984 sigset_t mask; 1985 1986 PROC_LOCK(p); 1987 td->td_oldsigmask = td->td_sigmask; 1988 td->td_pflags |= TDP_OLDMASK; 1989 OSIG2SIG(uap->mask, mask); 1990 SIG_CANTMASK(mask); 1991 SIGSETLO(td->td_sigmask, mask); 1992 signotify(td); 1993 while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0) 1994 /* void */; 1995 PROC_UNLOCK(p); 1996 /* always return EINTR rather than ERESTART... */ 1997 return (EINTR); 1998} 1999 2000struct sigstack32 { 2001 u_int32_t ss_sp; 2002 int ss_onstack; 2003}; 2004 2005int 2006ofreebsd32_sigstack(struct thread *td, 2007 struct ofreebsd32_sigstack_args *uap) 2008{ 2009 struct sigstack32 s32; 2010 struct sigstack nss, oss; 2011 int error = 0; 2012 2013 if (uap->nss != NULL) { 2014 error = copyin(uap->nss, &s32, sizeof(s32)); 2015 if (error) 2016 return (error); 2017 nss.ss_sp = PTRIN(s32.ss_sp); 2018 CP(s32, nss, ss_onstack); 2019 } 2020 oss.ss_sp = td->td_sigstk.ss_sp; 2021 oss.ss_onstack = sigonstack(cpu_getstack(td)); 2022 if (uap->nss != NULL) { 2023 td->td_sigstk.ss_sp = nss.ss_sp; 2024 td->td_sigstk.ss_size = 0; 2025 td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK; 2026 td->td_pflags |= TDP_ALTSTACK; 2027 } 2028 if (uap->oss != NULL) { 2029 s32.ss_sp = PTROUT(oss.ss_sp); 2030 CP(oss, s32, ss_onstack); 2031 error = copyout(&s32, uap->oss, sizeof(s32)); 2032 } 2033 return (error); 2034} 2035#endif 2036 2037int 2038freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap) 2039{ 2040 struct timespec32 rmt32, rqt32; 2041 struct timespec rmt, rqt; 2042 int error; 2043 2044 error = copyin(uap->rqtp, &rqt32, sizeof(rqt32)); 2045 if (error) 2046 return (error); 2047 2048 CP(rqt32, rqt, tv_sec); 2049 CP(rqt32, rqt, tv_nsec); 2050 2051 if (uap->rmtp && 2052 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 2053 return (EFAULT); 2054 error = kern_nanosleep(td, &rqt, &rmt); 2055 if (error && uap->rmtp) { 2056 int error2; 2057 2058 CP(rmt, rmt32, tv_sec); 2059 CP(rmt, rmt32, tv_nsec); 2060 2061 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32)); 2062 if (error2) 2063 error = error2; 2064 } 2065 return (error); 2066} 2067 2068int 2069freebsd32_clock_gettime(struct thread *td, 2070 struct freebsd32_clock_gettime_args *uap) 2071{ 2072 struct timespec ats; 2073 struct timespec32 ats32; 2074 int error; 2075 2076 error = kern_clock_gettime(td, uap->clock_id, &ats); 2077 if (error == 0) { 2078 CP(ats, ats32, tv_sec); 2079 CP(ats, ats32, tv_nsec); 2080 error = copyout(&ats32, uap->tp, sizeof(ats32)); 2081 } 2082 return (error); 2083} 2084 2085int 2086freebsd32_clock_settime(struct thread *td, 2087 struct freebsd32_clock_settime_args *uap) 2088{ 2089 struct timespec ats; 2090 struct timespec32 ats32; 2091 int error; 2092 2093 error = copyin(uap->tp, &ats32, sizeof(ats32)); 2094 if (error) 2095 return (error); 2096 CP(ats32, ats, tv_sec); 2097 CP(ats32, ats, tv_nsec); 2098 2099 return (kern_clock_settime(td, uap->clock_id, &ats)); 2100} 2101 2102int 2103freebsd32_clock_getres(struct thread *td, 2104 struct freebsd32_clock_getres_args *uap) 2105{ 2106 struct timespec ts; 2107 struct timespec32 ts32; 2108 int error; 2109 2110 if (uap->tp == NULL) 2111 return (0); 2112 error = kern_clock_getres(td, uap->clock_id, &ts); 2113 if (error == 0) { 2114 CP(ts, ts32, tv_sec); 2115 CP(ts, ts32, tv_nsec); 2116 error = copyout(&ts32, uap->tp, sizeof(ts32)); 2117 } 2118 return (error); 2119} 2120 2121#if 0 2122 2123int 2124freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 2125{ 2126 int error; 2127 struct yyy32 *p32, s32; 2128 struct yyy *p = NULL, s; 2129 2130 if (uap->zzz) { 2131 error = copyin(uap->zzz, &s32, sizeof(s32)); 2132 if (error) 2133 return (error); 2134 /* translate in */ 2135 p = &s; 2136 } 2137 error = kern_xxx(td, p); 2138 if (error) 2139 return (error); 2140 if (uap->zzz) { 2141 /* translate out */ 2142 error = copyout(&s32, p32, sizeof(s32)); 2143 } 2144 return (error); 2145} 2146 2147#endif 2148