freebsd32_misc.c revision 147654
1193323Sed/*- 2193323Sed * Copyright (c) 2002 Doug Rabson 3193323Sed * All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer. 10193323Sed * 2. Redistributions in binary form must reproduce the above copyright 11193323Sed * notice, this list of conditions and the following disclaimer in the 12193323Sed * documentation and/or other materials provided with the distribution. 13193323Sed * 14193323Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15193323Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17193323Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24193323Sed * SUCH DAMAGE. 25193323Sed */ 26193323Sed 27198090Srdivacky#include <sys/cdefs.h> 28193323Sed__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 147654 2005-06-29 15:16:20Z jhb $"); 29193323Sed 30193323Sed#include "opt_compat.h" 31193323Sed 32198090Srdivacky#include <sys/param.h> 33193323Sed#include <sys/systm.h> 34193323Sed#include <sys/bus.h> 35193323Sed#include <sys/exec.h> 36193323Sed#include <sys/fcntl.h> 37193323Sed#include <sys/filedesc.h> 38193323Sed#include <sys/namei.h> 39193323Sed#include <sys/imgact.h> 40193323Sed#include <sys/kernel.h> 41193323Sed#include <sys/lock.h> 42193323Sed#include <sys/malloc.h> 43193323Sed#include <sys/file.h> /* Must come after sys/malloc.h */ 44193323Sed#include <sys/mman.h> 45193323Sed#include <sys/module.h> 46198892Srdivacky#include <sys/mount.h> 47193323Sed#include <sys/mutex.h> 48193323Sed#include <sys/namei.h> 49193323Sed#include <sys/param.h> 50193323Sed#include <sys/proc.h> 51193323Sed#include <sys/reboot.h> 52193323Sed#include <sys/resource.h> 53206083Srdivacky#include <sys/resourcevar.h> 54193323Sed#include <sys/selinfo.h> 55193323Sed#include <sys/eventvar.h> /* Must come after sys/selinfo.h */ 56193323Sed#include <sys/pipe.h> /* Must come after sys/selinfo.h */ 57193323Sed#include <sys/signal.h> 58193323Sed#include <sys/signalvar.h> 59193323Sed#include <sys/socket.h> 60193323Sed#include <sys/socketvar.h> 61193323Sed#include <sys/stat.h> 62193323Sed#include <sys/syscallsubr.h> 63193323Sed#include <sys/sysctl.h> 64193323Sed#include <sys/sysent.h> 65193323Sed#include <sys/sysproto.h> 66193323Sed#include <sys/systm.h> 67193323Sed#include <sys/unistd.h> 68193323Sed#include <sys/vnode.h> 69193323Sed#include <sys/wait.h> 70193323Sed 71193323Sed#include <vm/vm.h> 72193323Sed#include <vm/vm_kern.h> 73193323Sed#include <vm/vm_param.h> 74193323Sed#include <vm/pmap.h> 75206083Srdivacky#include <vm/vm_map.h> 76198090Srdivacky#include <vm/vm_object.h> 77193323Sed#include <vm/vm_extern.h> 78193323Sed 79193323Sed#include <compat/freebsd32/freebsd32_util.h> 80193323Sed#include <compat/freebsd32/freebsd32.h> 81193323Sed#include <compat/freebsd32/freebsd32_proto.h> 82193323Sed 83193323SedCTASSERT(sizeof(struct timeval32) == 8); 84193323SedCTASSERT(sizeof(struct timespec32) == 8); 85193323SedCTASSERT(sizeof(struct statfs32) == 256); 86193323SedCTASSERT(sizeof(struct rusage32) == 72); 87193323Sed 88193323Sedint 89193323Sedfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap) 90193323Sed{ 91193323Sed int error, status; 92193323Sed struct rusage32 ru32; 93193323Sed struct rusage ru, *rup; 94193323Sed 95193323Sed if (uap->rusage != NULL) 96193323Sed rup = &ru; 97193323Sed else 98193323Sed rup = NULL; 99193323Sed error = kern_wait(td, uap->pid, &status, uap->options, rup); 100193323Sed if (error) 101193323Sed return (error); 102193323Sed if (uap->status != NULL) 103193323Sed error = copyout(&status, uap->status, sizeof(status)); 104193323Sed if (uap->rusage != NULL && error == 0) { 105193323Sed TV_CP(ru, ru32, ru_utime); 106193323Sed TV_CP(ru, ru32, ru_stime); 107193323Sed CP(ru, ru32, ru_maxrss); 108193323Sed CP(ru, ru32, ru_ixrss); 109193323Sed CP(ru, ru32, ru_idrss); 110193323Sed CP(ru, ru32, ru_isrss); 111193323Sed CP(ru, ru32, ru_minflt); 112193323Sed CP(ru, ru32, ru_majflt); 113193323Sed CP(ru, ru32, ru_nswap); 114193323Sed CP(ru, ru32, ru_inblock); 115193323Sed CP(ru, ru32, ru_oublock); 116193323Sed CP(ru, ru32, ru_msgsnd); 117193323Sed CP(ru, ru32, ru_msgrcv); 118193323Sed CP(ru, ru32, ru_nsignals); 119193323Sed CP(ru, ru32, ru_nvcsw); 120193323Sed CP(ru, ru32, ru_nivcsw); 121193323Sed error = copyout(&ru32, uap->rusage, sizeof(ru32)); 122193323Sed } 123210299Sed return (error); 124210299Sed} 125212904Sdim 126210299Sed#ifdef COMPAT_FREEBSD4 127193323Sedstatic void 128193323Sedcopy_statfs(struct statfs *in, struct statfs32 *out) 129212904Sdim{ 130210299Sed CP(*in, *out, f_bsize); 131193323Sed CP(*in, *out, f_iosize); 132193323Sed CP(*in, *out, f_blocks); 133193323Sed CP(*in, *out, f_bfree); 134193323Sed CP(*in, *out, f_bavail); 135193323Sed CP(*in, *out, f_files); 136193323Sed CP(*in, *out, f_ffree); 137206083Srdivacky CP(*in, *out, f_fsid); 138193323Sed CP(*in, *out, f_owner); 139206083Srdivacky CP(*in, *out, f_type); 140193323Sed CP(*in, *out, f_flags); 141206083Srdivacky CP(*in, *out, f_flags); 142193323Sed CP(*in, *out, f_syncwrites); 143193323Sed CP(*in, *out, f_asyncwrites); 144193323Sed bcopy(in->f_fstypename, 145193323Sed out->f_fstypename, MFSNAMELEN); 146193323Sed bcopy(in->f_mntonname, 147193323Sed out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 148193323Sed CP(*in, *out, f_syncreads); 149193323Sed CP(*in, *out, f_asyncreads); 150193323Sed bcopy(in->f_mntfromname, 151193323Sed out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 152193323Sed} 153193323Sed#endif 154212904Sdim 155193323Sed#ifdef COMPAT_FREEBSD4 156193323Sedint 157193323Sedfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap) 158193323Sed{ 159193323Sed struct statfs *buf, *sp; 160193323Sed struct statfs32 stat32; 161193323Sed size_t count, size; 162212904Sdim int error; 163210299Sed 164193323Sed count = uap->bufsize / sizeof(struct statfs32); 165193323Sed size = count * sizeof(struct statfs); 166193323Sed error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags); 167193323Sed if (size > 0) { 168193323Sed count = td->td_retval[0]; 169212904Sdim sp = buf; 170212904Sdim while (count > 0 && error == 0) { 171212904Sdim copy_statfs(sp, &stat32); 172193323Sed error = copyout(&stat32, uap->buf, sizeof(stat32)); 173193323Sed sp++; 174193323Sed uap->buf++; 175193323Sed count--; 176193323Sed } 177193323Sed free(buf, M_TEMP); 178193323Sed } 179193323Sed return (error); 180193323Sed} 181193323Sed#endif 182193323Sed 183193323Sedstruct sigaltstack32 { 184193323Sed u_int32_t ss_sp; 185193323Sed u_int32_t ss_size; 186194178Sed int ss_flags; 187194178Sed}; 188193323Sed 189193323SedCTASSERT(sizeof(struct sigaltstack32) == 12); 190193323Sed 191193323Sedint 192193323Sedfreebsd32_sigaltstack(struct thread *td, 193193323Sed struct freebsd32_sigaltstack_args *uap) 194193323Sed{ 195193323Sed struct sigaltstack32 s32; 196193323Sed struct sigaltstack ss, oss, *ssp; 197193323Sed int error; 198193323Sed 199193323Sed if (uap->ss != NULL) { 200193323Sed error = copyin(uap->ss, &s32, sizeof(s32)); 201193323Sed if (error) 202193323Sed return (error); 203193323Sed PTRIN_CP(s32, ss, ss_sp); 204193323Sed CP(s32, ss, ss_size); 205193323Sed CP(s32, ss, ss_flags); 206206083Srdivacky ssp = &ss; 207193323Sed } else 208198090Srdivacky ssp = NULL; 209198090Srdivacky error = kern_sigaltstack(td, ssp, &oss); 210193323Sed if (error == 0 && uap->oss != NULL) { 211193323Sed PTROUT_CP(oss, s32, ss_sp); 212193323Sed CP(oss, s32, ss_size); 213193323Sed CP(oss, s32, ss_flags); 214193323Sed error = copyout(&s32, uap->oss, sizeof(s32)); 215193323Sed } 216193323Sed return (error); 217193323Sed} 218193323Sed 219193323Sed/* 220193323Sed * Custom version of exec_copyin_args() so that we can translate 221193323Sed * the pointers. 222193323Sed */ 223212904Sdimstatic int 224193323Sedfreebsd32_exec_copyin_args(struct image_args *args, char *fname, 225193323Sed enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv) 226193323Sed{ 227212904Sdim char *argp, *envp; 228193323Sed u_int32_t *p32, arg; 229193323Sed size_t length; 230193323Sed int error; 231193323Sed 232193323Sed bzero(args, sizeof(*args)); 233193323Sed if (argv == NULL) 234193323Sed return (EFAULT); 235206083Srdivacky 236193323Sed /* 237193323Sed * Allocate temporary demand zeroed space for argument and 238193323Sed * environment strings 239193323Sed */ 240193323Sed args->buf = (char *) kmem_alloc_wait(exec_map, 241193323Sed PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 242193323Sed if (args->buf == NULL) 243193323Sed return (ENOMEM); 244193323Sed args->begin_argv = args->buf; 245193323Sed args->endp = args->begin_argv; 246193323Sed args->stringspace = ARG_MAX; 247193323Sed 248193323Sed args->fname = args->buf + ARG_MAX; 249193323Sed 250193323Sed /* 251193323Sed * Copy the file name. 252193323Sed */ 253212904Sdim error = (segflg == UIO_SYSSPACE) ? 254207618Srdivacky copystr(fname, args->fname, PATH_MAX, &length) : 255193323Sed copyinstr(fname, args->fname, PATH_MAX, &length); 256193323Sed if (error != 0) 257193323Sed return (error); 258193323Sed 259193323Sed /* 260193323Sed * extract arguments first 261193323Sed */ 262193323Sed p32 = argv; 263193323Sed for (;;) { 264193323Sed error = copyin(p32++, &arg, sizeof(arg)); 265193323Sed if (error) 266193323Sed return (error); 267193323Sed if (arg == 0) 268193323Sed break; 269193323Sed argp = PTRIN(arg); 270193323Sed error = copyinstr(argp, args->endp, args->stringspace, &length); 271193323Sed if (error) { 272193323Sed if (error == ENAMETOOLONG) 273193323Sed return (E2BIG); 274193323Sed else 275193323Sed return (error); 276193323Sed } 277193323Sed args->stringspace -= length; 278193323Sed args->endp += length; 279193323Sed args->argc++; 280193323Sed } 281193323Sed 282193323Sed args->begin_envv = args->endp; 283193323Sed 284193323Sed /* 285193323Sed * extract environment strings 286193323Sed */ 287193323Sed if (envv) { 288193323Sed p32 = envv; 289193323Sed for (;;) { 290193323Sed error = copyin(p32++, &arg, sizeof(arg)); 291193323Sed if (error) 292206083Srdivacky return (error); 293193323Sed if (arg == 0) 294193323Sed break; 295193323Sed envp = PTRIN(arg); 296193323Sed error = copyinstr(envp, args->endp, args->stringspace, 297193323Sed &length); 298193323Sed if (error) { 299193323Sed if (error == ENAMETOOLONG) 300193323Sed return (E2BIG); 301193323Sed else 302193323Sed return (error); 303193323Sed } 304193323Sed args->stringspace -= length; 305193323Sed args->endp += length; 306193323Sed args->envc++; 307193323Sed } 308193323Sed } 309193323Sed 310193323Sed return (0); 311193323Sed} 312193323Sed 313193323Sedint 314193323Sedfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) 315193323Sed{ 316193323Sed struct image_args eargs; 317206083Srdivacky int error; 318193323Sed 319193323Sed error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE, 320193323Sed uap->argv, uap->envv); 321193323Sed if (error == 0) 322206083Srdivacky error = kern_execve(td, &eargs, NULL); 323206083Srdivacky exec_free_args(&eargs); 324206083Srdivacky return (error); 325206083Srdivacky} 326193323Sed 327193323Sed#ifdef __ia64__ 328193323Sedstatic int 329193323Sedfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 330193323Sed int prot, int fd, off_t pos) 331193323Sed{ 332193323Sed vm_map_t map; 333193323Sed vm_map_entry_t entry; 334206083Srdivacky int rv; 335193323Sed 336193323Sed map = &td->td_proc->p_vmspace->vm_map; 337193323Sed if (fd != -1) 338193323Sed prot |= VM_PROT_WRITE; 339193323Sed 340193323Sed if (vm_map_lookup_entry(map, start, &entry)) { 341193323Sed if ((entry->protection & prot) != prot) { 342193323Sed rv = vm_map_protect(map, 343193323Sed trunc_page(start), 344193323Sed round_page(end), 345193323Sed entry->protection | prot, 346206083Srdivacky FALSE); 347193323Sed if (rv != KERN_SUCCESS) 348193323Sed return (EINVAL); 349193323Sed } 350193323Sed } else { 351193323Sed vm_offset_t addr = trunc_page(start); 352193323Sed rv = vm_map_find(map, 0, 0, 353193323Sed &addr, PAGE_SIZE, FALSE, prot, 354206083Srdivacky VM_PROT_ALL, 0); 355206083Srdivacky if (rv != KERN_SUCCESS) 356206083Srdivacky return (EINVAL); 357193323Sed } 358193323Sed 359206083Srdivacky if (fd != -1) { 360193323Sed struct pread_args r; 361193323Sed r.fd = fd; 362193323Sed r.buf = (void *) start; 363193323Sed r.nbyte = end - start; 364206083Srdivacky r.offset = pos; 365193323Sed return (pread(td, &r)); 366193323Sed } else { 367193323Sed while (start < end) { 368193323Sed subyte((void *) start, 0); 369193323Sed start++; 370206083Srdivacky } 371206083Srdivacky return (0); 372193323Sed } 373193323Sed} 374193323Sed#endif 375193323Sed 376193323Sedint 377193323Sedfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 378193323Sed{ 379193323Sed struct mmap_args ap; 380193323Sed vm_offset_t addr = (vm_offset_t) uap->addr; 381193323Sed vm_size_t len = uap->len; 382193323Sed int prot = uap->prot; 383193323Sed int flags = uap->flags; 384193323Sed int fd = uap->fd; 385193323Sed off_t pos = (uap->poslo 386193323Sed | ((off_t)uap->poshi << 32)); 387193323Sed#ifdef __ia64__ 388193323Sed vm_size_t pageoff; 389193323Sed int error; 390206083Srdivacky 391193323Sed /* 392193323Sed * Attempt to handle page size hassles. 393193323Sed */ 394206083Srdivacky pageoff = (pos & PAGE_MASK); 395193323Sed if (flags & MAP_FIXED) { 396193323Sed vm_offset_t start, end; 397193323Sed start = addr; 398193323Sed end = addr + len; 399193323Sed 400193323Sed if (start != trunc_page(start)) { 401193323Sed error = freebsd32_mmap_partial(td, start, 402193323Sed round_page(start), prot, 403193323Sed fd, pos); 404193323Sed if (fd != -1) 405193323Sed pos += round_page(start) - start; 406193323Sed start = round_page(start); 407193323Sed } 408193323Sed if (end != round_page(end)) { 409193323Sed vm_offset_t t = trunc_page(end); 410193323Sed error = freebsd32_mmap_partial(td, t, end, 411206083Srdivacky prot, fd, 412193323Sed pos + t - start); 413193323Sed end = trunc_page(end); 414193323Sed } 415193323Sed if (end > start && fd != -1 && (pos & PAGE_MASK)) { 416193323Sed /* 417193323Sed * We can't map this region at all. The specified 418193323Sed * address doesn't have the same alignment as the file 419193323Sed * position. Fake the mapping by simply reading the 420193323Sed * entire region into memory. First we need to make 421193323Sed * sure the region exists. 422193323Sed */ 423206083Srdivacky vm_map_t map; 424206083Srdivacky struct pread_args r; 425193323Sed int rv; 426193323Sed 427193323Sed prot |= VM_PROT_WRITE; 428193323Sed map = &td->td_proc->p_vmspace->vm_map; 429193323Sed rv = vm_map_remove(map, start, end); 430193323Sed if (rv != KERN_SUCCESS) 431193323Sed return (EINVAL); 432193323Sed rv = vm_map_find(map, 0, 0, 433193323Sed &start, end - start, FALSE, 434193323Sed prot, VM_PROT_ALL, 0); 435193323Sed if (rv != KERN_SUCCESS) 436193323Sed return (EINVAL); 437202375Srdivacky r.fd = fd; 438193323Sed r.buf = (void *) start; 439193323Sed r.nbyte = end - start; 440193323Sed r.offset = pos; 441193323Sed error = pread(td, &r); 442193323Sed if (error) 443206083Srdivacky return (error); 444206083Srdivacky 445193323Sed td->td_retval[0] = addr; 446193323Sed return (0); 447206083Srdivacky } 448206083Srdivacky if (end == start) { 449193323Sed /* 450193323Sed * After dealing with the ragged ends, there 451193323Sed * might be none left. 452193323Sed */ 453193323Sed td->td_retval[0] = addr; 454206083Srdivacky return (0); 455193323Sed } 456193323Sed addr = start; 457193323Sed len = end - start; 458193323Sed } 459193323Sed#endif 460193323Sed 461193323Sed ap.addr = (void *) addr; 462193323Sed ap.len = len; 463193323Sed ap.prot = prot; 464193323Sed ap.flags = flags; 465193323Sed ap.fd = fd; 466193323Sed ap.pos = pos; 467206083Srdivacky 468193323Sed return (mmap(td, &ap)); 469206083Srdivacky} 470193323Sed 471193323Sedstruct itimerval32 { 472193323Sed struct timeval32 it_interval; 473193323Sed struct timeval32 it_value; 474193323Sed}; 475193323Sed 476193323SedCTASSERT(sizeof(struct itimerval32) == 16); 477193323Sed 478193323Sedint 479193323Sedfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 480193323Sed{ 481193323Sed struct itimerval itv, oitv, *itvp; 482193323Sed struct itimerval32 i32; 483193323Sed int error; 484193323Sed 485193323Sed if (uap->itv != NULL) { 486193323Sed error = copyin(uap->itv, &i32, sizeof(i32)); 487193323Sed if (error) 488193323Sed return (error); 489193323Sed TV_CP(i32, itv, it_interval); 490193323Sed TV_CP(i32, itv, it_value); 491193323Sed itvp = &itv; 492193323Sed } else 493193323Sed itvp = NULL; 494193323Sed error = kern_setitimer(td, uap->which, itvp, &oitv); 495193323Sed if (error || uap->oitv == NULL) 496193323Sed return (error); 497193323Sed TV_CP(oitv, i32, it_interval); 498193323Sed TV_CP(oitv, i32, it_value); 499193323Sed return (copyout(&i32, uap->oitv, sizeof(i32))); 500193323Sed} 501202375Srdivacky 502193323Sedint 503193323Sedfreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap) 504193323Sed{ 505193323Sed struct itimerval itv; 506206083Srdivacky struct itimerval32 i32; 507193323Sed int error; 508193323Sed 509193323Sed error = kern_getitimer(td, uap->which, &itv); 510193323Sed if (error || uap->itv == NULL) 511193323Sed return (error); 512193323Sed TV_CP(itv, i32, it_interval); 513193323Sed TV_CP(itv, i32, it_value); 514193323Sed return (copyout(&i32, uap->itv, sizeof(i32))); 515193323Sed} 516193323Sed 517193323Sedint 518193323Sedfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 519193323Sed{ 520193323Sed struct timeval32 tv32; 521193323Sed struct timeval tv, *tvp; 522193323Sed int error; 523193323Sed 524193323Sed if (uap->tv != NULL) { 525193323Sed error = copyin(uap->tv, &tv32, sizeof(tv32)); 526193323Sed if (error) 527193323Sed return (error); 528193323Sed CP(tv32, tv, tv_sec); 529193323Sed CP(tv32, tv, tv_usec); 530193323Sed tvp = &tv; 531193323Sed } else 532193323Sed tvp = NULL; 533193323Sed /* 534193323Sed * XXX big-endian needs to convert the fd_sets too. 535193323Sed * XXX Do pointers need PTRIN()? 536193323Sed */ 537193323Sed return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp)); 538193323Sed} 539193323Sed 540193323Sedstruct kevent32 { 541193323Sed u_int32_t ident; /* identifier for this event */ 542193323Sed short filter; /* filter for event */ 543202375Srdivacky u_short flags; 544208599Srdivacky u_int fflags; 545208599Srdivacky int32_t data; 546208599Srdivacky u_int32_t udata; /* opaque user data identifier */ 547208599Srdivacky}; 548208599Srdivacky 549208599SrdivackyCTASSERT(sizeof(struct kevent32) == 20); 550208599Srdivackystatic int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count); 551208599Srdivackystatic int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count); 552193323Sed 553193323Sed/* 554193323Sed * Copy 'count' items into the destination list pointed to by uap->eventlist. 555193323Sed */ 556193323Sedstatic int 557193323Sedfreebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count) 558193323Sed{ 559193323Sed struct freebsd32_kevent_args *uap; 560193323Sed struct kevent32 ks32[KQ_NEVENTS]; 561193323Sed int i, error = 0; 562193323Sed 563193323Sed KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 564202375Srdivacky uap = (struct freebsd32_kevent_args *)arg; 565193323Sed 566193323Sed for (i = 0; i < count; i++) { 567193323Sed CP(kevp[i], ks32[i], ident); 568193323Sed CP(kevp[i], ks32[i], filter); 569193323Sed CP(kevp[i], ks32[i], flags); 570193323Sed CP(kevp[i], ks32[i], fflags); 571193323Sed CP(kevp[i], ks32[i], data); 572193323Sed PTROUT_CP(kevp[i], ks32[i], udata); 573193323Sed } 574193323Sed error = copyout(ks32, uap->eventlist, count * sizeof *ks32); 575193323Sed if (error == 0) 576193323Sed uap->eventlist += count; 577193323Sed return (error); 578193323Sed} 579193323Sed 580193323Sed/* 581193323Sed * Copy 'count' items from the list pointed to by uap->changelist. 582193323Sed */ 583193323Sedstatic int 584193323Sedfreebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count) 585193323Sed{ 586193323Sed struct freebsd32_kevent_args *uap; 587193323Sed struct kevent32 ks32[KQ_NEVENTS]; 588193323Sed int i, error = 0; 589193323Sed 590193323Sed KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 591193323Sed uap = (struct freebsd32_kevent_args *)arg; 592193323Sed 593193323Sed error = copyin(uap->changelist, ks32, count * sizeof *ks32); 594193323Sed if (error) 595193323Sed goto done; 596193323Sed uap->changelist += count; 597193323Sed 598193323Sed for (i = 0; i < count; i++) { 599193323Sed CP(ks32[i], kevp[i], ident); 600193323Sed CP(ks32[i], kevp[i], filter); 601193323Sed CP(ks32[i], kevp[i], flags); 602193323Sed CP(ks32[i], kevp[i], fflags); 603193323Sed CP(ks32[i], kevp[i], data); 604193323Sed PTRIN_CP(ks32[i], kevp[i], udata); 605193323Sed } 606193323Seddone: 607193323Sed return (error); 608193323Sed} 609193323Sed 610193323Sedint 611193323Sedfreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 612206083Srdivacky{ 613193323Sed struct timespec32 ts32; 614193323Sed struct timespec ts, *tsp; 615193323Sed struct kevent_copyops k_ops = { uap, 616206083Srdivacky freebsd32_kevent_copyout, 617206083Srdivacky freebsd32_kevent_copyin}; 618193323Sed int error; 619193323Sed 620193323Sed 621193323Sed if (uap->timeout) { 622193323Sed error = copyin(uap->timeout, &ts32, sizeof(ts32)); 623193323Sed if (error) 624193323Sed return (error); 625193323Sed CP(ts32, ts, tv_sec); 626193323Sed CP(ts32, ts, tv_nsec); 627193323Sed tsp = &ts; 628193323Sed } else 629202375Srdivacky tsp = NULL; 630198090Srdivacky error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents, 631193323Sed &k_ops, tsp); 632193323Sed return (error); 633193323Sed} 634193323Sed 635193323Sedint 636193323Sedfreebsd32_gettimeofday(struct thread *td, 637193323Sed struct freebsd32_gettimeofday_args *uap) 638193323Sed{ 639202375Srdivacky struct timeval atv; 640198090Srdivacky struct timeval32 atv32; 641193323Sed struct timezone rtz; 642193323Sed int error = 0; 643193323Sed 644193323Sed if (uap->tp) { 645193323Sed microtime(&atv); 646193323Sed CP(atv, atv32, tv_sec); 647193323Sed CP(atv, atv32, tv_usec); 648193323Sed error = copyout(&atv32, uap->tp, sizeof (atv32)); 649193323Sed } 650198090Srdivacky if (error == 0 && uap->tzp != NULL) { 651193323Sed rtz.tz_minuteswest = tz_minuteswest; 652193323Sed rtz.tz_dsttime = tz_dsttime; 653193323Sed error = copyout(&rtz, uap->tzp, sizeof (rtz)); 654193323Sed } 655193323Sed return (error); 656193323Sed} 657198090Srdivacky 658193323Sedint 659193323Sedfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 660193323Sed{ 661193323Sed struct rusage32 s32; 662193323Sed struct rusage s; 663193323Sed int error; 664193323Sed 665193323Sed error = kern_getrusage(td, uap->who, &s); 666206083Srdivacky if (error) 667193323Sed return (error); 668193323Sed if (uap->rusage != NULL) { 669206083Srdivacky TV_CP(s, s32, ru_utime); 670193323Sed TV_CP(s, s32, ru_stime); 671193323Sed CP(s, s32, ru_maxrss); 672193323Sed CP(s, s32, ru_ixrss); 673193323Sed CP(s, s32, ru_idrss); 674193323Sed CP(s, s32, ru_isrss); 675193323Sed CP(s, s32, ru_minflt); 676193323Sed CP(s, s32, ru_majflt); 677193323Sed CP(s, s32, ru_nswap); 678193323Sed CP(s, s32, ru_inblock); 679193323Sed CP(s, s32, ru_oublock); 680193323Sed CP(s, s32, ru_msgsnd); 681193323Sed CP(s, s32, ru_msgrcv); 682193323Sed CP(s, s32, ru_nsignals); 683193323Sed CP(s, s32, ru_nvcsw); 684193323Sed CP(s, s32, ru_nivcsw); 685193323Sed error = copyout(&s32, uap->rusage, sizeof(s32)); 686193323Sed } 687193323Sed return (error); 688193323Sed} 689193323Sed 690193323Sedstruct iovec32 { 691193323Sed u_int32_t iov_base; 692193323Sed int iov_len; 693193323Sed}; 694202375Srdivacky 695198090SrdivackyCTASSERT(sizeof(struct iovec32) == 8); 696193323Sed 697193323Sedstatic int 698193323Sedfreebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) 699206083Srdivacky{ 700193323Sed struct iovec32 iov32; 701193323Sed struct iovec *iov; 702193323Sed struct uio *uio; 703206083Srdivacky u_int iovlen; 704206083Srdivacky int error, i; 705193323Sed 706193323Sed *uiop = NULL; 707206083Srdivacky if (iovcnt > UIO_MAXIOV) 708193323Sed return (EINVAL); 709193323Sed iovlen = iovcnt * sizeof(struct iovec); 710193323Sed uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 711193323Sed iov = (struct iovec *)(uio + 1); 712193323Sed for (i = 0; i < iovcnt; i++) { 713193323Sed error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); 714193323Sed if (error) { 715193323Sed free(uio, M_IOV); 716193323Sed return (error); 717193323Sed } 718193323Sed iov[i].iov_base = PTRIN(iov32.iov_base); 719193323Sed iov[i].iov_len = iov32.iov_len; 720193323Sed } 721193323Sed uio->uio_iov = iov; 722193323Sed uio->uio_iovcnt = iovcnt; 723193323Sed uio->uio_segflg = UIO_USERSPACE; 724193323Sed uio->uio_offset = -1; 725193323Sed uio->uio_resid = 0; 726193323Sed for (i = 0; i < iovcnt; i++) { 727212904Sdim if (iov->iov_len > INT_MAX - uio->uio_resid) { 728193323Sed free(uio, M_IOV); 729193323Sed return (EINVAL); 730193323Sed } 731193323Sed uio->uio_resid += iov->iov_len; 732193323Sed iov++; 733193323Sed } 734193323Sed *uiop = uio; 735193323Sed return (0); 736193323Sed} 737193323Sed 738193323Sedint 739193323Sedfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 740193323Sed{ 741193323Sed struct uio *auio; 742193323Sed int error; 743193323Sed 744193323Sed error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 745193323Sed if (error) 746193323Sed return (error); 747193323Sed error = kern_readv(td, uap->fd, auio); 748193323Sed free(auio, M_IOV); 749193323Sed return (error); 750193323Sed} 751193323Sed 752193323Sedint 753193323Sedfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 754193323Sed{ 755193323Sed struct uio *auio; 756193323Sed int error; 757193323Sed 758193323Sed error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 759193323Sed if (error) 760193323Sed return (error); 761193323Sed error = kern_writev(td, uap->fd, auio); 762193323Sed free(auio, M_IOV); 763193323Sed return (error); 764193323Sed} 765193323Sed 766193323Sedint 767193323Sedfreebsd32_settimeofday(struct thread *td, 768193323Sed struct freebsd32_settimeofday_args *uap) 769193323Sed{ 770193323Sed struct timeval32 tv32; 771193323Sed struct timeval tv, *tvp; 772193323Sed struct timezone tz, *tzp; 773193323Sed int error; 774193323Sed 775193323Sed if (uap->tv) { 776193323Sed error = copyin(uap->tv, &tv32, sizeof(tv32)); 777193323Sed if (error) 778193323Sed return (error); 779193323Sed CP(tv32, tv, tv_sec); 780193323Sed CP(tv32, tv, tv_usec); 781193323Sed tvp = &tv; 782212904Sdim } else 783207618Srdivacky tvp = NULL; 784193323Sed if (uap->tzp) { 785193323Sed error = copyin(uap->tzp, &tz, sizeof(tz)); 786193323Sed if (error) 787193323Sed return (error); 788193323Sed tzp = &tz; 789193323Sed } else 790193323Sed tzp = NULL; 791206083Srdivacky return (kern_settimeofday(td, tvp, tzp)); 792193323Sed} 793193323Sed 794193323Sedint 795193323Sedfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 796204642Srdivacky{ 797193323Sed struct timeval32 s32[2]; 798193323Sed struct timeval s[2], *sp; 799193323Sed int error; 800193323Sed 801193323Sed if (uap->tptr != NULL) { 802193323Sed error = copyin(uap->tptr, s32, sizeof(s32)); 803193323Sed if (error) 804193323Sed return (error); 805206083Srdivacky CP(s32[0], s[0], tv_sec); 806193323Sed CP(s32[0], s[0], tv_usec); 807193323Sed CP(s32[1], s[1], tv_sec); 808193323Sed CP(s32[1], s[1], tv_usec); 809193323Sed sp = s; 810193323Sed } else 811198090Srdivacky sp = NULL; 812193323Sed return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 813193323Sed} 814193323Sed 815193323Sedint 816193323Sedfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 817193323Sed{ 818193323Sed struct timeval32 tv32; 819193323Sed struct timeval delta, olddelta, *deltap; 820193323Sed int error; 821193323Sed 822193323Sed if (uap->delta) { 823193323Sed error = copyin(uap->delta, &tv32, sizeof(tv32)); 824193323Sed if (error) 825193323Sed return (error); 826193323Sed CP(tv32, delta, tv_sec); 827193323Sed CP(tv32, delta, tv_usec); 828193323Sed deltap = δ 829193323Sed } else 830193323Sed deltap = NULL; 831193323Sed error = kern_adjtime(td, deltap, &olddelta); 832193323Sed if (uap->olddelta && error == 0) { 833193323Sed CP(olddelta, tv32, tv_sec); 834193323Sed CP(olddelta, tv32, tv_usec); 835193323Sed error = copyout(&tv32, uap->olddelta, sizeof(tv32)); 836193323Sed } 837193323Sed return (error); 838193323Sed} 839193323Sed 840193323Sed#ifdef COMPAT_FREEBSD4 841193323Sedint 842193323Sedfreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap) 843193323Sed{ 844193323Sed struct statfs32 s32; 845193323Sed struct statfs s; 846193323Sed int error; 847193323Sed 848193323Sed error = kern_statfs(td, uap->path, UIO_USERSPACE, &s); 849193323Sed if (error) 850193323Sed return (error); 851193323Sed copy_statfs(&s, &s32); 852193323Sed return (copyout(&s32, uap->buf, sizeof(s32))); 853193323Sed} 854193323Sed#endif 855193323Sed 856193323Sed#ifdef COMPAT_FREEBSD4 857193323Sedint 858193323Sedfreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap) 859193323Sed{ 860193323Sed struct statfs32 s32; 861193323Sed struct statfs s; 862193323Sed int error; 863193323Sed 864193323Sed error = kern_fstatfs(td, uap->fd, &s); 865193323Sed if (error) 866193323Sed return (error); 867208599Srdivacky copy_statfs(&s, &s32); 868193323Sed return (copyout(&s32, uap->buf, sizeof(s32))); 869193323Sed} 870204642Srdivacky#endif 871193323Sed 872193323Sed#ifdef COMPAT_FREEBSD4 873193323Sedint 874193323Sedfreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap) 875193323Sed{ 876193323Sed struct statfs32 s32; 877193323Sed struct statfs s; 878198090Srdivacky fhandle_t fh; 879193323Sed int error; 880193323Sed 881193323Sed if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 882193323Sed return (error); 883193323Sed error = kern_fhstatfs(td, fh, &s); 884193323Sed if (error) 885193323Sed return (error); 886193323Sed copy_statfs(&s, &s32); 887193323Sed return (copyout(&s32, uap->buf, sizeof(s32))); 888193323Sed} 889193323Sed#endif 890193323Sed 891193323Sedint 892193323Sedfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 893193323Sed{ 894193323Sed /* 895193323Sed * Vector through to semsys if it is loaded. 896193323Sed */ 897193323Sed return sysent[169].sy_call(td, uap); 898198090Srdivacky} 899193323Sed 900193323Sedint 901193323Sedfreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 902193323Sed{ 903193323Sed /* 904193323Sed * Vector through to msgsys if it is loaded. 905193323Sed */ 906193323Sed return sysent[170].sy_call(td, uap); 907193323Sed} 908193323Sed 909193323Sedint 910193323Sedfreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 911193323Sed{ 912193323Sed /* 913193323Sed * Vector through to shmsys if it is loaded. 914193323Sed */ 915202375Srdivacky return sysent[171].sy_call(td, uap); 916193323Sed} 917193323Sed 918193323Sedint 919193323Sedfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 920193323Sed{ 921193323Sed struct pread_args ap; 922193323Sed 923193323Sed ap.fd = uap->fd; 924193323Sed ap.buf = uap->buf; 925193323Sed ap.nbyte = uap->nbyte; 926202375Srdivacky ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 927193323Sed return (pread(td, &ap)); 928193323Sed} 929206083Srdivacky 930193323Sedint 931206083Srdivackyfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 932193323Sed{ 933206083Srdivacky struct pwrite_args ap; 934193323Sed 935193323Sed ap.fd = uap->fd; 936193323Sed ap.buf = uap->buf; 937193323Sed ap.nbyte = uap->nbyte; 938193323Sed ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 939193323Sed return (pwrite(td, &ap)); 940} 941 942int 943freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 944{ 945 int error; 946 struct lseek_args ap; 947 off_t pos; 948 949 ap.fd = uap->fd; 950 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 951 ap.whence = uap->whence; 952 error = lseek(td, &ap); 953 /* Expand the quad return into two parts for eax and edx */ 954 pos = *(off_t *)(td->td_retval); 955 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 956 td->td_retval[1] = pos >> 32; /* %edx */ 957 return error; 958} 959 960int 961freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 962{ 963 struct truncate_args ap; 964 965 ap.path = uap->path; 966 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 967 return (truncate(td, &ap)); 968} 969 970int 971freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 972{ 973 struct ftruncate_args ap; 974 975 ap.fd = uap->fd; 976 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 977 return (ftruncate(td, &ap)); 978} 979 980#ifdef COMPAT_FREEBSD4 981int 982freebsd4_freebsd32_sendfile(struct thread *td, 983 struct freebsd4_freebsd32_sendfile_args *uap) 984{ 985 struct freebsd4_sendfile_args ap; 986 987 ap.fd = uap->fd; 988 ap.s = uap->s; 989 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 990 ap.nbytes = uap->nbytes; /* XXX check */ 991 ap.hdtr = uap->hdtr; /* XXX check */ 992 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 993 ap.flags = uap->flags; 994 return (freebsd4_sendfile(td, &ap)); 995} 996#endif 997 998int 999freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 1000{ 1001 struct sendfile_args ap; 1002 1003 ap.fd = uap->fd; 1004 ap.s = uap->s; 1005 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1006 ap.nbytes = uap->nbytes; /* XXX check */ 1007 ap.hdtr = uap->hdtr; /* XXX check */ 1008 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1009 ap.flags = uap->flags; 1010 return (sendfile(td, &ap)); 1011} 1012 1013struct stat32 { 1014 dev_t st_dev; 1015 ino_t st_ino; 1016 mode_t st_mode; 1017 nlink_t st_nlink; 1018 uid_t st_uid; 1019 gid_t st_gid; 1020 dev_t st_rdev; 1021 struct timespec32 st_atimespec; 1022 struct timespec32 st_mtimespec; 1023 struct timespec32 st_ctimespec; 1024 off_t st_size; 1025 int64_t st_blocks; 1026 u_int32_t st_blksize; 1027 u_int32_t st_flags; 1028 u_int32_t st_gen; 1029 struct timespec32 st_birthtimespec; 1030 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1031 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1032}; 1033 1034 1035CTASSERT(sizeof(struct stat32) == 96); 1036 1037static void 1038copy_stat( struct stat *in, struct stat32 *out) 1039{ 1040 CP(*in, *out, st_dev); 1041 CP(*in, *out, st_ino); 1042 CP(*in, *out, st_mode); 1043 CP(*in, *out, st_nlink); 1044 CP(*in, *out, st_uid); 1045 CP(*in, *out, st_gid); 1046 CP(*in, *out, st_rdev); 1047 TS_CP(*in, *out, st_atimespec); 1048 TS_CP(*in, *out, st_mtimespec); 1049 TS_CP(*in, *out, st_ctimespec); 1050 CP(*in, *out, st_size); 1051 CP(*in, *out, st_blocks); 1052 CP(*in, *out, st_blksize); 1053 CP(*in, *out, st_flags); 1054 CP(*in, *out, st_gen); 1055} 1056 1057int 1058freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 1059{ 1060 struct stat sb; 1061 struct stat32 sb32; 1062 int error; 1063 1064 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); 1065 if (error) 1066 return (error); 1067 copy_stat(&sb, &sb32); 1068 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1069 return (error); 1070} 1071 1072int 1073freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 1074{ 1075 struct stat ub; 1076 struct stat32 ub32; 1077 int error; 1078 1079 error = kern_fstat(td, uap->fd, &ub); 1080 if (error) 1081 return (error); 1082 copy_stat(&ub, &ub32); 1083 error = copyout(&ub32, uap->ub, sizeof(ub32)); 1084 return (error); 1085} 1086 1087int 1088freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 1089{ 1090 struct stat sb; 1091 struct stat32 sb32; 1092 int error; 1093 1094 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); 1095 if (error) 1096 return (error); 1097 copy_stat(&sb, &sb32); 1098 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1099 return (error); 1100} 1101 1102/* 1103 * MPSAFE 1104 */ 1105int 1106freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 1107{ 1108 int error, name[CTL_MAXNAME]; 1109 size_t j, oldlen; 1110 1111 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1112 return (EINVAL); 1113 error = copyin(uap->name, name, uap->namelen * sizeof(int)); 1114 if (error) 1115 return (error); 1116 mtx_lock(&Giant); 1117 if (uap->oldlenp) 1118 oldlen = fuword32(uap->oldlenp); 1119 else 1120 oldlen = 0; 1121 error = userland_sysctl(td, name, uap->namelen, 1122 uap->old, &oldlen, 1, 1123 uap->new, uap->newlen, &j, SCTL_MASK32); 1124 if (error && error != ENOMEM) 1125 goto done2; 1126 if (uap->oldlenp) 1127 suword32(uap->oldlenp, j); 1128done2: 1129 mtx_unlock(&Giant); 1130 return (error); 1131} 1132 1133struct sigaction32 { 1134 u_int32_t sa_u; 1135 int sa_flags; 1136 sigset_t sa_mask; 1137}; 1138 1139CTASSERT(sizeof(struct sigaction32) == 24); 1140 1141int 1142freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 1143{ 1144 struct sigaction32 s32; 1145 struct sigaction sa, osa, *sap; 1146 int error; 1147 1148 if (uap->act) { 1149 error = copyin(uap->act, &s32, sizeof(s32)); 1150 if (error) 1151 return (error); 1152 sa.sa_handler = PTRIN(s32.sa_u); 1153 CP(s32, sa, sa_flags); 1154 CP(s32, sa, sa_mask); 1155 sap = &sa; 1156 } else 1157 sap = NULL; 1158 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 1159 if (error == 0 && uap->oact != NULL) { 1160 s32.sa_u = PTROUT(osa.sa_handler); 1161 CP(osa, s32, sa_flags); 1162 CP(osa, s32, sa_mask); 1163 error = copyout(&s32, uap->oact, sizeof(s32)); 1164 } 1165 return (error); 1166} 1167 1168#ifdef COMPAT_FREEBSD4 1169int 1170freebsd4_freebsd32_sigaction(struct thread *td, 1171 struct freebsd4_freebsd32_sigaction_args *uap) 1172{ 1173 struct sigaction32 s32; 1174 struct sigaction sa, osa, *sap; 1175 int error; 1176 1177 if (uap->act) { 1178 error = copyin(uap->act, &s32, sizeof(s32)); 1179 if (error) 1180 return (error); 1181 sa.sa_handler = PTRIN(s32.sa_u); 1182 CP(s32, sa, sa_flags); 1183 CP(s32, sa, sa_mask); 1184 sap = &sa; 1185 } else 1186 sap = NULL; 1187 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1188 if (error == 0 && uap->oact != NULL) { 1189 s32.sa_u = PTROUT(osa.sa_handler); 1190 CP(osa, s32, sa_flags); 1191 CP(osa, s32, sa_mask); 1192 error = copyout(&s32, uap->oact, sizeof(s32)); 1193 } 1194 return (error); 1195} 1196#endif 1197 1198int 1199freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap) 1200{ 1201 struct timespec32 rmt32, rqt32; 1202 struct timespec rmt, rqt; 1203 int error; 1204 1205 error = copyin(uap->rqtp, &rqt32, sizeof(rqt)); 1206 if (error) 1207 return (error); 1208 1209 CP(rqt32, rqt, tv_sec); 1210 CP(rqt32, rqt, tv_nsec); 1211 1212 if (uap->rmtp && 1213 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 1214 return (EFAULT); 1215 error = kern_nanosleep(td, &rqt, &rmt); 1216 if (error && uap->rmtp) { 1217 int error2; 1218 1219 CP(rmt, rmt32, tv_sec); 1220 CP(rmt, rmt32, tv_nsec); 1221 1222 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt)); 1223 if (error2) 1224 error = error2; 1225 } 1226 return (error); 1227} 1228 1229#if 0 1230 1231int 1232freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 1233{ 1234 int error; 1235 struct yyy32 *p32, s32; 1236 struct yyy *p = NULL, s; 1237 1238 if (uap->zzz) { 1239 error = copyin(uap->zzz, &s32, sizeof(s32)); 1240 if (error) 1241 return (error); 1242 /* translate in */ 1243 p = &s; 1244 } 1245 error = kern_xxx(td, p); 1246 if (error) 1247 return (error); 1248 if (uap->zzz) { 1249 /* translate out */ 1250 error = copyout(&s32, p32, sizeof(s32)); 1251 } 1252 return (error); 1253} 1254 1255#endif 1256