freebsd32_misc.c revision 151359
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 151359 2005-10-15 05:57:06Z 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/mman.h> 45#include <sys/module.h> 46#include <sys/mount.h> 47#include <sys/mutex.h> 48#include <sys/namei.h> 49#include <sys/param.h> 50#include <sys/proc.h> 51#include <sys/reboot.h> 52#include <sys/resource.h> 53#include <sys/resourcevar.h> 54#include <sys/selinfo.h> 55#include <sys/eventvar.h> /* Must come after sys/selinfo.h */ 56#include <sys/pipe.h> /* Must come after sys/selinfo.h */ 57#include <sys/signal.h> 58#include <sys/signalvar.h> 59#include <sys/socket.h> 60#include <sys/socketvar.h> 61#include <sys/stat.h> 62#include <sys/syscall.h> 63#include <sys/syscallsubr.h> 64#include <sys/sysctl.h> 65#include <sys/sysent.h> 66#include <sys/sysproto.h> 67#include <sys/systm.h> 68#include <sys/unistd.h> 69#include <sys/vnode.h> 70#include <sys/wait.h> 71 72#include <vm/vm.h> 73#include <vm/vm_kern.h> 74#include <vm/vm_param.h> 75#include <vm/pmap.h> 76#include <vm/vm_map.h> 77#include <vm/vm_object.h> 78#include <vm/vm_extern.h> 79 80#include <compat/freebsd32/freebsd32_util.h> 81#include <compat/freebsd32/freebsd32.h> 82#include <compat/freebsd32/freebsd32_proto.h> 83 84CTASSERT(sizeof(struct timeval32) == 8); 85CTASSERT(sizeof(struct timespec32) == 8); 86CTASSERT(sizeof(struct statfs32) == 256); 87CTASSERT(sizeof(struct rusage32) == 72); 88 89int 90freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap) 91{ 92 int error, status; 93 struct rusage32 ru32; 94 struct rusage ru, *rup; 95 96 if (uap->rusage != NULL) 97 rup = &ru; 98 else 99 rup = NULL; 100 error = kern_wait(td, uap->pid, &status, uap->options, rup); 101 if (error) 102 return (error); 103 if (uap->status != NULL) 104 error = copyout(&status, uap->status, sizeof(status)); 105 if (uap->rusage != NULL && error == 0) { 106 TV_CP(ru, ru32, ru_utime); 107 TV_CP(ru, ru32, ru_stime); 108 CP(ru, ru32, ru_maxrss); 109 CP(ru, ru32, ru_ixrss); 110 CP(ru, ru32, ru_idrss); 111 CP(ru, ru32, ru_isrss); 112 CP(ru, ru32, ru_minflt); 113 CP(ru, ru32, ru_majflt); 114 CP(ru, ru32, ru_nswap); 115 CP(ru, ru32, ru_inblock); 116 CP(ru, ru32, ru_oublock); 117 CP(ru, ru32, ru_msgsnd); 118 CP(ru, ru32, ru_msgrcv); 119 CP(ru, ru32, ru_nsignals); 120 CP(ru, ru32, ru_nvcsw); 121 CP(ru, ru32, ru_nivcsw); 122 error = copyout(&ru32, uap->rusage, sizeof(ru32)); 123 } 124 return (error); 125} 126 127#ifdef COMPAT_FREEBSD4 128static void 129copy_statfs(struct statfs *in, struct statfs32 *out) 130{ 131 CP(*in, *out, f_bsize); 132 CP(*in, *out, f_iosize); 133 CP(*in, *out, f_blocks); 134 CP(*in, *out, f_bfree); 135 CP(*in, *out, f_bavail); 136 CP(*in, *out, f_files); 137 CP(*in, *out, f_ffree); 138 CP(*in, *out, f_fsid); 139 CP(*in, *out, f_owner); 140 CP(*in, *out, f_type); 141 CP(*in, *out, f_flags); 142 CP(*in, *out, f_flags); 143 CP(*in, *out, f_syncwrites); 144 CP(*in, *out, f_asyncwrites); 145 bcopy(in->f_fstypename, 146 out->f_fstypename, MFSNAMELEN); 147 bcopy(in->f_mntonname, 148 out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 149 CP(*in, *out, f_syncreads); 150 CP(*in, *out, f_asyncreads); 151 bcopy(in->f_mntfromname, 152 out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 153} 154#endif 155 156#ifdef COMPAT_FREEBSD4 157int 158freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap) 159{ 160 struct statfs *buf, *sp; 161 struct statfs32 stat32; 162 size_t count, size; 163 int error; 164 165 count = uap->bufsize / sizeof(struct statfs32); 166 size = count * sizeof(struct statfs); 167 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags); 168 if (size > 0) { 169 count = td->td_retval[0]; 170 sp = buf; 171 while (count > 0 && error == 0) { 172 copy_statfs(sp, &stat32); 173 error = copyout(&stat32, uap->buf, sizeof(stat32)); 174 sp++; 175 uap->buf++; 176 count--; 177 } 178 free(buf, M_TEMP); 179 } 180 return (error); 181} 182#endif 183 184struct sigaltstack32 { 185 u_int32_t ss_sp; 186 u_int32_t ss_size; 187 int ss_flags; 188}; 189 190CTASSERT(sizeof(struct sigaltstack32) == 12); 191 192int 193freebsd32_sigaltstack(struct thread *td, 194 struct freebsd32_sigaltstack_args *uap) 195{ 196 struct sigaltstack32 s32; 197 struct sigaltstack ss, oss, *ssp; 198 int error; 199 200 if (uap->ss != NULL) { 201 error = copyin(uap->ss, &s32, sizeof(s32)); 202 if (error) 203 return (error); 204 PTRIN_CP(s32, ss, ss_sp); 205 CP(s32, ss, ss_size); 206 CP(s32, ss, ss_flags); 207 ssp = &ss; 208 } else 209 ssp = NULL; 210 error = kern_sigaltstack(td, ssp, &oss); 211 if (error == 0 && uap->oss != NULL) { 212 PTROUT_CP(oss, s32, ss_sp); 213 CP(oss, s32, ss_size); 214 CP(oss, s32, ss_flags); 215 error = copyout(&s32, uap->oss, sizeof(s32)); 216 } 217 return (error); 218} 219 220/* 221 * Custom version of exec_copyin_args() so that we can translate 222 * the pointers. 223 */ 224static int 225freebsd32_exec_copyin_args(struct image_args *args, char *fname, 226 enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv) 227{ 228 char *argp, *envp; 229 u_int32_t *p32, arg; 230 size_t length; 231 int error; 232 233 bzero(args, sizeof(*args)); 234 if (argv == NULL) 235 return (EFAULT); 236 237 /* 238 * Allocate temporary demand zeroed space for argument and 239 * environment strings 240 */ 241 args->buf = (char *) kmem_alloc_wait(exec_map, 242 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 243 if (args->buf == NULL) 244 return (ENOMEM); 245 args->begin_argv = args->buf; 246 args->endp = args->begin_argv; 247 args->stringspace = ARG_MAX; 248 249 args->fname = args->buf + ARG_MAX; 250 251 /* 252 * Copy the file name. 253 */ 254 error = (segflg == UIO_SYSSPACE) ? 255 copystr(fname, args->fname, PATH_MAX, &length) : 256 copyinstr(fname, args->fname, PATH_MAX, &length); 257 if (error != 0) 258 return (error); 259 260 /* 261 * extract arguments first 262 */ 263 p32 = argv; 264 for (;;) { 265 error = copyin(p32++, &arg, sizeof(arg)); 266 if (error) 267 return (error); 268 if (arg == 0) 269 break; 270 argp = PTRIN(arg); 271 error = copyinstr(argp, args->endp, args->stringspace, &length); 272 if (error) { 273 if (error == ENAMETOOLONG) 274 return (E2BIG); 275 else 276 return (error); 277 } 278 args->stringspace -= length; 279 args->endp += length; 280 args->argc++; 281 } 282 283 args->begin_envv = args->endp; 284 285 /* 286 * extract environment strings 287 */ 288 if (envv) { 289 p32 = envv; 290 for (;;) { 291 error = copyin(p32++, &arg, sizeof(arg)); 292 if (error) 293 return (error); 294 if (arg == 0) 295 break; 296 envp = PTRIN(arg); 297 error = copyinstr(envp, args->endp, args->stringspace, 298 &length); 299 if (error) { 300 if (error == ENAMETOOLONG) 301 return (E2BIG); 302 else 303 return (error); 304 } 305 args->stringspace -= length; 306 args->endp += length; 307 args->envc++; 308 } 309 } 310 311 return (0); 312} 313 314int 315freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) 316{ 317 struct image_args eargs; 318 int error; 319 320 error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE, 321 uap->argv, uap->envv); 322 if (error == 0) 323 error = kern_execve(td, &eargs, NULL); 324 exec_free_args(&eargs); 325 return (error); 326} 327 328#ifdef __ia64__ 329static int 330freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 331 int prot, int fd, off_t pos) 332{ 333 vm_map_t map; 334 vm_map_entry_t entry; 335 int rv; 336 337 map = &td->td_proc->p_vmspace->vm_map; 338 if (fd != -1) 339 prot |= VM_PROT_WRITE; 340 341 if (vm_map_lookup_entry(map, start, &entry)) { 342 if ((entry->protection & prot) != prot) { 343 rv = vm_map_protect(map, 344 trunc_page(start), 345 round_page(end), 346 entry->protection | prot, 347 FALSE); 348 if (rv != KERN_SUCCESS) 349 return (EINVAL); 350 } 351 } else { 352 vm_offset_t addr = trunc_page(start); 353 rv = vm_map_find(map, 0, 0, 354 &addr, PAGE_SIZE, FALSE, prot, 355 VM_PROT_ALL, 0); 356 if (rv != KERN_SUCCESS) 357 return (EINVAL); 358 } 359 360 if (fd != -1) { 361 struct pread_args r; 362 r.fd = fd; 363 r.buf = (void *) start; 364 r.nbyte = end - start; 365 r.offset = pos; 366 return (pread(td, &r)); 367 } else { 368 while (start < end) { 369 subyte((void *) start, 0); 370 start++; 371 } 372 return (0); 373 } 374} 375#endif 376 377int 378freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 379{ 380 struct mmap_args ap; 381 vm_offset_t addr = (vm_offset_t) uap->addr; 382 vm_size_t len = uap->len; 383 int prot = uap->prot; 384 int flags = uap->flags; 385 int fd = uap->fd; 386 off_t pos = (uap->poslo 387 | ((off_t)uap->poshi << 32)); 388#ifdef __ia64__ 389 vm_size_t pageoff; 390 int error; 391 392 /* 393 * Attempt to handle page size hassles. 394 */ 395 pageoff = (pos & PAGE_MASK); 396 if (flags & MAP_FIXED) { 397 vm_offset_t start, end; 398 start = addr; 399 end = addr + len; 400 401 mtx_lock(&Giant); 402 if (start != trunc_page(start)) { 403 error = freebsd32_mmap_partial(td, start, 404 round_page(start), prot, 405 fd, pos); 406 if (fd != -1) 407 pos += round_page(start) - start; 408 start = round_page(start); 409 } 410 if (end != round_page(end)) { 411 vm_offset_t t = trunc_page(end); 412 error = freebsd32_mmap_partial(td, t, end, 413 prot, fd, 414 pos + t - start); 415 end = trunc_page(end); 416 } 417 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 418 /* 419 * We can't map this region at all. The specified 420 * address doesn't have the same alignment as the file 421 * position. Fake the mapping by simply reading the 422 * entire region into memory. First we need to make 423 * sure the region exists. 424 */ 425 vm_map_t map; 426 struct pread_args r; 427 int rv; 428 429 prot |= VM_PROT_WRITE; 430 map = &td->td_proc->p_vmspace->vm_map; 431 rv = vm_map_remove(map, start, end); 432 if (rv != KERN_SUCCESS) { 433 mtx_unlock(&Giant); 434 return (EINVAL); 435 } 436 rv = vm_map_find(map, 0, 0, 437 &start, end - start, FALSE, 438 prot, VM_PROT_ALL, 0); 439 mtx_unlock(&Giant); 440 if (rv != KERN_SUCCESS) 441 return (EINVAL); 442 r.fd = fd; 443 r.buf = (void *) start; 444 r.nbyte = end - start; 445 r.offset = pos; 446 error = pread(td, &r); 447 if (error) 448 return (error); 449 450 td->td_retval[0] = addr; 451 return (0); 452 } 453 mtx_unlock(&Giant); 454 if (end == start) { 455 /* 456 * After dealing with the ragged ends, there 457 * might be none left. 458 */ 459 td->td_retval[0] = addr; 460 return (0); 461 } 462 addr = start; 463 len = end - start; 464 } 465#endif 466 467 ap.addr = (void *) addr; 468 ap.len = len; 469 ap.prot = prot; 470 ap.flags = flags; 471 ap.fd = fd; 472 ap.pos = pos; 473 474 return (mmap(td, &ap)); 475} 476 477struct itimerval32 { 478 struct timeval32 it_interval; 479 struct timeval32 it_value; 480}; 481 482CTASSERT(sizeof(struct itimerval32) == 16); 483 484int 485freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 486{ 487 struct itimerval itv, oitv, *itvp; 488 struct itimerval32 i32; 489 int error; 490 491 if (uap->itv != NULL) { 492 error = copyin(uap->itv, &i32, sizeof(i32)); 493 if (error) 494 return (error); 495 TV_CP(i32, itv, it_interval); 496 TV_CP(i32, itv, it_value); 497 itvp = &itv; 498 } else 499 itvp = NULL; 500 error = kern_setitimer(td, uap->which, itvp, &oitv); 501 if (error || uap->oitv == NULL) 502 return (error); 503 TV_CP(oitv, i32, it_interval); 504 TV_CP(oitv, i32, it_value); 505 return (copyout(&i32, uap->oitv, sizeof(i32))); 506} 507 508int 509freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap) 510{ 511 struct itimerval itv; 512 struct itimerval32 i32; 513 int error; 514 515 error = kern_getitimer(td, uap->which, &itv); 516 if (error || uap->itv == NULL) 517 return (error); 518 TV_CP(itv, i32, it_interval); 519 TV_CP(itv, i32, it_value); 520 return (copyout(&i32, uap->itv, sizeof(i32))); 521} 522 523int 524freebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 525{ 526 struct timeval32 tv32; 527 struct timeval tv, *tvp; 528 int error; 529 530 if (uap->tv != NULL) { 531 error = copyin(uap->tv, &tv32, sizeof(tv32)); 532 if (error) 533 return (error); 534 CP(tv32, tv, tv_sec); 535 CP(tv32, tv, tv_usec); 536 tvp = &tv; 537 } else 538 tvp = NULL; 539 /* 540 * XXX big-endian needs to convert the fd_sets too. 541 * XXX Do pointers need PTRIN()? 542 */ 543 return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp)); 544} 545 546struct kevent32 { 547 u_int32_t ident; /* identifier for this event */ 548 short filter; /* filter for event */ 549 u_short flags; 550 u_int fflags; 551 int32_t data; 552 u_int32_t udata; /* opaque user data identifier */ 553}; 554 555CTASSERT(sizeof(struct kevent32) == 20); 556static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count); 557static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count); 558 559/* 560 * Copy 'count' items into the destination list pointed to by uap->eventlist. 561 */ 562static int 563freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count) 564{ 565 struct freebsd32_kevent_args *uap; 566 struct kevent32 ks32[KQ_NEVENTS]; 567 int i, error = 0; 568 569 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 570 uap = (struct freebsd32_kevent_args *)arg; 571 572 for (i = 0; i < count; i++) { 573 CP(kevp[i], ks32[i], ident); 574 CP(kevp[i], ks32[i], filter); 575 CP(kevp[i], ks32[i], flags); 576 CP(kevp[i], ks32[i], fflags); 577 CP(kevp[i], ks32[i], data); 578 PTROUT_CP(kevp[i], ks32[i], udata); 579 } 580 error = copyout(ks32, uap->eventlist, count * sizeof *ks32); 581 if (error == 0) 582 uap->eventlist += count; 583 return (error); 584} 585 586/* 587 * Copy 'count' items from the list pointed to by uap->changelist. 588 */ 589static int 590freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count) 591{ 592 struct freebsd32_kevent_args *uap; 593 struct kevent32 ks32[KQ_NEVENTS]; 594 int i, error = 0; 595 596 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 597 uap = (struct freebsd32_kevent_args *)arg; 598 599 error = copyin(uap->changelist, ks32, count * sizeof *ks32); 600 if (error) 601 goto done; 602 uap->changelist += count; 603 604 for (i = 0; i < count; i++) { 605 CP(ks32[i], kevp[i], ident); 606 CP(ks32[i], kevp[i], filter); 607 CP(ks32[i], kevp[i], flags); 608 CP(ks32[i], kevp[i], fflags); 609 CP(ks32[i], kevp[i], data); 610 PTRIN_CP(ks32[i], kevp[i], udata); 611 } 612done: 613 return (error); 614} 615 616int 617freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 618{ 619 struct timespec32 ts32; 620 struct timespec ts, *tsp; 621 struct kevent_copyops k_ops = { uap, 622 freebsd32_kevent_copyout, 623 freebsd32_kevent_copyin}; 624 int error; 625 626 627 if (uap->timeout) { 628 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 629 if (error) 630 return (error); 631 CP(ts32, ts, tv_sec); 632 CP(ts32, ts, tv_nsec); 633 tsp = &ts; 634 } else 635 tsp = NULL; 636 error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents, 637 &k_ops, tsp); 638 return (error); 639} 640 641int 642freebsd32_gettimeofday(struct thread *td, 643 struct freebsd32_gettimeofday_args *uap) 644{ 645 struct timeval atv; 646 struct timeval32 atv32; 647 struct timezone rtz; 648 int error = 0; 649 650 if (uap->tp) { 651 microtime(&atv); 652 CP(atv, atv32, tv_sec); 653 CP(atv, atv32, tv_usec); 654 error = copyout(&atv32, uap->tp, sizeof (atv32)); 655 } 656 if (error == 0 && uap->tzp != NULL) { 657 rtz.tz_minuteswest = tz_minuteswest; 658 rtz.tz_dsttime = tz_dsttime; 659 error = copyout(&rtz, uap->tzp, sizeof (rtz)); 660 } 661 return (error); 662} 663 664int 665freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 666{ 667 struct rusage32 s32; 668 struct rusage s; 669 int error; 670 671 error = kern_getrusage(td, uap->who, &s); 672 if (error) 673 return (error); 674 if (uap->rusage != NULL) { 675 TV_CP(s, s32, ru_utime); 676 TV_CP(s, s32, ru_stime); 677 CP(s, s32, ru_maxrss); 678 CP(s, s32, ru_ixrss); 679 CP(s, s32, ru_idrss); 680 CP(s, s32, ru_isrss); 681 CP(s, s32, ru_minflt); 682 CP(s, s32, ru_majflt); 683 CP(s, s32, ru_nswap); 684 CP(s, s32, ru_inblock); 685 CP(s, s32, ru_oublock); 686 CP(s, s32, ru_msgsnd); 687 CP(s, s32, ru_msgrcv); 688 CP(s, s32, ru_nsignals); 689 CP(s, s32, ru_nvcsw); 690 CP(s, s32, ru_nivcsw); 691 error = copyout(&s32, uap->rusage, sizeof(s32)); 692 } 693 return (error); 694} 695 696struct iovec32 { 697 u_int32_t iov_base; 698 int iov_len; 699}; 700 701CTASSERT(sizeof(struct iovec32) == 8); 702 703static int 704freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) 705{ 706 struct iovec32 iov32; 707 struct iovec *iov; 708 struct uio *uio; 709 u_int iovlen; 710 int error, i; 711 712 *uiop = NULL; 713 if (iovcnt > UIO_MAXIOV) 714 return (EINVAL); 715 iovlen = iovcnt * sizeof(struct iovec); 716 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 717 iov = (struct iovec *)(uio + 1); 718 for (i = 0; i < iovcnt; i++) { 719 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); 720 if (error) { 721 free(uio, M_IOV); 722 return (error); 723 } 724 iov[i].iov_base = PTRIN(iov32.iov_base); 725 iov[i].iov_len = iov32.iov_len; 726 } 727 uio->uio_iov = iov; 728 uio->uio_iovcnt = iovcnt; 729 uio->uio_segflg = UIO_USERSPACE; 730 uio->uio_offset = -1; 731 uio->uio_resid = 0; 732 for (i = 0; i < iovcnt; i++) { 733 if (iov->iov_len > INT_MAX - uio->uio_resid) { 734 free(uio, M_IOV); 735 return (EINVAL); 736 } 737 uio->uio_resid += iov->iov_len; 738 iov++; 739 } 740 *uiop = uio; 741 return (0); 742} 743 744int 745freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 746{ 747 struct uio *auio; 748 int error; 749 750 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 751 if (error) 752 return (error); 753 error = kern_readv(td, uap->fd, auio); 754 free(auio, M_IOV); 755 return (error); 756} 757 758int 759freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 760{ 761 struct uio *auio; 762 int error; 763 764 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 765 if (error) 766 return (error); 767 error = kern_writev(td, uap->fd, auio); 768 free(auio, M_IOV); 769 return (error); 770} 771 772int 773freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap) 774{ 775 struct uio *auio; 776 int error; 777 778 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 779 if (error) 780 return (error); 781 error = kern_preadv(td, uap->fd, auio, uap->offset); 782 free(auio, M_IOV); 783 return (error); 784} 785 786int 787freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap) 788{ 789 struct uio *auio; 790 int error; 791 792 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 793 if (error) 794 return (error); 795 error = kern_pwritev(td, uap->fd, auio, uap->offset); 796 free(auio, M_IOV); 797 return (error); 798} 799 800static int 801freebsd32_copyiniov(struct iovec32 *iovp, u_int iovcnt, struct iovec **iov, 802 int error) 803{ 804 struct iovec32 iov32; 805 int i; 806 807 u_int iovlen; 808 809 *iov = NULL; 810 if (iovcnt > UIO_MAXIOV) 811 return (error); 812 iovlen = iovcnt * sizeof(struct iovec); 813 *iov = malloc(iovlen, M_IOV, M_WAITOK); 814 for (i = 0; i < iovcnt; i++) { 815 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); 816 if (error) { 817 free(*iov, M_IOV); 818 *iov = NULL; 819 return (error); 820 } 821 iov[i]->iov_base = PTRIN(iov32.iov_base); 822 iov[i]->iov_len = iov32.iov_len; 823 } 824 return (0); 825} 826 827struct msghdr32 { 828 u_int32_t msg_name; 829 socklen_t msg_namelen; 830 u_int32_t msg_iov; 831 int msg_iovlen; 832 u_int32_t msg_control; 833 socklen_t msg_controllen; 834 int msg_flags; 835}; 836CTASSERT(sizeof(struct msghdr32) == 28); 837 838static int 839freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg) 840{ 841 struct msghdr32 m32; 842 int error; 843 844 error = copyin(msg32, &m32, sizeof(m32)); 845 if (error) 846 return (error); 847 msg->msg_name = PTRIN(m32.msg_name); 848 msg->msg_namelen = m32.msg_namelen; 849 msg->msg_iov = PTRIN(m32.msg_iov); 850 msg->msg_iovlen = m32.msg_iovlen; 851 msg->msg_control = PTRIN(m32.msg_control); 852 msg->msg_controllen = m32.msg_controllen; 853 msg->msg_flags = m32.msg_flags; 854 return (freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, m32.msg_iovlen, &msg->msg_iov, 855 EMSGSIZE)); 856} 857 858static int 859freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32) 860{ 861 struct msghdr32 m32; 862 int error; 863 864 m32.msg_name = PTROUT(msg->msg_name); 865 m32.msg_namelen = msg->msg_namelen; 866 m32.msg_iov = PTROUT(msg->msg_iov); 867 m32.msg_iovlen = msg->msg_iovlen; 868 m32.msg_control = PTROUT(msg->msg_control); 869 m32.msg_controllen = msg->msg_controllen; 870 m32.msg_flags = msg->msg_flags; 871 error = copyout(&m32, msg32, sizeof(m32)); 872 return (error); 873} 874 875int 876freebsd32_recvmsg(td, uap) 877 struct thread *td; 878 struct freebsd32_recvmsg_args /* { 879 int s; 880 struct msghdr32 *msg; 881 int flags; 882 } */ *uap; 883{ 884 struct msghdr msg; 885 struct msghdr32 m32; 886 struct iovec *uiov, *iov; 887 int error; 888 889 error = copyin(uap->msg, &m32, sizeof(m32)); 890 if (error) 891 return (error); 892 error = freebsd32_copyinmsghdr(uap->msg, &msg); 893 if (error) 894 return (error); 895 error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, 896 m32.msg_iovlen, &iov, EMSGSIZE); 897 if (error) 898 return (error); 899 msg.msg_flags = uap->flags; 900 uiov = msg.msg_iov; 901 msg.msg_iov = iov; 902 error = kern_recvit(td, uap->s, &msg, NULL, UIO_SYSSPACE); 903 if (error == 0) { 904 msg.msg_iov = uiov; 905 error = freebsd32_copyoutmsghdr(&msg, uap->msg); 906 } 907 free(iov, M_IOV); 908 free(uiov, M_IOV); 909 return (error); 910} 911 912int 913freebsd32_sendmsg(struct thread *td, 914 struct freebsd32_sendmsg_args *uap) 915{ 916 struct msghdr msg; 917 struct msghdr32 m32; 918 struct iovec *iov; 919 int error; 920 921 error = copyin(uap->msg, &m32, sizeof(m32)); 922 if (error) 923 return (error); 924 error = freebsd32_copyinmsghdr(uap->msg, &msg); 925 if (error) 926 return (error); 927 error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, 928 m32.msg_iovlen, &iov, EMSGSIZE); 929 if (error) 930 return (error); 931 msg.msg_iov = iov; 932 error = kern_sendit(td, uap->s, &msg, uap->flags, NULL, UIO_SYSSPACE); 933 free(iov, M_IOV); 934 return (error); 935} 936 937int 938freebsd32_recvfrom(struct thread *td, 939 struct freebsd32_recvfrom_args *uap) 940{ 941 struct msghdr msg; 942 struct iovec aiov; 943 int error; 944 945 if (uap->fromlenaddr) { 946 error = copyin((void *)(uintptr_t)uap->fromlenaddr, 947 &msg.msg_namelen, sizeof(msg.msg_namelen)); 948 if (error) 949 return (error); 950 } else { 951 msg.msg_namelen = 0; 952 } 953 954 msg.msg_name = (void *)(uintptr_t)uap->from; 955 msg.msg_iov = &aiov; 956 msg.msg_iovlen = 1; 957 aiov.iov_base = (void *)(uintptr_t)uap->buf; 958 aiov.iov_len = uap->len; 959 msg.msg_control = 0; 960 msg.msg_flags = uap->flags; 961 error = kern_recvit(td, uap->s, &msg, (void *)(uintptr_t)uap->fromlenaddr, UIO_USERSPACE); 962 return (error); 963} 964 965int 966freebsd32_settimeofday(struct thread *td, 967 struct freebsd32_settimeofday_args *uap) 968{ 969 struct timeval32 tv32; 970 struct timeval tv, *tvp; 971 struct timezone tz, *tzp; 972 int error; 973 974 if (uap->tv) { 975 error = copyin(uap->tv, &tv32, sizeof(tv32)); 976 if (error) 977 return (error); 978 CP(tv32, tv, tv_sec); 979 CP(tv32, tv, tv_usec); 980 tvp = &tv; 981 } else 982 tvp = NULL; 983 if (uap->tzp) { 984 error = copyin(uap->tzp, &tz, sizeof(tz)); 985 if (error) 986 return (error); 987 tzp = &tz; 988 } else 989 tzp = NULL; 990 return (kern_settimeofday(td, tvp, tzp)); 991} 992 993int 994freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 995{ 996 struct timeval32 s32[2]; 997 struct timeval s[2], *sp; 998 int error; 999 1000 if (uap->tptr != NULL) { 1001 error = copyin(uap->tptr, s32, sizeof(s32)); 1002 if (error) 1003 return (error); 1004 CP(s32[0], s[0], tv_sec); 1005 CP(s32[0], s[0], tv_usec); 1006 CP(s32[1], s[1], tv_sec); 1007 CP(s32[1], s[1], tv_usec); 1008 sp = s; 1009 } else 1010 sp = NULL; 1011 return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 1012} 1013 1014int 1015freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 1016{ 1017 struct timeval32 tv32; 1018 struct timeval delta, olddelta, *deltap; 1019 int error; 1020 1021 if (uap->delta) { 1022 error = copyin(uap->delta, &tv32, sizeof(tv32)); 1023 if (error) 1024 return (error); 1025 CP(tv32, delta, tv_sec); 1026 CP(tv32, delta, tv_usec); 1027 deltap = δ 1028 } else 1029 deltap = NULL; 1030 error = kern_adjtime(td, deltap, &olddelta); 1031 if (uap->olddelta && error == 0) { 1032 CP(olddelta, tv32, tv_sec); 1033 CP(olddelta, tv32, tv_usec); 1034 error = copyout(&tv32, uap->olddelta, sizeof(tv32)); 1035 } 1036 return (error); 1037} 1038 1039#ifdef COMPAT_FREEBSD4 1040int 1041freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap) 1042{ 1043 struct statfs32 s32; 1044 struct statfs s; 1045 int error; 1046 1047 error = kern_statfs(td, uap->path, UIO_USERSPACE, &s); 1048 if (error) 1049 return (error); 1050 copy_statfs(&s, &s32); 1051 return (copyout(&s32, uap->buf, sizeof(s32))); 1052} 1053#endif 1054 1055#ifdef COMPAT_FREEBSD4 1056int 1057freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap) 1058{ 1059 struct statfs32 s32; 1060 struct statfs s; 1061 int error; 1062 1063 error = kern_fstatfs(td, uap->fd, &s); 1064 if (error) 1065 return (error); 1066 copy_statfs(&s, &s32); 1067 return (copyout(&s32, uap->buf, sizeof(s32))); 1068} 1069#endif 1070 1071#ifdef COMPAT_FREEBSD4 1072int 1073freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap) 1074{ 1075 struct statfs32 s32; 1076 struct statfs s; 1077 fhandle_t fh; 1078 int error; 1079 1080 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 1081 return (error); 1082 error = kern_fhstatfs(td, fh, &s); 1083 if (error) 1084 return (error); 1085 copy_statfs(&s, &s32); 1086 return (copyout(&s32, uap->buf, sizeof(s32))); 1087} 1088#endif 1089 1090int 1091freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 1092{ 1093 /* 1094 * Vector through to semsys if it is loaded. 1095 */ 1096 return sysent[SYS_semsys].sy_call(td, uap); 1097} 1098 1099int 1100freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 1101{ 1102 /* 1103 * Vector through to msgsys if it is loaded. 1104 */ 1105 return sysent[SYS_msgsys].sy_call(td, uap); 1106} 1107 1108int 1109freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 1110{ 1111 /* 1112 * Vector through to shmsys if it is loaded. 1113 */ 1114 return sysent[SYS_shmsys].sy_call(td, uap); 1115} 1116 1117int 1118freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 1119{ 1120 struct pread_args ap; 1121 1122 ap.fd = uap->fd; 1123 ap.buf = uap->buf; 1124 ap.nbyte = uap->nbyte; 1125 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1126 return (pread(td, &ap)); 1127} 1128 1129int 1130freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 1131{ 1132 struct pwrite_args ap; 1133 1134 ap.fd = uap->fd; 1135 ap.buf = uap->buf; 1136 ap.nbyte = uap->nbyte; 1137 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1138 return (pwrite(td, &ap)); 1139} 1140 1141int 1142freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 1143{ 1144 int error; 1145 struct lseek_args ap; 1146 off_t pos; 1147 1148 ap.fd = uap->fd; 1149 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1150 ap.whence = uap->whence; 1151 error = lseek(td, &ap); 1152 /* Expand the quad return into two parts for eax and edx */ 1153 pos = *(off_t *)(td->td_retval); 1154 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1155 td->td_retval[1] = pos >> 32; /* %edx */ 1156 return error; 1157} 1158 1159int 1160freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 1161{ 1162 struct truncate_args ap; 1163 1164 ap.path = uap->path; 1165 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1166 return (truncate(td, &ap)); 1167} 1168 1169int 1170freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 1171{ 1172 struct ftruncate_args ap; 1173 1174 ap.fd = uap->fd; 1175 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1176 return (ftruncate(td, &ap)); 1177} 1178 1179#ifdef COMPAT_FREEBSD4 1180int 1181freebsd4_freebsd32_sendfile(struct thread *td, 1182 struct freebsd4_freebsd32_sendfile_args *uap) 1183{ 1184 struct freebsd4_sendfile_args ap; 1185 1186 ap.fd = uap->fd; 1187 ap.s = uap->s; 1188 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1189 ap.nbytes = uap->nbytes; /* XXX check */ 1190 ap.hdtr = uap->hdtr; /* XXX check */ 1191 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1192 ap.flags = uap->flags; 1193 return (freebsd4_sendfile(td, &ap)); 1194} 1195#endif 1196 1197int 1198freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 1199{ 1200 struct sendfile_args ap; 1201 1202 ap.fd = uap->fd; 1203 ap.s = uap->s; 1204 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1205 ap.nbytes = uap->nbytes; /* XXX check */ 1206 ap.hdtr = uap->hdtr; /* XXX check */ 1207 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1208 ap.flags = uap->flags; 1209 return (sendfile(td, &ap)); 1210} 1211 1212struct stat32 { 1213 dev_t st_dev; 1214 ino_t st_ino; 1215 mode_t st_mode; 1216 nlink_t st_nlink; 1217 uid_t st_uid; 1218 gid_t st_gid; 1219 dev_t st_rdev; 1220 struct timespec32 st_atimespec; 1221 struct timespec32 st_mtimespec; 1222 struct timespec32 st_ctimespec; 1223 off_t st_size; 1224 int64_t st_blocks; 1225 u_int32_t st_blksize; 1226 u_int32_t st_flags; 1227 u_int32_t st_gen; 1228 struct timespec32 st_birthtimespec; 1229 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1230 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1231}; 1232 1233 1234CTASSERT(sizeof(struct stat32) == 96); 1235 1236static void 1237copy_stat( struct stat *in, struct stat32 *out) 1238{ 1239 CP(*in, *out, st_dev); 1240 CP(*in, *out, st_ino); 1241 CP(*in, *out, st_mode); 1242 CP(*in, *out, st_nlink); 1243 CP(*in, *out, st_uid); 1244 CP(*in, *out, st_gid); 1245 CP(*in, *out, st_rdev); 1246 TS_CP(*in, *out, st_atimespec); 1247 TS_CP(*in, *out, st_mtimespec); 1248 TS_CP(*in, *out, st_ctimespec); 1249 CP(*in, *out, st_size); 1250 CP(*in, *out, st_blocks); 1251 CP(*in, *out, st_blksize); 1252 CP(*in, *out, st_flags); 1253 CP(*in, *out, st_gen); 1254} 1255 1256int 1257freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 1258{ 1259 struct stat sb; 1260 struct stat32 sb32; 1261 int error; 1262 1263 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); 1264 if (error) 1265 return (error); 1266 copy_stat(&sb, &sb32); 1267 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1268 return (error); 1269} 1270 1271int 1272freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 1273{ 1274 struct stat ub; 1275 struct stat32 ub32; 1276 int error; 1277 1278 error = kern_fstat(td, uap->fd, &ub); 1279 if (error) 1280 return (error); 1281 copy_stat(&ub, &ub32); 1282 error = copyout(&ub32, uap->ub, sizeof(ub32)); 1283 return (error); 1284} 1285 1286int 1287freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 1288{ 1289 struct stat sb; 1290 struct stat32 sb32; 1291 int error; 1292 1293 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); 1294 if (error) 1295 return (error); 1296 copy_stat(&sb, &sb32); 1297 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1298 return (error); 1299} 1300 1301/* 1302 * MPSAFE 1303 */ 1304int 1305freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 1306{ 1307 int error, name[CTL_MAXNAME]; 1308 size_t j, oldlen; 1309 1310 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1311 return (EINVAL); 1312 error = copyin(uap->name, name, uap->namelen * sizeof(int)); 1313 if (error) 1314 return (error); 1315 mtx_lock(&Giant); 1316 if (uap->oldlenp) 1317 oldlen = fuword32(uap->oldlenp); 1318 else 1319 oldlen = 0; 1320 error = userland_sysctl(td, name, uap->namelen, 1321 uap->old, &oldlen, 1, 1322 uap->new, uap->newlen, &j, SCTL_MASK32); 1323 if (error && error != ENOMEM) 1324 goto done2; 1325 if (uap->oldlenp) 1326 suword32(uap->oldlenp, j); 1327done2: 1328 mtx_unlock(&Giant); 1329 return (error); 1330} 1331 1332struct sigaction32 { 1333 u_int32_t sa_u; 1334 int sa_flags; 1335 sigset_t sa_mask; 1336}; 1337 1338CTASSERT(sizeof(struct sigaction32) == 24); 1339 1340int 1341freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 1342{ 1343 struct sigaction32 s32; 1344 struct sigaction sa, osa, *sap; 1345 int error; 1346 1347 if (uap->act) { 1348 error = copyin(uap->act, &s32, sizeof(s32)); 1349 if (error) 1350 return (error); 1351 sa.sa_handler = PTRIN(s32.sa_u); 1352 CP(s32, sa, sa_flags); 1353 CP(s32, sa, sa_mask); 1354 sap = &sa; 1355 } else 1356 sap = NULL; 1357 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 1358 if (error == 0 && uap->oact != NULL) { 1359 s32.sa_u = PTROUT(osa.sa_handler); 1360 CP(osa, s32, sa_flags); 1361 CP(osa, s32, sa_mask); 1362 error = copyout(&s32, uap->oact, sizeof(s32)); 1363 } 1364 return (error); 1365} 1366 1367#ifdef COMPAT_FREEBSD4 1368int 1369freebsd4_freebsd32_sigaction(struct thread *td, 1370 struct freebsd4_freebsd32_sigaction_args *uap) 1371{ 1372 struct sigaction32 s32; 1373 struct sigaction sa, osa, *sap; 1374 int error; 1375 1376 if (uap->act) { 1377 error = copyin(uap->act, &s32, sizeof(s32)); 1378 if (error) 1379 return (error); 1380 sa.sa_handler = PTRIN(s32.sa_u); 1381 CP(s32, sa, sa_flags); 1382 CP(s32, sa, sa_mask); 1383 sap = &sa; 1384 } else 1385 sap = NULL; 1386 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1387 if (error == 0 && uap->oact != NULL) { 1388 s32.sa_u = PTROUT(osa.sa_handler); 1389 CP(osa, s32, sa_flags); 1390 CP(osa, s32, sa_mask); 1391 error = copyout(&s32, uap->oact, sizeof(s32)); 1392 } 1393 return (error); 1394} 1395#endif 1396 1397int 1398freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap) 1399{ 1400 struct timespec32 rmt32, rqt32; 1401 struct timespec rmt, rqt; 1402 int error; 1403 1404 error = copyin(uap->rqtp, &rqt32, sizeof(rqt32)); 1405 if (error) 1406 return (error); 1407 1408 CP(rqt32, rqt, tv_sec); 1409 CP(rqt32, rqt, tv_nsec); 1410 1411 if (uap->rmtp && 1412 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 1413 return (EFAULT); 1414 error = kern_nanosleep(td, &rqt, &rmt); 1415 if (error && uap->rmtp) { 1416 int error2; 1417 1418 CP(rmt, rmt32, tv_sec); 1419 CP(rmt, rmt32, tv_nsec); 1420 1421 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32)); 1422 if (error2) 1423 error = error2; 1424 } 1425 return (error); 1426} 1427 1428int 1429freebsd32_clock_gettime(struct thread *td, 1430 struct freebsd32_clock_gettime_args *uap) 1431{ 1432 struct timespec ats; 1433 struct timespec32 ats32; 1434 int error; 1435 1436 error = kern_clock_gettime(td, uap->clock_id, &ats); 1437 if (error == 0) { 1438 CP(ats, ats32, tv_sec); 1439 CP(ats, ats32, tv_nsec); 1440 error = copyout(&ats32, uap->tp, sizeof(ats32)); 1441 } 1442 return (error); 1443} 1444 1445int 1446freebsd32_clock_settime(struct thread *td, 1447 struct freebsd32_clock_settime_args *uap) 1448{ 1449 struct timespec ats; 1450 struct timespec32 ats32; 1451 int error; 1452 1453 error = copyin(uap->tp, &ats32, sizeof(ats32)); 1454 if (error) 1455 return (error); 1456 CP(ats32, ats, tv_sec); 1457 CP(ats32, ats, tv_nsec); 1458 1459 return (kern_clock_settime(td, uap->clock_id, &ats)); 1460} 1461 1462int 1463freebsd32_clock_getres(struct thread *td, 1464 struct freebsd32_clock_getres_args *uap) 1465{ 1466 struct timespec ts; 1467 struct timespec32 ts32; 1468 int error; 1469 1470 if (uap->tp == NULL) 1471 return (0); 1472 error = kern_clock_getres(td, uap->clock_id, &ts); 1473 if (error == 0) { 1474 CP(ts, ts32, tv_sec); 1475 CP(ts, ts32, tv_nsec); 1476 error = copyout(&ts32, uap->tp, sizeof(ts32)); 1477 } 1478 return (error); 1479} 1480 1481#if 0 1482 1483int 1484freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 1485{ 1486 int error; 1487 struct yyy32 *p32, s32; 1488 struct yyy *p = NULL, s; 1489 1490 if (uap->zzz) { 1491 error = copyin(uap->zzz, &s32, sizeof(s32)); 1492 if (error) 1493 return (error); 1494 /* translate in */ 1495 p = &s; 1496 } 1497 error = kern_xxx(td, p); 1498 if (error) 1499 return (error); 1500 if (uap->zzz) { 1501 /* translate out */ 1502 error = copyout(&s32, p32, sizeof(s32)); 1503 } 1504 return (error); 1505} 1506 1507#endif 1508