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