freebsd32_misc.c revision 140481
154359Sroberto/*- 254359Sroberto * Copyright (c) 2002 Doug Rabson 354359Sroberto * All rights reserved. 454359Sroberto * 554359Sroberto * Redistribution and use in source and binary forms, with or without 654359Sroberto * modification, are permitted provided that the following conditions 754359Sroberto * are met: 854359Sroberto * 1. Redistributions of source code must retain the above copyright 954359Sroberto * notice, this list of conditions and the following disclaimer. 1054359Sroberto * 2. Redistributions in binary form must reproduce the above copyright 1154359Sroberto * notice, this list of conditions and the following disclaimer in the 12132451Sroberto * documentation and/or other materials provided with the distribution. 13132451Sroberto * 14290001Sglebius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1582498Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1654359Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1754359Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1854359Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1954359Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2054359Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2154359Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2254359Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2354359Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2454359Sroberto * SUCH DAMAGE. 2554359Sroberto */ 2654359Sroberto 2754359Sroberto#include <sys/cdefs.h> 2854359Sroberto__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 140481 2005-01-19 17:44:59Z ps $"); 2954359Sroberto 3054359Sroberto#include "opt_compat.h" 3182498Sroberto 32132451Sroberto#include <sys/param.h> 33132451Sroberto#include <sys/systm.h> 34132451Sroberto#include <sys/bus.h> 35132451Sroberto#include <sys/exec.h> 36132451Sroberto#include <sys/fcntl.h> 37132451Sroberto#include <sys/filedesc.h> 3882498Sroberto#include <sys/namei.h> 39132451Sroberto#include <sys/imgact.h> 40132451Sroberto#include <sys/kernel.h> 41132451Sroberto#include <sys/lock.h> 4282498Sroberto#include <sys/malloc.h> 43182007Sroberto#include <sys/file.h> /* Must come after sys/malloc.h */ 44182007Sroberto#include <sys/mman.h> 45182007Sroberto#include <sys/module.h> 46182007Sroberto#include <sys/mount.h> 47182007Sroberto#include <sys/mutex.h> 48182007Sroberto#include <sys/namei.h> 49182007Sroberto#include <sys/param.h> 50182007Sroberto#include <sys/proc.h> 51182007Sroberto#include <sys/reboot.h> 52182007Sroberto#include <sys/resource.h> 53182007Sroberto#include <sys/resourcevar.h> 5454359Sroberto#include <sys/selinfo.h> 55290001Sglebius#include <sys/pipe.h> /* Must come after sys/selinfo.h */ 56290001Sglebius#include <sys/signal.h> 57290001Sglebius#include <sys/signalvar.h> 58290001Sglebius#include <sys/socket.h> 59290001Sglebius#include <sys/socketvar.h> 60290001Sglebius#include <sys/stat.h> 61290001Sglebius#include <sys/syscallsubr.h> 62290001Sglebius#include <sys/sysctl.h> 63290001Sglebius#include <sys/sysent.h> 64290001Sglebius#include <sys/sysproto.h> 65290001Sglebius#include <sys/systm.h> 66290001Sglebius#include <sys/unistd.h> 67290001Sglebius#include <sys/vnode.h> 68290001Sglebius#include <sys/wait.h> 69290001Sglebius 70290001Sglebius#include <vm/vm.h> 71290001Sglebius#include <vm/vm_kern.h> 72290001Sglebius#include <vm/vm_param.h> 73290001Sglebius#include <vm/pmap.h> 74290001Sglebius#include <vm/vm_map.h> 75290001Sglebius#include <vm/vm_object.h> 76290001Sglebius#include <vm/vm_extern.h> 77290001Sglebius 78290001Sglebius#include <compat/freebsd32/freebsd32_util.h> 79290001Sglebius#include <compat/freebsd32/freebsd32.h> 80290001Sglebius#include <compat/freebsd32/freebsd32_proto.h> 81290001Sglebius 82290001SglebiusCTASSERT(sizeof(struct timeval32) == 8); 83290001SglebiusCTASSERT(sizeof(struct timespec32) == 8); 84290001SglebiusCTASSERT(sizeof(struct statfs32) == 256); 85290001SglebiusCTASSERT(sizeof(struct rusage32) == 72); 86290001Sglebius 87290001Sglebiusint 88290001Sglebiusfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap) 89290001Sglebius{ 90290001Sglebius int error, status; 91290001Sglebius struct rusage32 ru32; 92290001Sglebius struct rusage ru, *rup; 93290001Sglebius 94290001Sglebius if (uap->rusage != NULL) 95290001Sglebius rup = &ru; 96290001Sglebius else 97182007Sroberto rup = NULL; 98182007Sroberto error = kern_wait(td, uap->pid, &status, uap->options, rup); 99182007Sroberto if (error) 100182007Sroberto return (error); 101182007Sroberto if (uap->status != NULL) 102182007Sroberto error = copyout(&status, uap->status, sizeof(status)); 103182007Sroberto if (uap->rusage != NULL && error == 0) { 104182007Sroberto TV_CP(ru, ru32, ru_utime); 105182007Sroberto TV_CP(ru, ru32, ru_stime); 106182007Sroberto CP(ru, ru32, ru_maxrss); 107182007Sroberto CP(ru, ru32, ru_ixrss); 108182007Sroberto CP(ru, ru32, ru_idrss); 109182007Sroberto CP(ru, ru32, ru_isrss); 110182007Sroberto CP(ru, ru32, ru_minflt); 111182007Sroberto CP(ru, ru32, ru_majflt); 112182007Sroberto CP(ru, ru32, ru_nswap); 113182007Sroberto CP(ru, ru32, ru_inblock); 114182007Sroberto CP(ru, ru32, ru_oublock); 11554359Sroberto CP(ru, ru32, ru_msgsnd); 11682498Sroberto CP(ru, ru32, ru_msgrcv); 11782498Sroberto CP(ru, ru32, ru_nsignals); 11854359Sroberto CP(ru, ru32, ru_nvcsw); 11954359Sroberto CP(ru, ru32, ru_nivcsw); 12082498Sroberto error = copyout(&ru32, uap->rusage, sizeof(ru32)); 12182498Sroberto } 12254359Sroberto return (error); 12354359Sroberto} 12454359Sroberto 12582498Sroberto#ifdef COMPAT_FREEBSD4 12682498Srobertostatic void 12782498Srobertocopy_statfs(struct statfs *in, struct statfs32 *out) 12882498Sroberto{ 12954359Sroberto CP(*in, *out, f_bsize); 13054359Sroberto CP(*in, *out, f_iosize); 13154359Sroberto CP(*in, *out, f_blocks); 13254359Sroberto CP(*in, *out, f_bfree); 13354359Sroberto CP(*in, *out, f_bavail); 13454359Sroberto CP(*in, *out, f_files); 13582498Sroberto CP(*in, *out, f_ffree); 13654359Sroberto CP(*in, *out, f_fsid); 13754359Sroberto CP(*in, *out, f_owner); 13854359Sroberto CP(*in, *out, f_type); 13954359Sroberto CP(*in, *out, f_flags); 14054359Sroberto CP(*in, *out, f_flags); 14154359Sroberto CP(*in, *out, f_syncwrites); 14254359Sroberto CP(*in, *out, f_asyncwrites); 14354359Sroberto bcopy(in->f_fstypename, 14454359Sroberto out->f_fstypename, MFSNAMELEN); 14556746Sroberto bcopy(in->f_mntonname, 14656746Sroberto out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 14756746Sroberto CP(*in, *out, f_syncreads); 14882498Sroberto CP(*in, *out, f_asyncreads); 14956746Sroberto bcopy(in->f_mntfromname, 15082498Sroberto out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 15182498Sroberto} 15256746Sroberto#endif 15356746Sroberto 15454359Sroberto#ifdef COMPAT_FREEBSD4 15554359Srobertoint 15654359Srobertofreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap) 15754359Sroberto{ 158182007Sroberto int error; 15954359Sroberto caddr_t sg; 16082498Sroberto struct statfs32 *sp32, stat32; 16182498Sroberto struct statfs *sp = NULL, stat; 16282498Sroberto int maxcount, count, i; 16382498Sroberto 164290001Sglebius sp32 = uap->buf; 16582498Sroberto maxcount = uap->bufsize / sizeof(struct statfs32); 16682498Sroberto 16754359Sroberto if (sp32) { 168290001Sglebius sg = stackgap_init(); 16954359Sroberto sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount); 17054359Sroberto uap->buf = (struct statfs32 *)sp; 17156746Sroberto } 17256746Sroberto error = getfsstat(td, (struct getfsstat_args *) uap); 17356746Sroberto if (sp32 && !error) { 17456746Sroberto count = td->td_retval[0]; 17556746Sroberto for (i = 0; i < count; i++) { 176182007Sroberto error = copyin(&sp[i], &stat, sizeof(stat)); 17756746Sroberto if (error) 17856746Sroberto return (error); 17954359Sroberto copy_statfs(&stat, &stat32); 18054359Sroberto error = copyout(&stat32, &sp32[i], sizeof(stat32)); 181182007Sroberto if (error) 18254359Sroberto return (error); 18354359Sroberto } 184290001Sglebius } 185290001Sglebius return (error); 186290001Sglebius} 187290001Sglebius#endif 188290001Sglebius 189290001Sglebiusstruct sigaltstack32 { 190290001Sglebius u_int32_t ss_sp; 191290001Sglebius u_int32_t ss_size; 192290001Sglebius int ss_flags; 193290001Sglebius}; 194290001Sglebius 19556746SrobertoCTASSERT(sizeof(struct sigaltstack32) == 12); 19654359Sroberto 19754359Srobertoint 198132451Srobertofreebsd32_sigaltstack(struct thread *td, 199132451Sroberto struct freebsd32_sigaltstack_args *uap) 200132451Sroberto{ 20154359Sroberto struct sigaltstack32 s32; 20254359Sroberto struct sigaltstack ss, oss, *ssp; 20382498Sroberto int error; 20454359Sroberto 20554359Sroberto if (uap->ss != NULL) { 20654359Sroberto error = copyin(uap->ss, &s32, sizeof(s32)); 20754359Sroberto if (error) 20854359Sroberto return (error); 20954359Sroberto PTRIN_CP(s32, ss, ss_sp); 21082498Sroberto CP(s32, ss, ss_size); 21154359Sroberto CP(s32, ss, ss_flags); 21254359Sroberto ssp = &ss; 21354359Sroberto } else 21454359Sroberto ssp = NULL; 21554359Sroberto error = kern_sigaltstack(td, ssp, &oss); 216132451Sroberto if (error == 0 && uap->oss != NULL) { 217132451Sroberto PTROUT_CP(oss, s32, ss_sp); 218132451Sroberto CP(oss, s32, ss_size); 219132451Sroberto CP(oss, s32, ss_flags); 220132451Sroberto error = copyout(&s32, uap->oss, sizeof(s32)); 221132451Sroberto } 222132451Sroberto return (error); 223132451Sroberto} 22482498Sroberto 22582498Srobertoint 22682498Srobertofreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) 22782498Sroberto{ 22882498Sroberto int error; 22982498Sroberto caddr_t sg; 23082498Sroberto struct execve_args ap; 23182498Sroberto u_int32_t *p32, arg; 23282498Sroberto char **p, *p64; 23382498Sroberto int count; 23482498Sroberto 23582498Sroberto sg = stackgap_init(); 23682498Sroberto ap.fname = uap->fname; 23782498Sroberto 23882498Sroberto if (uap->argv) { 23982498Sroberto count = 0; 24082498Sroberto p32 = uap->argv; 24182498Sroberto do { 24282498Sroberto error = copyin(p32++, &arg, sizeof(arg)); 24382498Sroberto if (error) 24482498Sroberto return error; 24582498Sroberto count++; 24682498Sroberto } while (arg != 0); 24782498Sroberto p = stackgap_alloc(&sg, count * sizeof(char *)); 24882498Sroberto ap.argv = p; 24982498Sroberto p32 = uap->argv; 25082498Sroberto do { 25182498Sroberto error = copyin(p32++, &arg, sizeof(arg)); 25282498Sroberto if (error) 25382498Sroberto return error; 25482498Sroberto p64 = PTRIN(arg); 25582498Sroberto error = copyout(&p64, p++, sizeof(p64)); 25682498Sroberto if (error) 25782498Sroberto return error; 25882498Sroberto } while (arg != 0); 25982498Sroberto } 26082498Sroberto if (uap->envv) { 26182498Sroberto count = 0; 26282498Sroberto p32 = uap->envv; 26382498Sroberto do { 26482498Sroberto error = copyin(p32++, &arg, sizeof(arg)); 26582498Sroberto if (error) 26682498Sroberto return error; 26754359Sroberto count++; 26854359Sroberto } while (arg != 0); 26982498Sroberto p = stackgap_alloc(&sg, count * sizeof(char *)); 27082498Sroberto ap.envv = p; 27182498Sroberto p32 = uap->envv; 27254359Sroberto do { 27354359Sroberto error = copyin(p32++, &arg, sizeof(arg)); 274132451Sroberto if (error) 27554359Sroberto return error; 27654359Sroberto p64 = PTRIN(arg); 27754359Sroberto error = copyout(&p64, p++, sizeof(p64)); 27882498Sroberto if (error) 27954359Sroberto return error; 280132451Sroberto } while (arg != 0); 28154359Sroberto } 28254359Sroberto 28354359Sroberto return execve(td, &ap); 28482498Sroberto} 28554359Sroberto 28654359Sroberto#ifdef __ia64__ 28782498Srobertostatic int 28882498Srobertofreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 28982498Sroberto int prot, int fd, off_t pos) 29082498Sroberto{ 29182498Sroberto vm_map_t map; 29282498Sroberto vm_map_entry_t entry; 29382498Sroberto int rv; 29482498Sroberto 295132451Sroberto map = &td->td_proc->p_vmspace->vm_map; 296132451Sroberto if (fd != -1) 29782498Sroberto prot |= VM_PROT_WRITE; 29854359Sroberto 29954359Sroberto if (vm_map_lookup_entry(map, start, &entry)) { 30054359Sroberto if ((entry->protection & prot) != prot) { 30182498Sroberto rv = vm_map_protect(map, 30254359Sroberto trunc_page(start), 30382498Sroberto round_page(end), 30454359Sroberto entry->protection | prot, 30582498Sroberto FALSE); 30682498Sroberto if (rv != KERN_SUCCESS) 30782498Sroberto return (EINVAL); 30882498Sroberto } 30982498Sroberto } else { 310182007Sroberto vm_offset_t addr = trunc_page(start); 311132451Sroberto rv = vm_map_find(map, 0, 0, 31282498Sroberto &addr, PAGE_SIZE, FALSE, prot, 313132451Sroberto VM_PROT_ALL, 0); 314132451Sroberto if (rv != KERN_SUCCESS) 315132451Sroberto return (EINVAL); 316132451Sroberto } 317132451Sroberto 318182007Sroberto if (fd != -1) { 319182007Sroberto struct pread_args r; 320290001Sglebius r.fd = fd; 321132451Sroberto r.buf = (void *) start; 322132451Sroberto r.nbyte = end - start; 323290001Sglebius r.offset = pos; 324290001Sglebius return (pread(td, &r)); 32582498Sroberto } else { 32682498Sroberto while (start < end) { 327290001Sglebius subyte((void *) start, 0); 32882498Sroberto start++; 32982498Sroberto } 330132451Sroberto return (0); 331290001Sglebius } 33254359Sroberto} 333132451Sroberto#endif 334132451Sroberto 33554359Srobertoint 336132451Srobertofreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 337132451Sroberto{ 338132451Sroberto struct mmap_args ap; 339132451Sroberto vm_offset_t addr = (vm_offset_t) uap->addr; 340290001Sglebius vm_size_t len = uap->len; 341132451Sroberto int prot = uap->prot; 34282498Sroberto int flags = uap->flags; 34354359Sroberto int fd = uap->fd; 34454359Sroberto off_t pos = (uap->poslo 345132451Sroberto | ((off_t)uap->poshi << 32)); 346132451Sroberto#ifdef __ia64__ 347132451Sroberto vm_size_t pageoff; 348182007Sroberto int error; 349132451Sroberto 350132451Sroberto /* 351132451Sroberto * Attempt to handle page size hassles. 35282498Sroberto */ 353132451Sroberto pageoff = (pos & PAGE_MASK); 354290001Sglebius if (flags & MAP_FIXED) { 355290001Sglebius vm_offset_t start, end; 35654359Sroberto start = addr; 35754359Sroberto end = addr + len; 35854359Sroberto 35954359Sroberto if (start != trunc_page(start)) { 36054359Sroberto error = freebsd32_mmap_partial(td, start, 361290001Sglebius round_page(start), prot, 362290001Sglebius fd, pos); 363290001Sglebius if (fd != -1) 364290001Sglebius pos += round_page(start) - start; 365290001Sglebius start = round_page(start); 366290001Sglebius } 367290001Sglebius if (end != round_page(end)) { 368290001Sglebius vm_offset_t t = trunc_page(end); 369290001Sglebius error = freebsd32_mmap_partial(td, t, end, 37054359Sroberto prot, fd, 371290001Sglebius pos + t - start); 372290001Sglebius end = trunc_page(end); 373290001Sglebius } 374290001Sglebius if (end > start && fd != -1 && (pos & PAGE_MASK)) { 375290001Sglebius /* 376290001Sglebius * We can't map this region at all. The specified 377290001Sglebius * address doesn't have the same alignment as the file 378290001Sglebius * position. Fake the mapping by simply reading the 379290001Sglebius * entire region into memory. First we need to make 380290001Sglebius * sure the region exists. 381290001Sglebius */ 382290001Sglebius vm_map_t map; 383290001Sglebius struct pread_args r; 384290001Sglebius int rv; 385290001Sglebius 386290001Sglebius prot |= VM_PROT_WRITE; 387290001Sglebius map = &td->td_proc->p_vmspace->vm_map; 388290001Sglebius rv = vm_map_remove(map, start, end); 389290001Sglebius if (rv != KERN_SUCCESS) 390290001Sglebius return (EINVAL); 391132451Sroberto rv = vm_map_find(map, 0, 0, 392290001Sglebius &start, end - start, FALSE, 393290001Sglebius prot, VM_PROT_ALL, 0); 394290001Sglebius if (rv != KERN_SUCCESS) 395290001Sglebius return (EINVAL); 396290001Sglebius r.fd = fd; 397290001Sglebius r.buf = (void *) start; 398290001Sglebius r.nbyte = end - start; 399290001Sglebius r.offset = pos; 400290001Sglebius error = pread(td, &r); 401290001Sglebius if (error) 402290001Sglebius return (error); 403290001Sglebius 404290001Sglebius td->td_retval[0] = addr; 405290001Sglebius return (0); 406290001Sglebius } 407290001Sglebius if (end == start) { 408290001Sglebius /* 409290001Sglebius * After dealing with the ragged ends, there 410290001Sglebius * might be none left. 411290001Sglebius */ 412290001Sglebius td->td_retval[0] = addr; 413290001Sglebius return (0); 414290001Sglebius } 41554359Sroberto addr = start; 41654359Sroberto len = end - start; 41754359Sroberto } 41854359Sroberto#endif 41954359Sroberto 42054359Sroberto ap.addr = (void *) addr; 42154359Sroberto ap.len = len; 422182007Sroberto ap.prot = prot; 42354359Sroberto ap.flags = flags; 42454359Sroberto ap.fd = fd; 42554359Sroberto ap.pos = pos; 42654359Sroberto 42754359Sroberto return (mmap(td, &ap)); 42882498Sroberto} 42954359Sroberto 43054359Srobertostruct itimerval32 { 43156746Sroberto struct timeval32 it_interval; 43254359Sroberto struct timeval32 it_value; 43354359Sroberto}; 434290001Sglebius 43554359SrobertoCTASSERT(sizeof(struct itimerval32) == 16); 43656746Sroberto 43754359Srobertoint 43882498Srobertofreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 439290001Sglebius{ 440290001Sglebius int error; 441290001Sglebius caddr_t sg; 442290001Sglebius struct itimerval32 *p32, *op32, s32; 443290001Sglebius struct itimerval *p = NULL, *op = NULL, s; 444290001Sglebius 445290001Sglebius p32 = uap->itv; 446290001Sglebius if (p32) { 447290001Sglebius sg = stackgap_init(); 448290001Sglebius p = stackgap_alloc(&sg, sizeof(struct itimerval)); 449290001Sglebius uap->itv = (struct itimerval32 *)p; 450290001Sglebius error = copyin(p32, &s32, sizeof(s32)); 451290001Sglebius if (error) 452290001Sglebius return (error); 453290001Sglebius TV_CP(s32, s, it_interval); 454290001Sglebius TV_CP(s32, s, it_value); 455290001Sglebius error = copyout(&s, p, sizeof(s)); 456290001Sglebius if (error) 457290001Sglebius return (error); 458290001Sglebius } 459290001Sglebius op32 = uap->oitv; 460290001Sglebius if (op32) { 461290001Sglebius sg = stackgap_init(); 462290001Sglebius op = stackgap_alloc(&sg, sizeof(struct itimerval)); 463290001Sglebius uap->oitv = (struct itimerval32 *)op; 464290001Sglebius } 465290001Sglebius error = setitimer(td, (struct setitimer_args *) uap); 466290001Sglebius if (error) 467290001Sglebius return (error); 468290001Sglebius if (op32) { 469290001Sglebius error = copyin(op, &s, sizeof(s)); 470290001Sglebius if (error) 471290001Sglebius return (error); 472290001Sglebius TV_CP(s, s32, it_interval); 473290001Sglebius TV_CP(s, s32, it_value); 474290001Sglebius error = copyout(&s32, op32, sizeof(s32)); 475290001Sglebius } 476290001Sglebius return (error); 477290001Sglebius} 478290001Sglebius 479290001Sglebiusint 48054359Srobertofreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap) 48154359Sroberto{ 48254359Sroberto int error; 483132451Sroberto caddr_t sg; 484132451Sroberto struct itimerval32 *p32, s32; 485132451Sroberto struct itimerval *p = NULL, s; 486132451Sroberto 487132451Sroberto p32 = uap->itv; 488132451Sroberto if (p32) { 489132451Sroberto sg = stackgap_init(); 490132451Sroberto p = stackgap_alloc(&sg, sizeof(struct itimerval)); 491132451Sroberto uap->itv = (struct itimerval32 *)p; 492132451Sroberto } 493132451Sroberto error = getitimer(td, (struct getitimer_args *) uap); 494132451Sroberto if (error) 495132451Sroberto return (error); 496132451Sroberto if (p32) { 497132451Sroberto error = copyin(p, &s, sizeof(s)); 498132451Sroberto if (error) 499132451Sroberto return (error); 500132451Sroberto TV_CP(s, s32, it_interval); 501132451Sroberto TV_CP(s, s32, it_value); 502132451Sroberto error = copyout(&s32, p32, sizeof(s32)); 503132451Sroberto } 504132451Sroberto return (error); 505132451Sroberto} 506132451Sroberto 507132451Srobertoint 508132451Srobertofreebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 509132451Sroberto{ 510132451Sroberto int error; 511132451Sroberto caddr_t sg; 512132451Sroberto struct timeval32 *p32, s32; 513132451Sroberto struct timeval *p = NULL, s; 514290001Sglebius 515132451Sroberto p32 = uap->tv; 516182007Sroberto if (p32) { 517182007Sroberto sg = stackgap_init(); 518132451Sroberto p = stackgap_alloc(&sg, sizeof(struct timeval)); 519132451Sroberto uap->tv = (struct timeval32 *)p; 520132451Sroberto error = copyin(p32, &s32, sizeof(s32)); 521132451Sroberto if (error) 522132451Sroberto return (error); 523132451Sroberto CP(s32, s, tv_sec); 524132451Sroberto CP(s32, s, tv_usec); 525132451Sroberto error = copyout(&s, p, sizeof(s)); 526182007Sroberto if (error) 527182007Sroberto return (error); 528132451Sroberto } 529132451Sroberto /* 530132451Sroberto * XXX big-endian needs to convert the fd_sets too. 531132451Sroberto */ 532132451Sroberto return (select(td, (struct select_args *) uap)); 533132451Sroberto} 534290001Sglebius 535132451Srobertostruct kevent32 { 536132451Sroberto u_int32_t ident; /* identifier for this event */ 537132451Sroberto short filter; /* filter for event */ 538132451Sroberto u_short flags; 539132451Sroberto u_int fflags; 540132451Sroberto int32_t data; 541132451Sroberto u_int32_t udata; /* opaque user data identifier */ 542132451Sroberto}; 543132451Sroberto 544132451SrobertoCTASSERT(sizeof(struct kevent32) == 20); 545132451Sroberto 546132451Srobertoint 54754359Srobertofreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 548132451Sroberto{ 549132451Sroberto int error; 550132451Sroberto caddr_t sg; 551132451Sroberto struct timespec32 ts32; 552132451Sroberto struct timespec ts; 553132451Sroberto struct kevent32 ks32; 55454359Sroberto struct kevent *ks; 55554359Sroberto struct kevent_args a; 556182007Sroberto int i; 557182007Sroberto 55854359Sroberto sg = stackgap_init(); 55954359Sroberto 56054359Sroberto a.fd = uap->fd; 56154359Sroberto a.changelist = uap->changelist; 56254359Sroberto a.nchanges = uap->nchanges; 56354359Sroberto a.eventlist = uap->eventlist; 56454359Sroberto a.nevents = uap->nevents; 56554359Sroberto a.timeout = NULL; 56654359Sroberto 56782498Sroberto if (uap->timeout) { 56854359Sroberto a.timeout = stackgap_alloc(&sg, sizeof(struct timespec)); 56954359Sroberto error = copyin(uap->timeout, &ts32, sizeof(ts32)); 57054359Sroberto if (error) 57154359Sroberto return (error); 57254359Sroberto CP(ts32, ts, tv_sec); 57354359Sroberto CP(ts32, ts, tv_nsec); 57454359Sroberto error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts)); 57554359Sroberto if (error) 57654359Sroberto return (error); 57754359Sroberto } 57854359Sroberto if (uap->changelist) { 57954359Sroberto a.changelist = (struct kevent *)stackgap_alloc(&sg, 58054359Sroberto uap->nchanges * sizeof(struct kevent)); 58154359Sroberto for (i = 0; i < uap->nchanges; i++) { 58254359Sroberto error = copyin(&uap->changelist[i], &ks32, 58356746Sroberto sizeof(ks32)); 58454359Sroberto if (error) 58554359Sroberto return (error); 58654359Sroberto ks = (struct kevent *)(uintptr_t)&a.changelist[i]; 58782498Sroberto CP(ks32, *ks, ident); 58854359Sroberto CP(ks32, *ks, filter); 58954359Sroberto CP(ks32, *ks, flags); 59054359Sroberto CP(ks32, *ks, fflags); 59154359Sroberto CP(ks32, *ks, data); 59254359Sroberto PTRIN_CP(ks32, *ks, udata); 59354359Sroberto } 594182007Sroberto } 59554359Sroberto if (uap->eventlist) { 59654359Sroberto a.eventlist = stackgap_alloc(&sg, 597290001Sglebius uap->nevents * sizeof(struct kevent)); 598290001Sglebius } 599290001Sglebius error = kevent(td, &a); 60054359Sroberto if (uap->eventlist && error > 0) { 601290001Sglebius for (i = 0; i < error; i++) { 60254359Sroberto ks = &a.eventlist[i]; 603132451Sroberto CP(*ks, ks32, ident); 604132451Sroberto CP(*ks, ks32, filter); 605290001Sglebius CP(*ks, ks32, flags); 606290001Sglebius CP(*ks, ks32, fflags); 607132451Sroberto CP(*ks, ks32, data); 608132451Sroberto PTROUT_CP(*ks, ks32, udata); 60954359Sroberto error = copyout(&ks32, &uap->eventlist[i], 61054359Sroberto sizeof(ks32)); 61182498Sroberto if (error) 61282498Sroberto return (error); 61382498Sroberto } 614132451Sroberto } 615132451Sroberto return error; 61682498Sroberto} 61754359Sroberto 61882498Srobertoint 619132451Srobertofreebsd32_gettimeofday(struct thread *td, 620132451Sroberto struct freebsd32_gettimeofday_args *uap) 621290001Sglebius{ 622290001Sglebius struct timeval atv; 62382498Sroberto struct timeval32 atv32; 62482498Sroberto struct timezone rtz; 62582498Sroberto int error = 0; 626132451Sroberto 627132451Sroberto if (uap->tp) { 62854359Sroberto microtime(&atv); 629290001Sglebius CP(atv, atv32, tv_sec); 63082498Sroberto CP(atv, atv32, tv_usec); 63182498Sroberto error = copyout(&atv32, uap->tp, sizeof (atv32)); 63282498Sroberto } 63382498Sroberto if (error == 0 && uap->tzp != NULL) { 63482498Sroberto rtz.tz_minuteswest = tz_minuteswest; 63582498Sroberto rtz.tz_dsttime = tz_dsttime; 636290001Sglebius error = copyout(&rtz, uap->tzp, sizeof (rtz)); 637182007Sroberto } 638290001Sglebius return (error); 63954359Sroberto} 640182007Sroberto 641182007Srobertoint 642182007Srobertofreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 643182007Sroberto{ 644182007Sroberto struct rusage32 s32; 645290001Sglebius struct rusage s; 646290001Sglebius int error; 647182007Sroberto 648182007Sroberto error = kern_getrusage(td, uap->who, &s); 649182007Sroberto if (error) 650182007Sroberto return (error); 651182007Sroberto if (uap->rusage != NULL) { 652182007Sroberto TV_CP(s, s32, ru_utime); 653182007Sroberto TV_CP(s, s32, ru_stime); 654182007Sroberto CP(s, s32, ru_maxrss); 655182007Sroberto CP(s, s32, ru_ixrss); 656182007Sroberto CP(s, s32, ru_idrss); 657290001Sglebius CP(s, s32, ru_isrss); 658290001Sglebius CP(s, s32, ru_minflt); 659290001Sglebius CP(s, s32, ru_majflt); 660290001Sglebius CP(s, s32, ru_nswap); 661290001Sglebius CP(s, s32, ru_inblock); 662290001Sglebius CP(s, s32, ru_oublock); 663290001Sglebius CP(s, s32, ru_msgsnd); 664290001Sglebius CP(s, s32, ru_msgrcv); 665290001Sglebius CP(s, s32, ru_nsignals); 666290001Sglebius CP(s, s32, ru_nvcsw); 667290001Sglebius CP(s, s32, ru_nivcsw); 668290001Sglebius error = copyout(&s32, uap->rusage, sizeof(s32)); 669290001Sglebius } 670182007Sroberto return (error); 671290001Sglebius} 672182007Sroberto 673290001Sglebiusstruct iovec32 { 674290001Sglebius u_int32_t iov_base; 675290001Sglebius int iov_len; 67654359Sroberto}; 67754359Sroberto#define STACKGAPLEN 400 678182007Sroberto 679290001SglebiusCTASSERT(sizeof(struct iovec32) == 8); 680290001Sglebius 681290001Sglebiusint 682182007Srobertofreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 683290001Sglebius{ 684132451Sroberto int error, osize, nsize, i; 685290001Sglebius caddr_t sg; 686290001Sglebius struct readv_args /* { 687290001Sglebius syscallarg(int) fd; 688290001Sglebius syscallarg(struct iovec *) iovp; 689290001Sglebius syscallarg(u_int) iovcnt; 690132451Sroberto } */ a; 691132451Sroberto struct iovec32 *oio; 692290001Sglebius struct iovec *nio; 693290001Sglebius 694290001Sglebius sg = stackgap_init(); 695290001Sglebius 696290001Sglebius if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 697290001Sglebius return (EINVAL); 698182007Sroberto 699182007Sroberto osize = uap->iovcnt * sizeof (struct iovec32); 700290001Sglebius nsize = uap->iovcnt * sizeof (struct iovec); 701290001Sglebius 702290001Sglebius oio = malloc(osize, M_TEMP, M_WAITOK); 703290001Sglebius nio = malloc(nsize, M_TEMP, M_WAITOK); 704290001Sglebius 705290001Sglebius error = 0; 706290001Sglebius if ((error = copyin(uap->iovp, oio, osize))) 707182007Sroberto goto punt; 708182007Sroberto for (i = 0; i < uap->iovcnt; i++) { 709182007Sroberto nio[i].iov_base = PTRIN(oio[i].iov_base); 710290001Sglebius nio[i].iov_len = oio[i].iov_len; 711182007Sroberto } 712290001Sglebius 713290001Sglebius a.fd = uap->fd; 714290001Sglebius a.iovp = stackgap_alloc(&sg, nsize); 715182007Sroberto a.iovcnt = uap->iovcnt; 716182007Sroberto 717182007Sroberto if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 718182007Sroberto goto punt; 719182007Sroberto error = readv(td, &a); 720182007Sroberto 721182007Srobertopunt: 722182007Sroberto free(oio, M_TEMP); 723182007Sroberto free(nio, M_TEMP); 724182007Sroberto return (error); 725182007Sroberto} 726132451Sroberto 727132451Srobertoint 728132451Srobertofreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 729132451Sroberto{ 730290001Sglebius int error, i, nsize, osize; 731132451Sroberto caddr_t sg; 732132451Sroberto struct writev_args /* { 733132451Sroberto syscallarg(int) fd; 734290001Sglebius syscallarg(struct iovec *) iovp; 735290001Sglebius syscallarg(u_int) iovcnt; 736290001Sglebius } */ a; 737132451Sroberto struct iovec32 *oio; 738132451Sroberto struct iovec *nio; 739132451Sroberto 740290001Sglebius sg = stackgap_init(); 741132451Sroberto 742132451Sroberto if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 743132451Sroberto return (EINVAL); 744132451Sroberto 745132451Sroberto osize = uap->iovcnt * sizeof (struct iovec32); 746132451Sroberto nsize = uap->iovcnt * sizeof (struct iovec); 747132451Sroberto 748132451Sroberto oio = malloc(osize, M_TEMP, M_WAITOK); 749132451Sroberto nio = malloc(nsize, M_TEMP, M_WAITOK); 750132451Sroberto 751132451Sroberto error = 0; 752132451Sroberto if ((error = copyin(uap->iovp, oio, osize))) 753132451Sroberto goto punt; 754132451Sroberto for (i = 0; i < uap->iovcnt; i++) { 755132451Sroberto nio[i].iov_base = PTRIN(oio[i].iov_base); 756132451Sroberto nio[i].iov_len = oio[i].iov_len; 757132451Sroberto } 758290001Sglebius 759132451Sroberto a.fd = uap->fd; 760132451Sroberto a.iovp = stackgap_alloc(&sg, nsize); 761290001Sglebius a.iovcnt = uap->iovcnt; 762290001Sglebius 763132451Sroberto if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 764132451Sroberto goto punt; 765132451Sroberto error = writev(td, &a); 766132451Sroberto 767132451Srobertopunt: 768132451Sroberto free(oio, M_TEMP); 769132451Sroberto free(nio, M_TEMP); 770132451Sroberto return (error); 771132451Sroberto} 772132451Sroberto 773132451Srobertoint 774132451Srobertofreebsd32_settimeofday(struct thread *td, 775132451Sroberto struct freebsd32_settimeofday_args *uap) 776132451Sroberto{ 777132451Sroberto int error; 778132451Sroberto caddr_t sg; 779132451Sroberto struct timeval32 *p32, s32; 780132451Sroberto struct timeval *p = NULL, s; 781132451Sroberto 782132451Sroberto p32 = uap->tv; 783290001Sglebius if (p32) { 784132451Sroberto sg = stackgap_init(); 785290001Sglebius p = stackgap_alloc(&sg, sizeof(struct timeval)); 786290001Sglebius uap->tv = (struct timeval32 *)p; 787132451Sroberto error = copyin(p32, &s32, sizeof(s32)); 788290001Sglebius if (error) 789290001Sglebius return (error); 790182007Sroberto CP(s32, s, tv_sec); 791290001Sglebius CP(s32, s, tv_usec); 792182007Sroberto error = copyout(&s, p, sizeof(s)); 793290001Sglebius if (error) 794290001Sglebius return (error); 795182007Sroberto } 796290001Sglebius return (settimeofday(td, (struct settimeofday_args *) uap)); 797290001Sglebius} 798182007Sroberto 799290001Sglebiusint 800290001Sglebiusfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 801132451Sroberto{ 802132451Sroberto int error; 803132451Sroberto caddr_t sg; 804132451Sroberto struct timeval32 *p32, s32[2]; 805132451Sroberto struct timeval *p = NULL, s[2]; 806132451Sroberto 807132451Sroberto p32 = uap->tptr; 808132451Sroberto if (p32) { 809132451Sroberto sg = stackgap_init(); 810132451Sroberto p = stackgap_alloc(&sg, 2*sizeof(struct timeval)); 811132451Sroberto uap->tptr = (struct timeval32 *)p; 812132451Sroberto error = copyin(p32, s32, sizeof(s32)); 813132451Sroberto if (error) 814132451Sroberto return (error); 815132451Sroberto CP(s32[0], s[0], tv_sec); 816132451Sroberto CP(s32[0], s[0], tv_usec); 817290001Sglebius CP(s32[1], s[1], tv_sec); 818132451Sroberto CP(s32[1], s[1], tv_usec); 819132451Sroberto error = copyout(s, p, sizeof(s)); 820132451Sroberto if (error) 821290001Sglebius return (error); 822290001Sglebius } 823132451Sroberto return (utimes(td, (struct utimes_args *) uap)); 824132451Sroberto} 825290001Sglebius 826290001Sglebiusint 827132451Srobertofreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 828132451Sroberto{ 829132451Sroberto int error; 830132451Sroberto caddr_t sg; 831132451Sroberto struct timeval32 *p32, *op32, s32; 832132451Sroberto struct timeval *p = NULL, *op = NULL, s; 833132451Sroberto 834132451Sroberto p32 = uap->delta; 835132451Sroberto if (p32) { 836132451Sroberto sg = stackgap_init(); 837132451Sroberto p = stackgap_alloc(&sg, sizeof(struct timeval)); 838132451Sroberto uap->delta = (struct timeval32 *)p; 839132451Sroberto error = copyin(p32, &s32, sizeof(s32)); 840132451Sroberto if (error) 841132451Sroberto return (error); 842132451Sroberto CP(s32, s, tv_sec); 843132451Sroberto CP(s32, s, tv_usec); 844132451Sroberto error = copyout(&s, p, sizeof(s)); 845132451Sroberto if (error) 846132451Sroberto return (error); 847132451Sroberto } 848132451Sroberto op32 = uap->olddelta; 849132451Sroberto if (op32) { 850182007Sroberto sg = stackgap_init(); 851290001Sglebius op = stackgap_alloc(&sg, sizeof(struct timeval)); 852132451Sroberto uap->olddelta = (struct timeval32 *)op; 853182007Sroberto } 854290001Sglebius error = utimes(td, (struct utimes_args *) uap); 85556746Sroberto if (error) 85656746Sroberto return error; 85756746Sroberto if (op32) { 85856746Sroberto error = copyin(op, &s, sizeof(s)); 859290001Sglebius if (error) 86056746Sroberto return (error); 86156746Sroberto CP(s, s32, tv_sec); 86256746Sroberto CP(s, s32, tv_usec); 86356746Sroberto error = copyout(&s32, op32, sizeof(s32)); 86482498Sroberto } 86556746Sroberto return (error); 86656746Sroberto} 867182007Sroberto 868290001Sglebius#ifdef COMPAT_FREEBSD4 869182007Srobertoint 870182007Srobertofreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap) 87154359Sroberto{ 872290001Sglebius int error; 873182007Sroberto caddr_t sg; 874182007Sroberto struct statfs32 *p32, s32; 87554359Sroberto struct statfs *p = NULL, s; 876290001Sglebius 877290001Sglebius p32 = uap->buf; 87856746Sroberto if (p32) { 879182007Sroberto sg = stackgap_init(); 880290001Sglebius p = stackgap_alloc(&sg, sizeof(struct statfs)); 881290001Sglebius uap->buf = (struct statfs32 *)p; 882182007Sroberto } 883182007Sroberto error = statfs(td, (struct statfs_args *) uap); 884182007Sroberto if (error) 885182007Sroberto return (error); 886290001Sglebius if (p32) { 887290001Sglebius error = copyin(p, &s, sizeof(s)); 888290001Sglebius if (error) 889182007Sroberto return (error); 890182007Sroberto copy_statfs(&s, &s32); 891182007Sroberto error = copyout(&s32, p32, sizeof(s32)); 892182007Sroberto } 893182007Sroberto return (error); 894182007Sroberto} 895182007Sroberto#endif 89654359Sroberto 897290001Sglebius#ifdef COMPAT_FREEBSD4 898290001Sglebiusint 89954359Srobertofreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap) 90056746Sroberto{ 901132451Sroberto int error; 90282498Sroberto caddr_t sg; 903132451Sroberto struct statfs32 *p32, s32; 904132451Sroberto struct statfs *p = NULL, s; 90582498Sroberto 906290001Sglebius p32 = uap->buf; 907182007Sroberto if (p32) { 908132451Sroberto sg = stackgap_init(); 909132451Sroberto p = stackgap_alloc(&sg, sizeof(struct statfs)); 910132451Sroberto uap->buf = (struct statfs32 *)p; 911132451Sroberto } 91282498Sroberto error = fstatfs(td, (struct fstatfs_args *) uap); 913182007Sroberto if (error) 914182007Sroberto return (error); 915182007Sroberto if (p32) { 916182007Sroberto error = copyin(p, &s, sizeof(s)); 917290001Sglebius if (error) 918290001Sglebius return (error); 919182007Sroberto copy_statfs(&s, &s32); 92056746Sroberto error = copyout(&s32, p32, sizeof(s32)); 921290001Sglebius } 922290001Sglebius return (error); 92354359Sroberto} 924132451Sroberto#endif 925132451Sroberto 92656746Sroberto#ifdef COMPAT_FREEBSD4 927132451Srobertoint 928132451Srobertofreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap) 929132451Sroberto{ 930132451Sroberto int error; 931132451Sroberto caddr_t sg; 932132451Sroberto struct statfs32 *p32, s32; 933132451Sroberto struct statfs *p = NULL, s; 934132451Sroberto 935290001Sglebius p32 = uap->buf; 936182007Sroberto if (p32) { 937132451Sroberto sg = stackgap_init(); 938132451Sroberto p = stackgap_alloc(&sg, sizeof(struct statfs)); 939290001Sglebius uap->buf = (struct statfs32 *)p; 940132451Sroberto } 941290001Sglebius error = fhstatfs(td, (struct fhstatfs_args *) uap); 942132451Sroberto if (error) 943132451Sroberto return (error); 944132451Sroberto if (p32) { 945132451Sroberto error = copyin(p, &s, sizeof(s)); 946132451Sroberto if (error) 947132451Sroberto return (error); 948182007Sroberto copy_statfs(&s, &s32); 949132451Sroberto error = copyout(&s32, p32, sizeof(s32)); 950290001Sglebius } 951132451Sroberto return (error); 952132451Sroberto} 953132451Sroberto#endif 954182007Sroberto 955290001Sglebiusint 956290001Sglebiusfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 957132451Sroberto{ 958132451Sroberto /* 95954359Sroberto * Vector through to semsys if it is loaded. 96054359Sroberto */ 961132451Sroberto return sysent[169].sy_call(td, uap); 962132451Sroberto} 963132451Sroberto 964290001Sglebiusint 965182007Srobertofreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 966182007Sroberto{ 967182007Sroberto /* 968132451Sroberto * Vector through to msgsys if it is loaded. 969132451Sroberto */ 970132451Sroberto return sysent[170].sy_call(td, uap); 971132451Sroberto} 972132451Sroberto 973132451Srobertoint 974132451Srobertofreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 975132451Sroberto{ 976132451Sroberto /* 977132451Sroberto * Vector through to shmsys if it is loaded. 978132451Sroberto */ 979132451Sroberto return sysent[171].sy_call(td, uap); 980132451Sroberto} 981132451Sroberto 982132451Srobertoint 983132451Srobertofreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 984132451Sroberto{ 985132451Sroberto struct pread_args ap; 986132451Sroberto 987132451Sroberto ap.fd = uap->fd; 988132451Sroberto ap.buf = uap->buf; 989132451Sroberto ap.nbyte = uap->nbyte; 990132451Sroberto ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 991132451Sroberto return (pread(td, &ap)); 992132451Sroberto} 993132451Sroberto 994132451Srobertoint 995132451Srobertofreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 996132451Sroberto{ 997290001Sglebius struct pwrite_args ap; 998132451Sroberto 999132451Sroberto ap.fd = uap->fd; 1000132451Sroberto ap.buf = uap->buf; 1001132451Sroberto ap.nbyte = uap->nbyte; 1002132451Sroberto ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1003132451Sroberto return (pwrite(td, &ap)); 1004132451Sroberto} 1005132451Sroberto 1006132451Srobertoint 1007132451Srobertofreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 1008132451Sroberto{ 1009132451Sroberto int error; 1010132451Sroberto struct lseek_args ap; 1011132451Sroberto off_t pos; 1012132451Sroberto 1013132451Sroberto ap.fd = uap->fd; 1014132451Sroberto ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1015132451Sroberto ap.whence = uap->whence; 1016132451Sroberto error = lseek(td, &ap); 1017132451Sroberto /* Expand the quad return into two parts for eax and edx */ 1018132451Sroberto pos = *(off_t *)(td->td_retval); 1019132451Sroberto td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1020132451Sroberto td->td_retval[1] = pos >> 32; /* %edx */ 1021132451Sroberto return error; 1022132451Sroberto} 1023132451Sroberto 1024132451Srobertoint 1025132451Srobertofreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 1026132451Sroberto{ 1027132451Sroberto struct truncate_args ap; 1028132451Sroberto 1029182007Sroberto ap.path = uap->path; 1030182007Sroberto ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1031182007Sroberto return (truncate(td, &ap)); 1032182007Sroberto} 103354359Sroberto 103454359Srobertoint 1035132451Srobertofreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 1036182007Sroberto{ 1037182007Sroberto struct ftruncate_args ap; 1038182007Sroberto 1039182007Sroberto ap.fd = uap->fd; 1040182007Sroberto ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 104154359Sroberto return (ftruncate(td, &ap)); 1042182007Sroberto} 1043182007Sroberto 1044132451Sroberto#ifdef COMPAT_FREEBSD4 1045132451Srobertoint 1046132451Srobertofreebsd4_freebsd32_sendfile(struct thread *td, 1047132451Sroberto struct freebsd4_freebsd32_sendfile_args *uap) 1048132451Sroberto{ 1049132451Sroberto struct freebsd4_sendfile_args ap; 1050132451Sroberto 1051132451Sroberto ap.fd = uap->fd; 1052290001Sglebius ap.s = uap->s; 1053132451Sroberto ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1054132451Sroberto ap.nbytes = uap->nbytes; /* XXX check */ 1055132451Sroberto ap.hdtr = uap->hdtr; /* XXX check */ 1056132451Sroberto ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1057132451Sroberto ap.flags = uap->flags; 1058132451Sroberto return (freebsd4_sendfile(td, &ap)); 1059132451Sroberto} 1060132451Sroberto#endif 1061132451Sroberto 1062132451Srobertoint 1063132451Srobertofreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 1064132451Sroberto{ 1065132451Sroberto struct sendfile_args ap; 1066132451Sroberto 1067132451Sroberto ap.fd = uap->fd; 1068132451Sroberto ap.s = uap->s; 1069132451Sroberto ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1070290001Sglebius ap.nbytes = uap->nbytes; /* XXX check */ 1071290001Sglebius ap.hdtr = uap->hdtr; /* XXX check */ 1072290001Sglebius ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 107354359Sroberto ap.flags = uap->flags; 1074132451Sroberto return (sendfile(td, &ap)); 107554359Sroberto} 107656746Sroberto 107756746Srobertostruct stat32 { 107854359Sroberto dev_t st_dev; 107954359Sroberto ino_t st_ino; 108054359Sroberto mode_t st_mode; 108182498Sroberto nlink_t st_nlink; 108254359Sroberto uid_t st_uid; 108354359Sroberto gid_t st_gid; 108454359Sroberto dev_t st_rdev; 108554359Sroberto struct timespec32 st_atimespec; 108654359Sroberto struct timespec32 st_mtimespec; 108754359Sroberto struct timespec32 st_ctimespec; 108882498Sroberto off_t st_size; 1089290001Sglebius int64_t st_blocks; 109082498Sroberto u_int32_t st_blksize; 109182498Sroberto u_int32_t st_flags; 1092290001Sglebius u_int32_t st_gen; 109382498Sroberto struct timespec32 st_birthtimespec; 109482498Sroberto unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 109554359Sroberto unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 109682498Sroberto}; 109754359Sroberto 109854359Sroberto 109954359SrobertoCTASSERT(sizeof(struct stat32) == 96); 110054359Sroberto 110154359Srobertostatic void 110254359Srobertocopy_stat( struct stat *in, struct stat32 *out) 110354359Sroberto{ 110454359Sroberto CP(*in, *out, st_dev); 110554359Sroberto CP(*in, *out, st_ino); 110654359Sroberto CP(*in, *out, st_mode); 110754359Sroberto CP(*in, *out, st_nlink); 110854359Sroberto CP(*in, *out, st_uid); 110954359Sroberto CP(*in, *out, st_gid); 111054359Sroberto CP(*in, *out, st_rdev); 111154359Sroberto TS_CP(*in, *out, st_atimespec); 111254359Sroberto TS_CP(*in, *out, st_mtimespec); 111354359Sroberto TS_CP(*in, *out, st_ctimespec); 111454359Sroberto CP(*in, *out, st_size); 111554359Sroberto CP(*in, *out, st_blocks); 111654359Sroberto CP(*in, *out, st_blksize); 111754359Sroberto CP(*in, *out, st_flags); 111854359Sroberto CP(*in, *out, st_gen); 111954359Sroberto} 112054359Sroberto 1121132451Srobertoint 1122132451Srobertofreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 112354359Sroberto{ 112454359Sroberto struct stat sb; 112554359Sroberto struct stat32 sb32; 112654359Sroberto int error; 112754359Sroberto struct nameidata nd; 112854359Sroberto 112954359Sroberto#ifdef LOOKUP_SHARED 113054359Sroberto NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ, 113154359Sroberto UIO_USERSPACE, uap->path, td); 113254359Sroberto#else 113354359Sroberto NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 113454359Sroberto uap->path, td); 113554359Sroberto#endif 113654359Sroberto if ((error = namei(&nd)) != 0) 113754359Sroberto return (error); 113854359Sroberto error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td); 113954359Sroberto NDFREE(&nd, NDF_ONLY_PNBUF); 114082498Sroberto vput(nd.ni_vp); 114182498Sroberto if (error) 114282498Sroberto return (error); 1143132451Sroberto copy_stat(&sb, &sb32); 114482498Sroberto error = copyout(&sb32, uap->ub, sizeof (sb32)); 114554359Sroberto return (error); 114682498Sroberto} 114754359Sroberto 114854359Srobertoint 114982498Srobertofreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 115082498Sroberto{ 115182498Sroberto struct file *fp; 115282498Sroberto struct stat ub; 115382498Sroberto struct stat32 ub32; 115482498Sroberto int error; 115554359Sroberto 115654359Sroberto if ((error = fget(td, uap->fd, &fp)) != 0) 115754359Sroberto return (error); 115854359Sroberto mtx_lock(&Giant); 115954359Sroberto error = fo_stat(fp, &ub, td->td_ucred, td); 116082498Sroberto mtx_unlock(&Giant); 116154359Sroberto fdrop(fp, td); 116254359Sroberto if (error) 1163132451Sroberto return (error); 1164132451Sroberto copy_stat(&ub, &ub32); 116554359Sroberto error = copyout(&ub32, uap->ub, sizeof(ub32)); 1166132451Sroberto return (error); 1167290001Sglebius} 1168132451Sroberto 1169132451Srobertoint 1170132451Srobertofreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 1171132451Sroberto{ 1172132451Sroberto int error; 117382498Sroberto struct vnode *vp; 117482498Sroberto struct stat sb; 1175132451Sroberto struct stat32 sb32; 1176132451Sroberto struct nameidata nd; 1177132451Sroberto 1178132451Sroberto NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1179132451Sroberto uap->path, td); 1180132451Sroberto if ((error = namei(&nd)) != 0) 118182498Sroberto return (error); 118282498Sroberto vp = nd.ni_vp; 118382498Sroberto error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td); 1184132451Sroberto NDFREE(&nd, NDF_ONLY_PNBUF); 118582498Sroberto vput(vp); 118682498Sroberto if (error) 118782498Sroberto return (error); 1188132451Sroberto copy_stat(&sb, &sb32); 1189132451Sroberto error = copyout(&sb32, uap->ub, sizeof (sb32)); 1190132451Sroberto return (error); 1191132451Sroberto} 1192132451Sroberto 1193290001Sglebius/* 1194290001Sglebius * MPSAFE 1195290001Sglebius */ 1196290001Sglebiusint 1197290001Sglebiusfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 1198290001Sglebius{ 1199290001Sglebius int error, name[CTL_MAXNAME]; 1200290001Sglebius size_t j, oldlen; 1201290001Sglebius 1202290001Sglebius if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1203290001Sglebius return (EINVAL); 120454359Sroberto error = copyin(uap->name, name, uap->namelen * sizeof(int)); 120554359Sroberto if (error) 120654359Sroberto return (error); 120754359Sroberto mtx_lock(&Giant); 120854359Sroberto if (uap->oldlenp) 120954359Sroberto oldlen = fuword32(uap->oldlenp); 121054359Sroberto else 121154359Sroberto oldlen = 0; 121254359Sroberto error = userland_sysctl(td, name, uap->namelen, 1213290001Sglebius uap->old, &oldlen, 1, 1214290001Sglebius uap->new, uap->newlen, &j, SCTL_MASK32); 1215290001Sglebius if (error && error != ENOMEM) 1216132451Sroberto goto done2; 121754359Sroberto if (uap->oldlenp) 121854359Sroberto suword32(uap->oldlenp, j); 1219182007Srobertodone2: 1220182007Sroberto mtx_unlock(&Giant); 1221182007Sroberto return (error); 1222290001Sglebius} 1223290001Sglebius 1224182007Srobertostruct sigaction32 { 1225182007Sroberto u_int32_t sa_u; 1226290001Sglebius int sa_flags; 1227290001Sglebius sigset_t sa_mask; 1228182007Sroberto}; 1229182007Sroberto 1230290001SglebiusCTASSERT(sizeof(struct sigaction32) == 24); 1231290001Sglebius 1232182007Srobertoint 123382498Srobertofreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 123454359Sroberto{ 1235182007Sroberto struct sigaction32 s32; 1236182007Sroberto struct sigaction sa, osa, *sap; 1237182007Sroberto int error; 1238182007Sroberto 1239182007Sroberto if (uap->act) { 1240132451Sroberto error = copyin(uap->act, &s32, sizeof(s32)); 124154359Sroberto if (error) 124254359Sroberto return (error); 1243290001Sglebius sa.sa_handler = PTRIN(s32.sa_u); 124456746Sroberto CP(s32, sa, sa_flags); 124556746Sroberto CP(s32, sa, sa_mask); 1246290001Sglebius sap = &sa; 1247290001Sglebius } else 124882498Sroberto sap = NULL; 124956746Sroberto error = kern_sigaction(td, uap->sig, sap, &osa, 0); 125056746Sroberto if (error != 0 && uap->oact != NULL) { 1251290001Sglebius s32.sa_u = PTROUT(osa.sa_handler); 125256746Sroberto CP(osa, s32, sa_flags); 125356746Sroberto CP(osa, s32, sa_mask); 125456746Sroberto error = copyout(&s32, uap->oact, sizeof(s32)); 125556746Sroberto } 1256290001Sglebius return (error); 125756746Sroberto} 125856746Sroberto 125956746Sroberto#ifdef COMPAT_FREEBSD4 126056746Srobertoint 126156746Srobertofreebsd4_freebsd32_sigaction(struct thread *td, 126256746Sroberto struct freebsd4_freebsd32_sigaction_args *uap) 126382498Sroberto{ 126456746Sroberto struct sigaction32 s32; 1265290001Sglebius struct sigaction sa, osa, *sap; 1266290001Sglebius int error; 1267290001Sglebius 1268290001Sglebius if (uap->act) { 126982498Sroberto error = copyin(uap->act, &s32, sizeof(s32)); 127056746Sroberto if (error) 127156746Sroberto return (error); 127282498Sroberto sa.sa_handler = PTRIN(s32.sa_u); 127382498Sroberto CP(s32, sa, sa_flags); 1274290001Sglebius CP(s32, sa, sa_mask); 127556746Sroberto sap = &sa; 127656746Sroberto } else 127782498Sroberto sap = NULL; 1278290001Sglebius error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 127956746Sroberto if (error != 0 && uap->oact != NULL) { 128056746Sroberto s32.sa_u = PTROUT(osa.sa_handler); 128156746Sroberto CP(osa, s32, sa_flags); 128256746Sroberto CP(osa, s32, sa_mask); 1283290001Sglebius error = copyout(&s32, uap->oact, sizeof(s32)); 1284290001Sglebius } 1285290001Sglebius return (error); 128656746Sroberto} 128782498Sroberto#endif 128854359Sroberto 128956746Srobertoint 129054359Srobertofreebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap) 129154359Sroberto{ 129254359Sroberto struct timespec32 rmt32, rqt32; 129354359Sroberto struct timespec rmt, rqt; 129454359Sroberto int error; 129554359Sroberto 129654359Sroberto error = copyin(uap->rqtp, &rqt32, sizeof(rqt)); 129782498Sroberto if (error) 129854359Sroberto return (error); 129956746Sroberto 130054359Sroberto CP(rqt32, rqt, tv_sec); 130154359Sroberto CP(rqt32, rqt, tv_nsec); 130254359Sroberto 130354359Sroberto if (uap->rmtp && 130454359Sroberto !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 130554359Sroberto return (EFAULT); 130654359Sroberto error = kern_nanosleep(td, &rqt, &rmt); 130782498Sroberto if (error && uap->rmtp) { 130854359Sroberto int error2; 130954359Sroberto 131056746Sroberto CP(rmt, rmt32, tv_sec); 131154359Sroberto CP(rmt, rmt32, tv_nsec); 131254359Sroberto 131354359Sroberto error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt)); 131454359Sroberto if (error2) 131582498Sroberto error = error2; 131654359Sroberto } 131754359Sroberto return (error); 131856746Sroberto} 131954359Sroberto 132054359Sroberto#if 0 132154359Sroberto 132254359Srobertoint 132354359Srobertofreebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 132454359Sroberto{ 132554359Sroberto int error; 132654359Sroberto caddr_t sg; 132754359Sroberto struct yyy32 *p32, s32; 132854359Sroberto struct yyy *p = NULL, s; 1329290001Sglebius 1330290001Sglebius p32 = uap->zzz; 1331290001Sglebius if (p32) { 1332290001Sglebius sg = stackgap_init(); 1333290001Sglebius p = stackgap_alloc(&sg, sizeof(struct yyy)); 133482498Sroberto uap->zzz = (struct yyy32 *)p; 133582498Sroberto error = copyin(p32, &s32, sizeof(s32)); 133654359Sroberto if (error) 133754359Sroberto return (error); 133856746Sroberto /* translate in */ 133954359Sroberto error = copyout(&s, p, sizeof(s)); 134054359Sroberto if (error) 134154359Sroberto return (error); 134254359Sroberto } 134354359Sroberto error = xxx(td, (struct xxx_args *) uap); 134454359Sroberto if (error) 134554359Sroberto return (error); 134654359Sroberto if (p32) { 134754359Sroberto error = copyin(p, &s, sizeof(s)); 134854359Sroberto if (error) 1349290001Sglebius return (error); 1350290001Sglebius /* translate out */ 1351290001Sglebius error = copyout(&s32, p32, sizeof(s32)); 1352290001Sglebius } 1353290001Sglebius return (error); 135482498Sroberto} 135582498Sroberto 135656746Sroberto#endif 135754359Sroberto