freebsd32_misc.c revision 192895
113044Sasami/*-
2116111Sphk * Copyright (c) 2002 Doug Rabson
313044Sasami * All rights reserved.
413044Sasami *
513044Sasami * Redistribution and use in source and binary forms, with or without
613044Sasami * modification, are permitted provided that the following conditions
713044Sasami * are met:
813044Sasami * 1. Redistributions of source code must retain the above copyright
913044Sasami *    notice, this list of conditions and the following disclaimer.
1013044Sasami * 2. Redistributions in binary form must reproduce the above copyright
1113044Sasami *    notice, this list of conditions and the following disclaimer in the
1213044Sasami *    documentation and/or other materials provided with the distribution.
1313044Sasami *
1413044Sasami * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1513044Sasami * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1613044Sasami * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1713044Sasami * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1813044Sasami * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1913044Sasami * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2013044Sasami * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2113044Sasami * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2213044Sasami * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2313044Sasami * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2413044Sasami * SUCH DAMAGE.
2513044Sasami */
2613044Sasami
2713044Sasami#include <sys/cdefs.h>
2813044Sasami__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 192895 2009-05-27 14:11:23Z jamie $");
2913044Sasami
3013044Sasami#include "opt_compat.h"
3113044Sasami#include "opt_inet.h"
3213044Sasami#include "opt_inet6.h"
3313044Sasami
34114589Sobrien#include <sys/param.h>
35114589Sobrien#include <sys/bus.h>
3636628Scharnier#include <sys/clock.h>
3713044Sasami#include <sys/exec.h>
3848568Sbillf#include <sys/fcntl.h>
3945329Speter#include <sys/filedesc.h>
4013044Sasami#include <sys/imgact.h>
4113044Sasami#include <sys/jail.h>
4213044Sasami#include <sys/kernel.h>
4313044Sasami#include <sys/limits.h>
4469793Sobrien#include <sys/lock.h>
4513044Sasami#include <sys/malloc.h>
4613044Sasami#include <sys/file.h>		/* Must come after sys/malloc.h */
4713044Sasami#include <sys/mbuf.h>
4813044Sasami#include <sys/mman.h>
49115730Sphk#include <sys/module.h>
5013044Sasami#include <sys/mount.h>
51116111Sphk#include <sys/mutex.h>
52116111Sphk#include <sys/namei.h>
53157740Scracauer#include <sys/proc.h>
54157740Scracauer#include <sys/reboot.h>
5513044Sasami#include <sys/resource.h>
5613044Sasami#include <sys/resourcevar.h>
5713044Sasami#include <sys/selinfo.h>
5813044Sasami#include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
5913044Sasami#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
60109417Sphk#include <sys/signal.h>
6113044Sasami#include <sys/signalvar.h>
62227081Sed#include <sys/socket.h>
63109417Sphk#include <sys/socketvar.h>
64116111Sphk#include <sys/stat.h>
6513044Sasami#include <sys/syscall.h>
6613044Sasami#include <sys/syscallsubr.h>
67116111Sphk#include <sys/sysctl.h>
6813762Sasami#include <sys/sysent.h>
69116111Sphk#include <sys/sysproto.h>
70157740Scracauer#include <sys/systm.h>
71157740Scracauer#include <sys/thr.h>
72157740Scracauer#include <sys/unistd.h>
73157740Scracauer#include <sys/ucontext.h>
74116111Sphk#include <sys/vnode.h>
7513044Sasami#include <sys/wait.h>
7613044Sasami#include <sys/ipc.h>
7713044Sasami#include <sys/msg.h>
7813044Sasami#include <sys/sem.h>
7913044Sasami#include <sys/shm.h>
8013044Sasami
8113044Sasami#ifdef INET
8213044Sasami#include <netinet/in.h>
8313044Sasami#endif
8492539Simp
8592539Simp#include <vm/vm.h>
8692539Simp#include <vm/vm_kern.h>
8792539Simp#include <vm/vm_param.h>
88109417Sphk#include <vm/pmap.h>
8992539Simp#include <vm/vm_map.h>
9013044Sasami#include <vm/vm_object.h>
9113044Sasami#include <vm/vm_extern.h>
9292539Simp
9313044Sasami#include <machine/cpu.h>
9413044Sasami
9513044Sasami#include <security/audit/audit.h>
9683329Sru
9713044Sasami#include <compat/freebsd32/freebsd32_util.h>
9813044Sasami#include <compat/freebsd32/freebsd32.h>
9913044Sasami#include <compat/freebsd32/freebsd32_ipc.h>
10013044Sasami#include <compat/freebsd32/freebsd32_signal.h>
10113044Sasami#include <compat/freebsd32/freebsd32_proto.h>
10213044Sasami
10313044SasamiCTASSERT(sizeof(struct timeval32) == 8);
10413044SasamiCTASSERT(sizeof(struct timespec32) == 8);
10513044SasamiCTASSERT(sizeof(struct itimerval32) == 16);
10613044SasamiCTASSERT(sizeof(struct statfs32) == 256);
10713044SasamiCTASSERT(sizeof(struct rusage32) == 72);
10813044SasamiCTASSERT(sizeof(struct sigaltstack32) == 12);
10913044SasamiCTASSERT(sizeof(struct kevent32) == 20);
11013044SasamiCTASSERT(sizeof(struct iovec32) == 8);
11113044SasamiCTASSERT(sizeof(struct msghdr32) == 28);
11213044SasamiCTASSERT(sizeof(struct stat32) == 96);
11313044SasamiCTASSERT(sizeof(struct sigaction32) == 24);
11413044Sasami
11513044Sasamistatic int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
11613044Sasamistatic int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
11713044Sasami
11813044Sasamiint
11913044Sasamifreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
12013044Sasami{
12113044Sasami	int error, status;
12213044Sasami	struct rusage32 ru32;
12313044Sasami	struct rusage ru, *rup;
12413044Sasami
12513044Sasami	if (uap->rusage != NULL)
12613044Sasami		rup = &ru;
12713044Sasami	else
12813044Sasami		rup = NULL;
12913044Sasami	error = kern_wait(td, uap->pid, &status, uap->options, rup);
13013044Sasami	if (error)
13113044Sasami		return (error);
13213044Sasami	if (uap->status != NULL)
13313044Sasami		error = copyout(&status, uap->status, sizeof(status));
13413044Sasami	if (uap->rusage != NULL && error == 0) {
13513044Sasami		TV_CP(ru, ru32, ru_utime);
13613044Sasami		TV_CP(ru, ru32, ru_stime);
13713044Sasami		CP(ru, ru32, ru_maxrss);
13813044Sasami		CP(ru, ru32, ru_ixrss);
13913044Sasami		CP(ru, ru32, ru_idrss);
140116111Sphk		CP(ru, ru32, ru_isrss);
14145329Speter		CP(ru, ru32, ru_minflt);
142116126Sphk		CP(ru, ru32, ru_majflt);
143116126Sphk		CP(ru, ru32, ru_nswap);
14445329Speter		CP(ru, ru32, ru_inblock);
14545329Speter		CP(ru, ru32, ru_oublock);
14613044Sasami		CP(ru, ru32, ru_msgsnd);
14713044Sasami		CP(ru, ru32, ru_msgrcv);
14813044Sasami		CP(ru, ru32, ru_nsignals);
14913044Sasami		CP(ru, ru32, ru_nvcsw);
15013044Sasami		CP(ru, ru32, ru_nivcsw);
15113044Sasami		error = copyout(&ru32, uap->rusage, sizeof(ru32));
15213044Sasami	}
15313044Sasami	return (error);
15413044Sasami}
15513044Sasami
15613044Sasami#ifdef COMPAT_FREEBSD4
15713044Sasamistatic void
15813044Sasamicopy_statfs(struct statfs *in, struct statfs32 *out)
15913044Sasami{
16013044Sasami
16113044Sasami	statfs_scale_blocks(in, INT32_MAX);
16236628Scharnier	bzero(out, sizeof(*out));
16313044Sasami	CP(*in, *out, f_bsize);
16413044Sasami	out->f_iosize = MIN(in->f_iosize, INT32_MAX);
16513044Sasami	CP(*in, *out, f_blocks);
16692539Simp	CP(*in, *out, f_bfree);
16713044Sasami	CP(*in, *out, f_bavail);
168116111Sphk	out->f_files = MIN(in->f_files, INT32_MAX);
169116111Sphk	out->f_ffree = MIN(in->f_ffree, INT32_MAX);
170116111Sphk	CP(*in, *out, f_fsid);
171116111Sphk	CP(*in, *out, f_owner);
172116111Sphk	CP(*in, *out, f_type);
173116111Sphk	CP(*in, *out, f_flags);
17413044Sasami	out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
17513044Sasami	out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
17613044Sasami	strlcpy(out->f_fstypename,
17713044Sasami	      in->f_fstypename, MFSNAMELEN);
17813044Sasami	strlcpy(out->f_mntonname,
179116111Sphk	      in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
180209052Suqs	out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
18113044Sasami	out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
182109472Sphk	strlcpy(out->f_mntfromname,
18313044Sasami	      in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
18413044Sasami}
18513044Sasami#endif
186116111Sphk
187116111Sphk#ifdef COMPAT_FREEBSD4
188116111Sphkint
189116111Sphkfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
190116111Sphk{
191116111Sphk	struct statfs *buf, *sp;
192116111Sphk	struct statfs32 stat32;
19313044Sasami	size_t count, size;
19413044Sasami	int error;
195116111Sphk
196116111Sphk	count = uap->bufsize / sizeof(struct statfs32);
197116111Sphk	size = count * sizeof(struct statfs);
198116111Sphk	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
199116111Sphk	if (size > 0) {
200116111Sphk		count = td->td_retval[0];
201116111Sphk		sp = buf;
20213044Sasami		while (count > 0 && error == 0) {
203116111Sphk			copy_statfs(sp, &stat32);
20413044Sasami			error = copyout(&stat32, uap->buf, sizeof(stat32));
20513044Sasami			sp++;
20613044Sasami			uap->buf++;
20748568Sbillf			count--;
20813044Sasami		}
20913044Sasami		free(buf, M_TEMP);
21013044Sasami	}
21113044Sasami	return (error);
21213044Sasami}
21313044Sasami#endif
21413044Sasami
21513044Sasamiint
21613044Sasamifreebsd32_sigaltstack(struct thread *td,
21713044Sasami		      struct freebsd32_sigaltstack_args *uap)
21848568Sbillf{
21913044Sasami	struct sigaltstack32 s32;
22013044Sasami	struct sigaltstack ss, oss, *ssp;
22113044Sasami	int error;
222109472Sphk
22313044Sasami	if (uap->ss != NULL) {
22413044Sasami		error = copyin(uap->ss, &s32, sizeof(s32));
22513044Sasami		if (error)
22613044Sasami			return (error);
22713044Sasami		PTRIN_CP(s32, ss, ss_sp);
22813044Sasami		CP(s32, ss, ss_size);
22913044Sasami		CP(s32, ss, ss_flags);
23013044Sasami		ssp = &ss;
23113044Sasami	} else
23213044Sasami		ssp = NULL;
23313044Sasami	error = kern_sigaltstack(td, ssp, &oss);
23413044Sasami	if (error == 0 && uap->oss != NULL) {
23513044Sasami		PTROUT_CP(oss, s32, ss_sp);
23613044Sasami		CP(oss, s32, ss_size);
23713044Sasami		CP(oss, s32, ss_flags);
23813044Sasami		error = copyout(&s32, uap->oss, sizeof(s32));
23913044Sasami	}
24013044Sasami	return (error);
24113044Sasami}
24213044Sasami
24313044Sasami/*
244116111Sphk * Custom version of exec_copyin_args() so that we can translate
245116111Sphk * the pointers.
246116111Sphk */
247116111Sphkstatic int
248116111Sphkfreebsd32_exec_copyin_args(struct image_args *args, char *fname,
249116111Sphk    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
250116111Sphk{
251116111Sphk	char *argp, *envp;
252116111Sphk	u_int32_t *p32, arg;
253157740Scracauer	size_t length;
254157740Scracauer	int error;
255157740Scracauer
256157740Scracauer	bzero(args, sizeof(*args));
257116111Sphk	if (argv == NULL)
258116111Sphk		return (EFAULT);
259116111Sphk
260116111Sphk	/*
261116111Sphk	 * Allocate temporary demand zeroed space for argument and
262116111Sphk	 *	environment strings
263116111Sphk	 */
26413044Sasami	args->buf = (char *) kmem_alloc_wait(exec_map,
265116111Sphk	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
266116111Sphk	if (args->buf == NULL)
267116111Sphk		return (ENOMEM);
268116111Sphk	args->begin_argv = args->buf;
269116111Sphk	args->endp = args->begin_argv;
27013044Sasami	args->stringspace = ARG_MAX;
271116111Sphk
272116111Sphk	/*
27313044Sasami	 * Copy the file name.
274116111Sphk	 */
275116111Sphk	if (fname != NULL) {
276116111Sphk		args->fname = args->buf + ARG_MAX;
277116111Sphk		error = (segflg == UIO_SYSSPACE) ?
27813044Sasami		    copystr(fname, args->fname, PATH_MAX, &length) :
27913044Sasami		    copyinstr(fname, args->fname, PATH_MAX, &length);
28013044Sasami		if (error != 0)
28192539Simp			goto err_exit;
28213044Sasami	} else
28313044Sasami		args->fname = NULL;
28413044Sasami
28513044Sasami	/*
28613044Sasami	 * extract arguments first
28732116Simp	 */
28813044Sasami	p32 = argv;
28951690Sbillf	for (;;) {
29032116Simp		error = copyin(p32++, &arg, sizeof(arg));
291241848Seadler		if (error)
292241848Seadler			goto err_exit;
29313044Sasami		if (arg == 0)
294241848Seadler			break;
295241848Seadler		argp = PTRIN(arg);
29613044Sasami		error = copyinstr(argp, args->endp, args->stringspace, &length);
29713044Sasami		if (error) {
29813044Sasami			if (error == ENAMETOOLONG)
299241848Seadler				error = E2BIG;
300241848Seadler			goto err_exit;
30113044Sasami		}
30213044Sasami		args->stringspace -= length;
30313044Sasami		args->endp += length;
30413044Sasami		args->argc++;
30513044Sasami	}
30613044Sasami
30713044Sasami	args->begin_envv = args->endp;
30813044Sasami
30913044Sasami	/*
31013044Sasami	 * extract environment strings
31113044Sasami	 */
31213044Sasami	if (envv) {
31313044Sasami		p32 = envv;
31413044Sasami		for (;;) {
31513044Sasami			error = copyin(p32++, &arg, sizeof(arg));
31613044Sasami			if (error)
31713044Sasami				goto err_exit;
31813044Sasami			if (arg == 0)
31913044Sasami				break;
32013044Sasami			envp = PTRIN(arg);
32113044Sasami			error = copyinstr(envp, args->endp, args->stringspace,
32213044Sasami			    &length);
32313044Sasami			if (error) {
32413044Sasami				if (error == ENAMETOOLONG)
32513044Sasami					error = E2BIG;
32613044Sasami				goto err_exit;
32713044Sasami			}
32813044Sasami			args->stringspace -= length;
32913044Sasami			args->endp += length;
33013044Sasami			args->envc++;
33113044Sasami		}
33213044Sasami	}
33313044Sasami
33413044Sasami	return (0);
33513044Sasami
33613044Sasamierr_exit:
33713044Sasami	kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
33813044Sasami	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
33913044Sasami	args->buf = NULL;
34013044Sasami	return (error);
34113044Sasami}
34213044Sasami
34313044Sasamiint
34413044Sasamifreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
34513044Sasami{
34613044Sasami	struct image_args eargs;
34713044Sasami	int error;
34892539Simp
34913044Sasami	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
35013044Sasami	    uap->argv, uap->envv);
351109417Sphk	if (error == 0)
352109417Sphk		error = kern_execve(td, &eargs, NULL);
353109417Sphk	return (error);
354109417Sphk}
355109417Sphk
356109417Sphkint
357109417Sphkfreebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
358109417Sphk{
35913044Sasami	struct image_args eargs;
36013044Sasami	int error;
36113044Sasami
362115731Sphk	error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE,
36313044Sasami	    uap->argv, uap->envv);
364115731Sphk	if (error == 0) {
365115731Sphk		eargs.fd = uap->fd;
366115731Sphk		error = kern_execve(td, &eargs, NULL);
367109417Sphk	}
368115730Sphk	return (error);
36913044Sasami}
370115730Sphk
371115731Sphk#ifdef __ia64__
372115731Sphkstatic int
373115730Sphkfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
374115730Sphk		       int prot, int fd, off_t pos)
375115731Sphk{
376115731Sphk	vm_map_t map;
377115730Sphk	vm_map_entry_t entry;
378115731Sphk	int rv;
379115731Sphk
380115731Sphk	map = &td->td_proc->p_vmspace->vm_map;
381115731Sphk	if (fd != -1)
382115731Sphk		prot |= VM_PROT_WRITE;
383115731Sphk
384115731Sphk	if (vm_map_lookup_entry(map, start, &entry)) {
385115731Sphk		if ((entry->protection & prot) != prot) {
386115730Sphk			rv = vm_map_protect(map,
387115731Sphk					    trunc_page(start),
388115731Sphk					    round_page(end),
38913044Sasami					    entry->protection | prot,
39013044Sasami					    FALSE);
39113044Sasami			if (rv != KERN_SUCCESS)
392115731Sphk				return (EINVAL);
393115731Sphk		}
39413044Sasami	} else {
395118632Sjohan		vm_offset_t addr = trunc_page(start);
39613044Sasami		rv = vm_map_find(map, 0, 0,
397115731Sphk				 &addr, PAGE_SIZE, FALSE, prot,
398118632Sjohan				 VM_PROT_ALL, 0);
399115731Sphk		if (rv != KERN_SUCCESS)
400118632Sjohan			return (EINVAL);
401118632Sjohan	}
402118632Sjohan
40313044Sasami	if (fd != -1) {
404118632Sjohan		struct pread_args r;
40513044Sasami		r.fd = fd;
40613044Sasami		r.buf = (void *) start;
40713044Sasami		r.nbyte = end - start;
40892539Simp		r.offset = pos;
40913044Sasami		return (pread(td, &r));
41013044Sasami	} else {
411116111Sphk		while (start < end) {
41213044Sasami			subyte((void *) start, 0);
413116111Sphk			start++;
414116111Sphk		}
415116111Sphk		return (0);
416116111Sphk	}
417116111Sphk}
418116111Sphk#endif
419116111Sphk
42013044Sasamiint
42113044Sasamifreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
42213044Sasami{
42313044Sasami	struct mmap_args ap;
42413044Sasami	vm_offset_t addr = (vm_offset_t) uap->addr;
42513044Sasami	vm_size_t len	 = uap->len;
42613044Sasami	int prot	 = uap->prot;
42713044Sasami	int flags	 = uap->flags;
42813044Sasami	int fd		 = uap->fd;
42913044Sasami	off_t pos	 = (uap->poslo
43013044Sasami			    | ((off_t)uap->poshi << 32));
431116111Sphk#ifdef __ia64__
43213044Sasami	vm_size_t pageoff;
43313044Sasami	int error;
43413044Sasami
43513044Sasami	/*
43613044Sasami	 * Attempt to handle page size hassles.
43713044Sasami	 */
438116111Sphk	pageoff = (pos & PAGE_MASK);
43913044Sasami	if (flags & MAP_FIXED) {
44013044Sasami		vm_offset_t start, end;
44113044Sasami		start = addr;
44292539Simp		end = addr + len;
44313044Sasami
44426541Scharnier		if (start != trunc_page(start)) {
445141611Sru			error = freebsd32_mmap_partial(td, start,
44626541Scharnier						       round_page(start), prot,
447141611Sru						       fd, pos);
44826541Scharnier			if (fd != -1)
449141611Sru				pos += round_page(start) - start;
45013044Sasami			start = round_page(start);
45113044Sasami		}
452		if (end != round_page(end)) {
453			vm_offset_t t = trunc_page(end);
454			error = freebsd32_mmap_partial(td, t, end,
455						  prot, fd,
456						  pos + t - start);
457			end = trunc_page(end);
458		}
459		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
460			/*
461			 * We can't map this region at all. The specified
462			 * address doesn't have the same alignment as the file
463			 * position. Fake the mapping by simply reading the
464			 * entire region into memory. First we need to make
465			 * sure the region exists.
466			 */
467			vm_map_t map;
468			struct pread_args r;
469			int rv;
470
471			prot |= VM_PROT_WRITE;
472			map = &td->td_proc->p_vmspace->vm_map;
473			rv = vm_map_remove(map, start, end);
474			if (rv != KERN_SUCCESS)
475				return (EINVAL);
476			rv = vm_map_find(map, 0, 0,
477					 &start, end - start, FALSE,
478					 prot, VM_PROT_ALL, 0);
479			if (rv != KERN_SUCCESS)
480				return (EINVAL);
481			r.fd = fd;
482			r.buf = (void *) start;
483			r.nbyte = end - start;
484			r.offset = pos;
485			error = pread(td, &r);
486			if (error)
487				return (error);
488
489			td->td_retval[0] = addr;
490			return (0);
491		}
492		if (end == start) {
493			/*
494			 * After dealing with the ragged ends, there
495			 * might be none left.
496			 */
497			td->td_retval[0] = addr;
498			return (0);
499		}
500		addr = start;
501		len = end - start;
502	}
503#endif
504
505	ap.addr = (void *) addr;
506	ap.len = len;
507	ap.prot = prot;
508	ap.flags = flags;
509	ap.fd = fd;
510	ap.pos = pos;
511
512	return (mmap(td, &ap));
513}
514
515#ifdef COMPAT_FREEBSD6
516int
517freebsd6_freebsd32_mmap(struct thread *td, struct freebsd6_freebsd32_mmap_args *uap)
518{
519	struct freebsd32_mmap_args ap;
520
521	ap.addr = uap->addr;
522	ap.len = uap->len;
523	ap.prot = uap->prot;
524	ap.flags = uap->flags;
525	ap.fd = uap->fd;
526	ap.poslo = uap->poslo;
527	ap.poshi = uap->poshi;
528
529	return (freebsd32_mmap(td, &ap));
530}
531#endif
532
533int
534freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
535{
536	struct itimerval itv, oitv, *itvp;
537	struct itimerval32 i32;
538	int error;
539
540	if (uap->itv != NULL) {
541		error = copyin(uap->itv, &i32, sizeof(i32));
542		if (error)
543			return (error);
544		TV_CP(i32, itv, it_interval);
545		TV_CP(i32, itv, it_value);
546		itvp = &itv;
547	} else
548		itvp = NULL;
549	error = kern_setitimer(td, uap->which, itvp, &oitv);
550	if (error || uap->oitv == NULL)
551		return (error);
552	TV_CP(oitv, i32, it_interval);
553	TV_CP(oitv, i32, it_value);
554	return (copyout(&i32, uap->oitv, sizeof(i32)));
555}
556
557int
558freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
559{
560	struct itimerval itv;
561	struct itimerval32 i32;
562	int error;
563
564	error = kern_getitimer(td, uap->which, &itv);
565	if (error || uap->itv == NULL)
566		return (error);
567	TV_CP(itv, i32, it_interval);
568	TV_CP(itv, i32, it_value);
569	return (copyout(&i32, uap->itv, sizeof(i32)));
570}
571
572int
573freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
574{
575	struct timeval32 tv32;
576	struct timeval tv, *tvp;
577	int error;
578
579	if (uap->tv != NULL) {
580		error = copyin(uap->tv, &tv32, sizeof(tv32));
581		if (error)
582			return (error);
583		CP(tv32, tv, tv_sec);
584		CP(tv32, tv, tv_usec);
585		tvp = &tv;
586	} else
587		tvp = NULL;
588	/*
589	 * XXX big-endian needs to convert the fd_sets too.
590	 * XXX Do pointers need PTRIN()?
591	 */
592	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
593}
594
595/*
596 * Copy 'count' items into the destination list pointed to by uap->eventlist.
597 */
598static int
599freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
600{
601	struct freebsd32_kevent_args *uap;
602	struct kevent32	ks32[KQ_NEVENTS];
603	int i, error = 0;
604
605	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
606	uap = (struct freebsd32_kevent_args *)arg;
607
608	for (i = 0; i < count; i++) {
609		CP(kevp[i], ks32[i], ident);
610		CP(kevp[i], ks32[i], filter);
611		CP(kevp[i], ks32[i], flags);
612		CP(kevp[i], ks32[i], fflags);
613		CP(kevp[i], ks32[i], data);
614		PTROUT_CP(kevp[i], ks32[i], udata);
615	}
616	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
617	if (error == 0)
618		uap->eventlist += count;
619	return (error);
620}
621
622/*
623 * Copy 'count' items from the list pointed to by uap->changelist.
624 */
625static int
626freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
627{
628	struct freebsd32_kevent_args *uap;
629	struct kevent32	ks32[KQ_NEVENTS];
630	int i, error = 0;
631
632	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
633	uap = (struct freebsd32_kevent_args *)arg;
634
635	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
636	if (error)
637		goto done;
638	uap->changelist += count;
639
640	for (i = 0; i < count; i++) {
641		CP(ks32[i], kevp[i], ident);
642		CP(ks32[i], kevp[i], filter);
643		CP(ks32[i], kevp[i], flags);
644		CP(ks32[i], kevp[i], fflags);
645		CP(ks32[i], kevp[i], data);
646		PTRIN_CP(ks32[i], kevp[i], udata);
647	}
648done:
649	return (error);
650}
651
652int
653freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
654{
655	struct timespec32 ts32;
656	struct timespec ts, *tsp;
657	struct kevent_copyops k_ops = { uap,
658					freebsd32_kevent_copyout,
659					freebsd32_kevent_copyin};
660	int error;
661
662
663	if (uap->timeout) {
664		error = copyin(uap->timeout, &ts32, sizeof(ts32));
665		if (error)
666			return (error);
667		CP(ts32, ts, tv_sec);
668		CP(ts32, ts, tv_nsec);
669		tsp = &ts;
670	} else
671		tsp = NULL;
672	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
673	    &k_ops, tsp);
674	return (error);
675}
676
677int
678freebsd32_gettimeofday(struct thread *td,
679		       struct freebsd32_gettimeofday_args *uap)
680{
681	struct timeval atv;
682	struct timeval32 atv32;
683	struct timezone rtz;
684	int error = 0;
685
686	if (uap->tp) {
687		microtime(&atv);
688		CP(atv, atv32, tv_sec);
689		CP(atv, atv32, tv_usec);
690		error = copyout(&atv32, uap->tp, sizeof (atv32));
691	}
692	if (error == 0 && uap->tzp != NULL) {
693		rtz.tz_minuteswest = tz_minuteswest;
694		rtz.tz_dsttime = tz_dsttime;
695		error = copyout(&rtz, uap->tzp, sizeof (rtz));
696	}
697	return (error);
698}
699
700int
701freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
702{
703	struct rusage32 s32;
704	struct rusage s;
705	int error;
706
707	error = kern_getrusage(td, uap->who, &s);
708	if (error)
709		return (error);
710	if (uap->rusage != NULL) {
711		TV_CP(s, s32, ru_utime);
712		TV_CP(s, s32, ru_stime);
713		CP(s, s32, ru_maxrss);
714		CP(s, s32, ru_ixrss);
715		CP(s, s32, ru_idrss);
716		CP(s, s32, ru_isrss);
717		CP(s, s32, ru_minflt);
718		CP(s, s32, ru_majflt);
719		CP(s, s32, ru_nswap);
720		CP(s, s32, ru_inblock);
721		CP(s, s32, ru_oublock);
722		CP(s, s32, ru_msgsnd);
723		CP(s, s32, ru_msgrcv);
724		CP(s, s32, ru_nsignals);
725		CP(s, s32, ru_nvcsw);
726		CP(s, s32, ru_nivcsw);
727		error = copyout(&s32, uap->rusage, sizeof(s32));
728	}
729	return (error);
730}
731
732static int
733freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
734{
735	struct iovec32 iov32;
736	struct iovec *iov;
737	struct uio *uio;
738	u_int iovlen;
739	int error, i;
740
741	*uiop = NULL;
742	if (iovcnt > UIO_MAXIOV)
743		return (EINVAL);
744	iovlen = iovcnt * sizeof(struct iovec);
745	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
746	iov = (struct iovec *)(uio + 1);
747	for (i = 0; i < iovcnt; i++) {
748		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
749		if (error) {
750			free(uio, M_IOV);
751			return (error);
752		}
753		iov[i].iov_base = PTRIN(iov32.iov_base);
754		iov[i].iov_len = iov32.iov_len;
755	}
756	uio->uio_iov = iov;
757	uio->uio_iovcnt = iovcnt;
758	uio->uio_segflg = UIO_USERSPACE;
759	uio->uio_offset = -1;
760	uio->uio_resid = 0;
761	for (i = 0; i < iovcnt; i++) {
762		if (iov->iov_len > INT_MAX - uio->uio_resid) {
763			free(uio, M_IOV);
764			return (EINVAL);
765		}
766		uio->uio_resid += iov->iov_len;
767		iov++;
768	}
769	*uiop = uio;
770	return (0);
771}
772
773int
774freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
775{
776	struct uio *auio;
777	int error;
778
779	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
780	if (error)
781		return (error);
782	error = kern_readv(td, uap->fd, auio);
783	free(auio, M_IOV);
784	return (error);
785}
786
787int
788freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
789{
790	struct uio *auio;
791	int error;
792
793	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
794	if (error)
795		return (error);
796	error = kern_writev(td, uap->fd, auio);
797	free(auio, M_IOV);
798	return (error);
799}
800
801int
802freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
803{
804	struct uio *auio;
805	int error;
806
807	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
808	if (error)
809		return (error);
810	error = kern_preadv(td, uap->fd, auio, uap->offset);
811	free(auio, M_IOV);
812	return (error);
813}
814
815int
816freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
817{
818	struct uio *auio;
819	int error;
820
821	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
822	if (error)
823		return (error);
824	error = kern_pwritev(td, uap->fd, auio, uap->offset);
825	free(auio, M_IOV);
826	return (error);
827}
828
829static int
830freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
831    int error)
832{
833	struct iovec32 iov32;
834	struct iovec *iov;
835	u_int iovlen;
836	int i;
837
838	*iovp = NULL;
839	if (iovcnt > UIO_MAXIOV)
840		return (error);
841	iovlen = iovcnt * sizeof(struct iovec);
842	iov = malloc(iovlen, M_IOV, M_WAITOK);
843	for (i = 0; i < iovcnt; i++) {
844		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
845		if (error) {
846			free(iov, M_IOV);
847			return (error);
848		}
849		iov[i].iov_base = PTRIN(iov32.iov_base);
850		iov[i].iov_len = iov32.iov_len;
851	}
852	*iovp = iov;
853	return (0);
854}
855
856static int
857freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
858{
859	struct msghdr32 m32;
860	int error;
861
862	error = copyin(msg32, &m32, sizeof(m32));
863	if (error)
864		return (error);
865	msg->msg_name = PTRIN(m32.msg_name);
866	msg->msg_namelen = m32.msg_namelen;
867	msg->msg_iov = PTRIN(m32.msg_iov);
868	msg->msg_iovlen = m32.msg_iovlen;
869	msg->msg_control = PTRIN(m32.msg_control);
870	msg->msg_controllen = m32.msg_controllen;
871	msg->msg_flags = m32.msg_flags;
872	return (0);
873}
874
875static int
876freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
877{
878	struct msghdr32 m32;
879	int error;
880
881	m32.msg_name = PTROUT(msg->msg_name);
882	m32.msg_namelen = msg->msg_namelen;
883	m32.msg_iov = PTROUT(msg->msg_iov);
884	m32.msg_iovlen = msg->msg_iovlen;
885	m32.msg_control = PTROUT(msg->msg_control);
886	m32.msg_controllen = msg->msg_controllen;
887	m32.msg_flags = msg->msg_flags;
888	error = copyout(&m32, msg32, sizeof(m32));
889	return (error);
890}
891
892#define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
893#define FREEBSD32_ALIGN(p)	\
894	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
895#define	FREEBSD32_CMSG_SPACE(l)	\
896	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
897
898#define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
899				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
900static int
901freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
902{
903	struct cmsghdr *cm;
904	void *data;
905	socklen_t clen, datalen;
906	int error;
907	caddr_t ctlbuf;
908	int len, maxlen, copylen;
909	struct mbuf *m;
910	error = 0;
911
912	len    = msg->msg_controllen;
913	maxlen = msg->msg_controllen;
914	msg->msg_controllen = 0;
915
916	m = control;
917	ctlbuf = msg->msg_control;
918
919	while (m && len > 0) {
920		cm = mtod(m, struct cmsghdr *);
921		clen = m->m_len;
922
923		while (cm != NULL) {
924
925			if (sizeof(struct cmsghdr) > clen ||
926			    cm->cmsg_len > clen) {
927				error = EINVAL;
928				break;
929			}
930
931			data   = CMSG_DATA(cm);
932			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
933
934			/* Adjust message length */
935			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
936			    datalen;
937
938
939			/* Copy cmsghdr */
940			copylen = sizeof(struct cmsghdr);
941			if (len < copylen) {
942				msg->msg_flags |= MSG_CTRUNC;
943				copylen = len;
944			}
945
946			error = copyout(cm,ctlbuf,copylen);
947			if (error)
948				goto exit;
949
950			ctlbuf += FREEBSD32_ALIGN(copylen);
951			len    -= FREEBSD32_ALIGN(copylen);
952
953			if (len <= 0)
954				break;
955
956			/* Copy data */
957			copylen = datalen;
958			if (len < copylen) {
959				msg->msg_flags |= MSG_CTRUNC;
960				copylen = len;
961			}
962
963			error = copyout(data,ctlbuf,copylen);
964			if (error)
965				goto exit;
966
967			ctlbuf += FREEBSD32_ALIGN(copylen);
968			len    -= FREEBSD32_ALIGN(copylen);
969
970			if (CMSG_SPACE(datalen) < clen) {
971				clen -= CMSG_SPACE(datalen);
972				cm = (struct cmsghdr *)
973					((caddr_t)cm + CMSG_SPACE(datalen));
974			} else {
975				clen = 0;
976				cm = NULL;
977			}
978		}
979		m = m->m_next;
980	}
981
982	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
983
984exit:
985	return (error);
986
987}
988
989int
990freebsd32_recvmsg(td, uap)
991	struct thread *td;
992	struct freebsd32_recvmsg_args /* {
993		int	s;
994		struct	msghdr32 *msg;
995		int	flags;
996	} */ *uap;
997{
998	struct msghdr msg;
999	struct msghdr32 m32;
1000	struct iovec *uiov, *iov;
1001	struct mbuf *control = NULL;
1002	struct mbuf **controlp;
1003
1004	int error;
1005	error = copyin(uap->msg, &m32, sizeof(m32));
1006	if (error)
1007		return (error);
1008	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1009	if (error)
1010		return (error);
1011	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1012	    EMSGSIZE);
1013	if (error)
1014		return (error);
1015	msg.msg_flags = uap->flags;
1016	uiov = msg.msg_iov;
1017	msg.msg_iov = iov;
1018
1019	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1020	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
1021	if (error == 0) {
1022		msg.msg_iov = uiov;
1023
1024		if (control != NULL)
1025			error = freebsd32_copy_msg_out(&msg, control);
1026
1027		if (error == 0)
1028			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1029	}
1030	free(iov, M_IOV);
1031
1032	if (control != NULL)
1033		m_freem(control);
1034
1035	return (error);
1036}
1037
1038
1039static int
1040freebsd32_convert_msg_in(struct mbuf **controlp)
1041{
1042	struct mbuf *control = *controlp;
1043	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1044	void *data;
1045	socklen_t clen = control->m_len, datalen;
1046	int error;
1047
1048	error = 0;
1049	*controlp = NULL;
1050
1051	while (cm != NULL) {
1052		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1053			error = EINVAL;
1054			break;
1055		}
1056
1057		data = FREEBSD32_CMSG_DATA(cm);
1058		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1059
1060		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1061		    cm->cmsg_level);
1062		controlp = &(*controlp)->m_next;
1063
1064		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1065			clen -= FREEBSD32_CMSG_SPACE(datalen);
1066			cm = (struct cmsghdr *)
1067				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1068		} else {
1069			clen = 0;
1070			cm = NULL;
1071		}
1072	}
1073
1074	m_freem(control);
1075	return (error);
1076}
1077
1078
1079int
1080freebsd32_sendmsg(struct thread *td,
1081		  struct freebsd32_sendmsg_args *uap)
1082{
1083	struct msghdr msg;
1084	struct msghdr32 m32;
1085	struct iovec *iov;
1086	struct mbuf *control = NULL;
1087	struct sockaddr *to = NULL;
1088	int error;
1089
1090	error = copyin(uap->msg, &m32, sizeof(m32));
1091	if (error)
1092		return (error);
1093	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1094	if (error)
1095		return (error);
1096	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1097	    EMSGSIZE);
1098	if (error)
1099		return (error);
1100	msg.msg_iov = iov;
1101	if (msg.msg_name != NULL) {
1102		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1103		if (error) {
1104			to = NULL;
1105			goto out;
1106		}
1107		msg.msg_name = to;
1108	}
1109
1110	if (msg.msg_control) {
1111		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1112			error = EINVAL;
1113			goto out;
1114		}
1115
1116		error = sockargs(&control, msg.msg_control,
1117		    msg.msg_controllen, MT_CONTROL);
1118		if (error)
1119			goto out;
1120
1121		error = freebsd32_convert_msg_in(&control);
1122		if (error)
1123			goto out;
1124	}
1125
1126	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1127	    UIO_USERSPACE);
1128
1129out:
1130	free(iov, M_IOV);
1131	if (to)
1132		free(to, M_SONAME);
1133	return (error);
1134}
1135
1136int
1137freebsd32_recvfrom(struct thread *td,
1138		   struct freebsd32_recvfrom_args *uap)
1139{
1140	struct msghdr msg;
1141	struct iovec aiov;
1142	int error;
1143
1144	if (uap->fromlenaddr) {
1145		error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
1146		    sizeof(msg.msg_namelen));
1147		if (error)
1148			return (error);
1149	} else {
1150		msg.msg_namelen = 0;
1151	}
1152
1153	msg.msg_name = PTRIN(uap->from);
1154	msg.msg_iov = &aiov;
1155	msg.msg_iovlen = 1;
1156	aiov.iov_base = PTRIN(uap->buf);
1157	aiov.iov_len = uap->len;
1158	msg.msg_control = NULL;
1159	msg.msg_flags = uap->flags;
1160	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
1161	if (error == 0 && uap->fromlenaddr)
1162		error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
1163		    sizeof (msg.msg_namelen));
1164	return (error);
1165}
1166
1167int
1168freebsd32_settimeofday(struct thread *td,
1169		       struct freebsd32_settimeofday_args *uap)
1170{
1171	struct timeval32 tv32;
1172	struct timeval tv, *tvp;
1173	struct timezone tz, *tzp;
1174	int error;
1175
1176	if (uap->tv) {
1177		error = copyin(uap->tv, &tv32, sizeof(tv32));
1178		if (error)
1179			return (error);
1180		CP(tv32, tv, tv_sec);
1181		CP(tv32, tv, tv_usec);
1182		tvp = &tv;
1183	} else
1184		tvp = NULL;
1185	if (uap->tzp) {
1186		error = copyin(uap->tzp, &tz, sizeof(tz));
1187		if (error)
1188			return (error);
1189		tzp = &tz;
1190	} else
1191		tzp = NULL;
1192	return (kern_settimeofday(td, tvp, tzp));
1193}
1194
1195int
1196freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1197{
1198	struct timeval32 s32[2];
1199	struct timeval s[2], *sp;
1200	int error;
1201
1202	if (uap->tptr != NULL) {
1203		error = copyin(uap->tptr, s32, sizeof(s32));
1204		if (error)
1205			return (error);
1206		CP(s32[0], s[0], tv_sec);
1207		CP(s32[0], s[0], tv_usec);
1208		CP(s32[1], s[1], tv_sec);
1209		CP(s32[1], s[1], tv_usec);
1210		sp = s;
1211	} else
1212		sp = NULL;
1213	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1214}
1215
1216int
1217freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
1218{
1219	struct timeval32 s32[2];
1220	struct timeval s[2], *sp;
1221	int error;
1222
1223	if (uap->tptr != NULL) {
1224		error = copyin(uap->tptr, s32, sizeof(s32));
1225		if (error)
1226			return (error);
1227		CP(s32[0], s[0], tv_sec);
1228		CP(s32[0], s[0], tv_usec);
1229		CP(s32[1], s[1], tv_sec);
1230		CP(s32[1], s[1], tv_usec);
1231		sp = s;
1232	} else
1233		sp = NULL;
1234	return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1235}
1236
1237int
1238freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1239{
1240	struct timeval32 s32[2];
1241	struct timeval s[2], *sp;
1242	int error;
1243
1244	if (uap->tptr != NULL) {
1245		error = copyin(uap->tptr, s32, sizeof(s32));
1246		if (error)
1247			return (error);
1248		CP(s32[0], s[0], tv_sec);
1249		CP(s32[0], s[0], tv_usec);
1250		CP(s32[1], s[1], tv_sec);
1251		CP(s32[1], s[1], tv_usec);
1252		sp = s;
1253	} else
1254		sp = NULL;
1255	return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1256}
1257
1258int
1259freebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)
1260{
1261	struct timeval32 s32[2];
1262	struct timeval s[2], *sp;
1263	int error;
1264
1265	if (uap->times != NULL) {
1266		error = copyin(uap->times, s32, sizeof(s32));
1267		if (error)
1268			return (error);
1269		CP(s32[0], s[0], tv_sec);
1270		CP(s32[0], s[0], tv_usec);
1271		CP(s32[1], s[1], tv_sec);
1272		CP(s32[1], s[1], tv_usec);
1273		sp = s;
1274	} else
1275		sp = NULL;
1276	return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,
1277		sp, UIO_SYSSPACE));
1278}
1279
1280int
1281freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1282{
1283	struct timeval32 tv32;
1284	struct timeval delta, olddelta, *deltap;
1285	int error;
1286
1287	if (uap->delta) {
1288		error = copyin(uap->delta, &tv32, sizeof(tv32));
1289		if (error)
1290			return (error);
1291		CP(tv32, delta, tv_sec);
1292		CP(tv32, delta, tv_usec);
1293		deltap = &delta;
1294	} else
1295		deltap = NULL;
1296	error = kern_adjtime(td, deltap, &olddelta);
1297	if (uap->olddelta && error == 0) {
1298		CP(olddelta, tv32, tv_sec);
1299		CP(olddelta, tv32, tv_usec);
1300		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1301	}
1302	return (error);
1303}
1304
1305#ifdef COMPAT_FREEBSD4
1306int
1307freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1308{
1309	struct statfs32 s32;
1310	struct statfs s;
1311	int error;
1312
1313	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1314	if (error)
1315		return (error);
1316	copy_statfs(&s, &s32);
1317	return (copyout(&s32, uap->buf, sizeof(s32)));
1318}
1319#endif
1320
1321#ifdef COMPAT_FREEBSD4
1322int
1323freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1324{
1325	struct statfs32 s32;
1326	struct statfs s;
1327	int error;
1328
1329	error = kern_fstatfs(td, uap->fd, &s);
1330	if (error)
1331		return (error);
1332	copy_statfs(&s, &s32);
1333	return (copyout(&s32, uap->buf, sizeof(s32)));
1334}
1335#endif
1336
1337#ifdef COMPAT_FREEBSD4
1338int
1339freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1340{
1341	struct statfs32 s32;
1342	struct statfs s;
1343	fhandle_t fh;
1344	int error;
1345
1346	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1347		return (error);
1348	error = kern_fhstatfs(td, fh, &s);
1349	if (error)
1350		return (error);
1351	copy_statfs(&s, &s32);
1352	return (copyout(&s32, uap->buf, sizeof(s32)));
1353}
1354#endif
1355
1356static void
1357freebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip)
1358{
1359
1360	CP(*ip32, *ip, cuid);
1361	CP(*ip32, *ip, cgid);
1362	CP(*ip32, *ip, uid);
1363	CP(*ip32, *ip, gid);
1364	CP(*ip32, *ip, mode);
1365	CP(*ip32, *ip, seq);
1366	CP(*ip32, *ip, key);
1367}
1368
1369static void
1370freebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32)
1371{
1372
1373	CP(*ip, *ip32, cuid);
1374	CP(*ip, *ip32, cgid);
1375	CP(*ip, *ip32, uid);
1376	CP(*ip, *ip32, gid);
1377	CP(*ip, *ip32, mode);
1378	CP(*ip, *ip32, seq);
1379	CP(*ip, *ip32, key);
1380}
1381
1382int
1383freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1384{
1385
1386	switch (uap->which) {
1387	case 0:
1388		return (freebsd32_semctl(td,
1389		    (struct freebsd32_semctl_args *)&uap->a2));
1390	default:
1391		return (semsys(td, (struct semsys_args *)uap));
1392	}
1393}
1394
1395int
1396freebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap)
1397{
1398	struct semid_ds32 dsbuf32;
1399	struct semid_ds dsbuf;
1400	union semun semun;
1401	union semun32 arg;
1402	register_t rval;
1403	int error;
1404
1405	switch (uap->cmd) {
1406	case SEM_STAT:
1407	case IPC_SET:
1408	case IPC_STAT:
1409	case GETALL:
1410	case SETVAL:
1411	case SETALL:
1412		error = copyin(uap->arg, &arg, sizeof(arg));
1413		if (error)
1414			return (error);
1415		break;
1416	}
1417
1418	switch (uap->cmd) {
1419	case SEM_STAT:
1420	case IPC_STAT:
1421		semun.buf = &dsbuf;
1422		break;
1423	case IPC_SET:
1424		error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
1425		if (error)
1426			return (error);
1427		freebsd32_ipcperm_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
1428		PTRIN_CP(dsbuf32, dsbuf, sem_base);
1429		CP(dsbuf32, dsbuf, sem_nsems);
1430		CP(dsbuf32, dsbuf, sem_otime);
1431		CP(dsbuf32, dsbuf, sem_pad1);
1432		CP(dsbuf32, dsbuf, sem_ctime);
1433		CP(dsbuf32, dsbuf, sem_pad2);
1434		CP(dsbuf32, dsbuf, sem_pad3[0]);
1435		CP(dsbuf32, dsbuf, sem_pad3[1]);
1436		CP(dsbuf32, dsbuf, sem_pad3[2]);
1437		CP(dsbuf32, dsbuf, sem_pad3[3]);
1438		semun.buf = &dsbuf;
1439		break;
1440	case GETALL:
1441	case SETALL:
1442		semun.array = PTRIN(arg.array);
1443		break;
1444	case SETVAL:
1445		semun.val = arg.val;
1446		break;
1447	}
1448
1449	error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
1450	    &rval);
1451	if (error)
1452		return (error);
1453
1454	switch (uap->cmd) {
1455	case SEM_STAT:
1456	case IPC_STAT:
1457		freebsd32_ipcperm_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
1458		PTROUT_CP(dsbuf, dsbuf32, sem_base);
1459		CP(dsbuf, dsbuf32, sem_nsems);
1460		CP(dsbuf, dsbuf32, sem_otime);
1461		CP(dsbuf, dsbuf32, sem_pad1);
1462		CP(dsbuf, dsbuf32, sem_ctime);
1463		CP(dsbuf, dsbuf32, sem_pad2);
1464		CP(dsbuf, dsbuf32, sem_pad3[0]);
1465		CP(dsbuf, dsbuf32, sem_pad3[1]);
1466		CP(dsbuf, dsbuf32, sem_pad3[2]);
1467		CP(dsbuf, dsbuf32, sem_pad3[3]);
1468		error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
1469		break;
1470	}
1471
1472	if (error == 0)
1473		td->td_retval[0] = rval;
1474	return (error);
1475}
1476
1477int
1478freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1479{
1480
1481	switch (uap->which) {
1482	case 0:
1483		return (freebsd32_msgctl(td,
1484		    (struct freebsd32_msgctl_args *)&uap->a2));
1485	case 2:
1486		return (freebsd32_msgsnd(td,
1487		    (struct freebsd32_msgsnd_args *)&uap->a2));
1488	case 3:
1489		return (freebsd32_msgrcv(td,
1490		    (struct freebsd32_msgrcv_args *)&uap->a2));
1491	default:
1492		return (msgsys(td, (struct msgsys_args *)uap));
1493	}
1494}
1495
1496int
1497freebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap)
1498{
1499	struct msqid_ds msqbuf;
1500	struct msqid_ds32 msqbuf32;
1501	int error;
1502
1503	if (uap->cmd == IPC_SET) {
1504		error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
1505		if (error)
1506			return (error);
1507		freebsd32_ipcperm_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
1508		PTRIN_CP(msqbuf32, msqbuf, msg_first);
1509		PTRIN_CP(msqbuf32, msqbuf, msg_last);
1510		CP(msqbuf32, msqbuf, msg_cbytes);
1511		CP(msqbuf32, msqbuf, msg_qnum);
1512		CP(msqbuf32, msqbuf, msg_qbytes);
1513		CP(msqbuf32, msqbuf, msg_lspid);
1514		CP(msqbuf32, msqbuf, msg_lrpid);
1515		CP(msqbuf32, msqbuf, msg_stime);
1516		CP(msqbuf32, msqbuf, msg_pad1);
1517		CP(msqbuf32, msqbuf, msg_rtime);
1518		CP(msqbuf32, msqbuf, msg_pad2);
1519		CP(msqbuf32, msqbuf, msg_ctime);
1520		CP(msqbuf32, msqbuf, msg_pad3);
1521		CP(msqbuf32, msqbuf, msg_pad4[0]);
1522		CP(msqbuf32, msqbuf, msg_pad4[1]);
1523		CP(msqbuf32, msqbuf, msg_pad4[2]);
1524		CP(msqbuf32, msqbuf, msg_pad4[3]);
1525	}
1526	error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1527	if (error)
1528		return (error);
1529	if (uap->cmd == IPC_STAT) {
1530		freebsd32_ipcperm_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
1531		PTROUT_CP(msqbuf, msqbuf32, msg_first);
1532		PTROUT_CP(msqbuf, msqbuf32, msg_last);
1533		CP(msqbuf, msqbuf32, msg_cbytes);
1534		CP(msqbuf, msqbuf32, msg_qnum);
1535		CP(msqbuf, msqbuf32, msg_qbytes);
1536		CP(msqbuf, msqbuf32, msg_lspid);
1537		CP(msqbuf, msqbuf32, msg_lrpid);
1538		CP(msqbuf, msqbuf32, msg_stime);
1539		CP(msqbuf, msqbuf32, msg_pad1);
1540		CP(msqbuf, msqbuf32, msg_rtime);
1541		CP(msqbuf, msqbuf32, msg_pad2);
1542		CP(msqbuf, msqbuf32, msg_ctime);
1543		CP(msqbuf, msqbuf32, msg_pad3);
1544		CP(msqbuf, msqbuf32, msg_pad4[0]);
1545		CP(msqbuf, msqbuf32, msg_pad4[1]);
1546		CP(msqbuf, msqbuf32, msg_pad4[2]);
1547		CP(msqbuf, msqbuf32, msg_pad4[3]);
1548		error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
1549	}
1550	return (error);
1551}
1552
1553int
1554freebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap)
1555{
1556	const void *msgp;
1557	long mtype;
1558	int32_t mtype32;
1559	int error;
1560
1561	msgp = PTRIN(uap->msgp);
1562	if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0)
1563		return (error);
1564	mtype = mtype32;
1565	return (kern_msgsnd(td, uap->msqid,
1566	    (const char *)msgp + sizeof(mtype32),
1567	    uap->msgsz, uap->msgflg, mtype));
1568}
1569
1570int
1571freebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap)
1572{
1573	void *msgp;
1574	long mtype;
1575	int32_t mtype32;
1576	int error;
1577
1578	msgp = PTRIN(uap->msgp);
1579	if ((error = kern_msgrcv(td, uap->msqid,
1580	    (char *)msgp + sizeof(mtype32), uap->msgsz,
1581	    uap->msgtyp, uap->msgflg, &mtype)) != 0)
1582		return (error);
1583	mtype32 = (int32_t)mtype;
1584	return (copyout(&mtype32, msgp, sizeof(mtype32)));
1585}
1586
1587int
1588freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1589{
1590
1591	switch (uap->which) {
1592	case 0:	{	/* shmat */
1593		struct shmat_args ap;
1594
1595		ap.shmid = uap->a2;
1596		ap.shmaddr = PTRIN(uap->a3);
1597		ap.shmflg = uap->a4;
1598		return (sysent[SYS_shmat].sy_call(td, &ap));
1599	}
1600	case 2: {	/* shmdt */
1601		struct shmdt_args ap;
1602
1603		ap.shmaddr = PTRIN(uap->a2);
1604		return (sysent[SYS_shmdt].sy_call(td, &ap));
1605	}
1606	case 3: {	/* shmget */
1607		struct shmget_args ap;
1608
1609		ap.key = uap->a2;
1610		ap.size = uap->a3;
1611		ap.shmflg = uap->a4;
1612		return (sysent[SYS_shmget].sy_call(td, &ap));
1613	}
1614	case 4: {	/* shmctl */
1615		struct freebsd32_shmctl_args ap;
1616
1617		ap.shmid = uap->a2;
1618		ap.cmd = uap->a3;
1619		ap.buf = PTRIN(uap->a4);
1620		return (freebsd32_shmctl(td, &ap));
1621	}
1622	case 1:		/* oshmctl */
1623	default:
1624		return (EINVAL);
1625	}
1626}
1627
1628int
1629freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
1630{
1631	int error = 0;
1632	union {
1633		struct shmid_ds shmid_ds;
1634		struct shm_info shm_info;
1635		struct shminfo shminfo;
1636	} u;
1637	union {
1638		struct shmid_ds32 shmid_ds32;
1639		struct shm_info32 shm_info32;
1640		struct shminfo32 shminfo32;
1641	} u32;
1642	size_t sz;
1643
1644	if (uap->cmd == IPC_SET) {
1645		if ((error = copyin(uap->buf, &u32.shmid_ds32,
1646		    sizeof(u32.shmid_ds32))))
1647			goto done;
1648		freebsd32_ipcperm_in(&u32.shmid_ds32.shm_perm,
1649		    &u.shmid_ds.shm_perm);
1650		CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1651		CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1652		CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1653		CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1654		CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1655		CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1656		CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1657		PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal);
1658	}
1659
1660	error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1661	if (error)
1662		goto done;
1663
1664	/* Cases in which we need to copyout */
1665	switch (uap->cmd) {
1666	case IPC_INFO:
1667		CP(u.shminfo, u32.shminfo32, shmmax);
1668		CP(u.shminfo, u32.shminfo32, shmmin);
1669		CP(u.shminfo, u32.shminfo32, shmmni);
1670		CP(u.shminfo, u32.shminfo32, shmseg);
1671		CP(u.shminfo, u32.shminfo32, shmall);
1672		error = copyout(&u32.shminfo32, uap->buf,
1673		    sizeof(u32.shminfo32));
1674		break;
1675	case SHM_INFO:
1676		CP(u.shm_info, u32.shm_info32, used_ids);
1677		CP(u.shm_info, u32.shm_info32, shm_rss);
1678		CP(u.shm_info, u32.shm_info32, shm_tot);
1679		CP(u.shm_info, u32.shm_info32, shm_swp);
1680		CP(u.shm_info, u32.shm_info32, swap_attempts);
1681		CP(u.shm_info, u32.shm_info32, swap_successes);
1682		error = copyout(&u32.shm_info32, uap->buf,
1683		    sizeof(u32.shm_info32));
1684		break;
1685	case SHM_STAT:
1686	case IPC_STAT:
1687		freebsd32_ipcperm_out(&u.shmid_ds.shm_perm,
1688		    &u32.shmid_ds32.shm_perm);
1689		CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1690		CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1691		CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1692		CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1693		CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1694		CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1695		CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1696		PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal);
1697		error = copyout(&u32.shmid_ds32, uap->buf,
1698		    sizeof(u32.shmid_ds32));
1699		break;
1700	}
1701
1702done:
1703	if (error) {
1704		/* Invalidate the return value */
1705		td->td_retval[0] = -1;
1706	}
1707	return (error);
1708}
1709
1710int
1711freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1712{
1713	struct pread_args ap;
1714
1715	ap.fd = uap->fd;
1716	ap.buf = uap->buf;
1717	ap.nbyte = uap->nbyte;
1718	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1719	return (pread(td, &ap));
1720}
1721
1722int
1723freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1724{
1725	struct pwrite_args ap;
1726
1727	ap.fd = uap->fd;
1728	ap.buf = uap->buf;
1729	ap.nbyte = uap->nbyte;
1730	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1731	return (pwrite(td, &ap));
1732}
1733
1734int
1735freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1736{
1737	int error;
1738	struct lseek_args ap;
1739	off_t pos;
1740
1741	ap.fd = uap->fd;
1742	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1743	ap.whence = uap->whence;
1744	error = lseek(td, &ap);
1745	/* Expand the quad return into two parts for eax and edx */
1746	pos = *(off_t *)(td->td_retval);
1747	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1748	td->td_retval[1] = pos >> 32;		/* %edx */
1749	return error;
1750}
1751
1752int
1753freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1754{
1755	struct truncate_args ap;
1756
1757	ap.path = uap->path;
1758	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1759	return (truncate(td, &ap));
1760}
1761
1762int
1763freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1764{
1765	struct ftruncate_args ap;
1766
1767	ap.fd = uap->fd;
1768	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1769	return (ftruncate(td, &ap));
1770}
1771
1772int
1773freebsd32_getdirentries(struct thread *td,
1774    struct freebsd32_getdirentries_args *uap)
1775{
1776	long base;
1777	int32_t base32;
1778	int error;
1779
1780	error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base);
1781	if (error)
1782		return (error);
1783	if (uap->basep != NULL) {
1784		base32 = base;
1785		error = copyout(&base32, uap->basep, sizeof(int32_t));
1786	}
1787	return (error);
1788}
1789
1790#ifdef COMPAT_FREEBSD6
1791/* versions with the 'int pad' argument */
1792int
1793freebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap)
1794{
1795	struct pread_args ap;
1796
1797	ap.fd = uap->fd;
1798	ap.buf = uap->buf;
1799	ap.nbyte = uap->nbyte;
1800	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1801	return (pread(td, &ap));
1802}
1803
1804int
1805freebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap)
1806{
1807	struct pwrite_args ap;
1808
1809	ap.fd = uap->fd;
1810	ap.buf = uap->buf;
1811	ap.nbyte = uap->nbyte;
1812	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1813	return (pwrite(td, &ap));
1814}
1815
1816int
1817freebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap)
1818{
1819	int error;
1820	struct lseek_args ap;
1821	off_t pos;
1822
1823	ap.fd = uap->fd;
1824	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1825	ap.whence = uap->whence;
1826	error = lseek(td, &ap);
1827	/* Expand the quad return into two parts for eax and edx */
1828	pos = *(off_t *)(td->td_retval);
1829	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1830	td->td_retval[1] = pos >> 32;		/* %edx */
1831	return error;
1832}
1833
1834int
1835freebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap)
1836{
1837	struct truncate_args ap;
1838
1839	ap.path = uap->path;
1840	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1841	return (truncate(td, &ap));
1842}
1843
1844int
1845freebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap)
1846{
1847	struct ftruncate_args ap;
1848
1849	ap.fd = uap->fd;
1850	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1851	return (ftruncate(td, &ap));
1852}
1853#endif /* COMPAT_FREEBSD6 */
1854
1855struct sf_hdtr32 {
1856	uint32_t headers;
1857	int hdr_cnt;
1858	uint32_t trailers;
1859	int trl_cnt;
1860};
1861
1862static int
1863freebsd32_do_sendfile(struct thread *td,
1864    struct freebsd32_sendfile_args *uap, int compat)
1865{
1866	struct sendfile_args ap;
1867	struct sf_hdtr32 hdtr32;
1868	struct sf_hdtr hdtr;
1869	struct uio *hdr_uio, *trl_uio;
1870	struct iovec32 *iov32;
1871	int error;
1872
1873	hdr_uio = trl_uio = NULL;
1874
1875	ap.fd = uap->fd;
1876	ap.s = uap->s;
1877	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1878	ap.nbytes = uap->nbytes;
1879	ap.hdtr = (struct sf_hdtr *)uap->hdtr;		/* XXX not used */
1880	ap.sbytes = uap->sbytes;
1881	ap.flags = uap->flags;
1882
1883	if (uap->hdtr != NULL) {
1884		error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
1885		if (error)
1886			goto out;
1887		PTRIN_CP(hdtr32, hdtr, headers);
1888		CP(hdtr32, hdtr, hdr_cnt);
1889		PTRIN_CP(hdtr32, hdtr, trailers);
1890		CP(hdtr32, hdtr, trl_cnt);
1891
1892		if (hdtr.headers != NULL) {
1893			iov32 = PTRIN(hdtr32.headers);
1894			error = freebsd32_copyinuio(iov32,
1895			    hdtr32.hdr_cnt, &hdr_uio);
1896			if (error)
1897				goto out;
1898		}
1899		if (hdtr.trailers != NULL) {
1900			iov32 = PTRIN(hdtr32.trailers);
1901			error = freebsd32_copyinuio(iov32,
1902			    hdtr32.trl_cnt, &trl_uio);
1903			if (error)
1904				goto out;
1905		}
1906	}
1907
1908	error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
1909out:
1910	if (hdr_uio)
1911		free(hdr_uio, M_IOV);
1912	if (trl_uio)
1913		free(trl_uio, M_IOV);
1914	return (error);
1915}
1916
1917#ifdef COMPAT_FREEBSD4
1918int
1919freebsd4_freebsd32_sendfile(struct thread *td,
1920    struct freebsd4_freebsd32_sendfile_args *uap)
1921{
1922	return (freebsd32_do_sendfile(td,
1923	    (struct freebsd32_sendfile_args *)uap, 1));
1924}
1925#endif
1926
1927int
1928freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1929{
1930
1931	return (freebsd32_do_sendfile(td, uap, 0));
1932}
1933
1934static void
1935copy_stat( struct stat *in, struct stat32 *out)
1936{
1937	CP(*in, *out, st_dev);
1938	CP(*in, *out, st_ino);
1939	CP(*in, *out, st_mode);
1940	CP(*in, *out, st_nlink);
1941	CP(*in, *out, st_uid);
1942	CP(*in, *out, st_gid);
1943	CP(*in, *out, st_rdev);
1944	TS_CP(*in, *out, st_atimespec);
1945	TS_CP(*in, *out, st_mtimespec);
1946	TS_CP(*in, *out, st_ctimespec);
1947	CP(*in, *out, st_size);
1948	CP(*in, *out, st_blocks);
1949	CP(*in, *out, st_blksize);
1950	CP(*in, *out, st_flags);
1951	CP(*in, *out, st_gen);
1952}
1953
1954int
1955freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1956{
1957	struct stat sb;
1958	struct stat32 sb32;
1959	int error;
1960
1961	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1962	if (error)
1963		return (error);
1964	copy_stat(&sb, &sb32);
1965	error = copyout(&sb32, uap->ub, sizeof (sb32));
1966	return (error);
1967}
1968
1969int
1970freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1971{
1972	struct stat ub;
1973	struct stat32 ub32;
1974	int error;
1975
1976	error = kern_fstat(td, uap->fd, &ub);
1977	if (error)
1978		return (error);
1979	copy_stat(&ub, &ub32);
1980	error = copyout(&ub32, uap->ub, sizeof(ub32));
1981	return (error);
1982}
1983
1984int
1985freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
1986{
1987	struct stat ub;
1988	struct stat32 ub32;
1989	int error;
1990
1991	error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE, &ub);
1992	if (error)
1993		return (error);
1994	copy_stat(&ub, &ub32);
1995	error = copyout(&ub32, uap->buf, sizeof(ub32));
1996	return (error);
1997}
1998
1999int
2000freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
2001{
2002	struct stat sb;
2003	struct stat32 sb32;
2004	int error;
2005
2006	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2007	if (error)
2008		return (error);
2009	copy_stat(&sb, &sb32);
2010	error = copyout(&sb32, uap->ub, sizeof (sb32));
2011	return (error);
2012}
2013
2014/*
2015 * MPSAFE
2016 */
2017int
2018freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
2019{
2020	int error, name[CTL_MAXNAME];
2021	size_t j, oldlen;
2022
2023	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
2024		return (EINVAL);
2025 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
2026 	if (error)
2027		return (error);
2028	if (uap->oldlenp)
2029		oldlen = fuword32(uap->oldlenp);
2030	else
2031		oldlen = 0;
2032	error = userland_sysctl(td, name, uap->namelen,
2033		uap->old, &oldlen, 1,
2034		uap->new, uap->newlen, &j, SCTL_MASK32);
2035	if (error && error != ENOMEM)
2036		return (error);
2037	if (uap->oldlenp)
2038		suword32(uap->oldlenp, j);
2039	return (0);
2040}
2041
2042int
2043freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
2044{
2045	uint32_t version;
2046	int error;
2047	struct jail j;
2048
2049	error = copyin(uap->jail, &version, sizeof(uint32_t));
2050	if (error)
2051		return (error);
2052
2053	switch (version) {
2054	case 0:
2055	{
2056		/* FreeBSD single IPv4 jails. */
2057		struct jail32_v0 j32_v0;
2058
2059		bzero(&j, sizeof(struct jail));
2060		error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));
2061		if (error)
2062			return (error);
2063		CP(j32_v0, j, version);
2064		PTRIN_CP(j32_v0, j, path);
2065		PTRIN_CP(j32_v0, j, hostname);
2066		j.ip4s = j32_v0.ip_number;
2067		break;
2068	}
2069
2070	case 1:
2071		/*
2072		 * Version 1 was used by multi-IPv4 jail implementations
2073		 * that never made it into the official kernel.
2074		 */
2075		return (EINVAL);
2076
2077	case 2:	/* JAIL_API_VERSION */
2078	{
2079		/* FreeBSD multi-IPv4/IPv6,noIP jails. */
2080		struct jail32 j32;
2081
2082		error = copyin(uap->jail, &j32, sizeof(struct jail32));
2083		if (error)
2084			return (error);
2085		CP(j32, j, version);
2086		PTRIN_CP(j32, j, path);
2087		PTRIN_CP(j32, j, hostname);
2088		PTRIN_CP(j32, j, jailname);
2089		CP(j32, j, ip4s);
2090		CP(j32, j, ip6s);
2091		PTRIN_CP(j32, j, ip4);
2092		PTRIN_CP(j32, j, ip6);
2093		break;
2094	}
2095
2096	default:
2097		/* Sci-Fi jails are not supported, sorry. */
2098		return (EINVAL);
2099	}
2100	return (kern_jail(td, &j));
2101}
2102
2103int
2104freebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)
2105{
2106	struct uio *auio;
2107	int error;
2108
2109	/* Check that we have an even number of iovecs. */
2110	if (uap->iovcnt & 1)
2111		return (EINVAL);
2112
2113	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2114	if (error)
2115		return (error);
2116	error = kern_jail_set(td, auio, uap->flags);
2117	free(auio, M_IOV);
2118	return (error);
2119}
2120
2121int
2122freebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)
2123{
2124	struct iovec32 iov32;
2125	struct uio *auio;
2126	int error, i;
2127
2128	/* Check that we have an even number of iovecs. */
2129	if (uap->iovcnt & 1)
2130		return (EINVAL);
2131
2132	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2133	if (error)
2134		return (error);
2135	error = kern_jail_get(td, auio, uap->flags);
2136	if (error == 0)
2137		for (i = 0; i < uap->iovcnt; i++) {
2138			PTROUT_CP(auio->uio_iov[i], iov32, iov_base);
2139			CP(auio->uio_iov[i], iov32, iov_len);
2140			error = copyout(&iov32, uap->iovp + i, sizeof(iov32));
2141			if (error != 0)
2142				break;
2143		}
2144	free(auio, M_IOV);
2145	return (error);
2146}
2147
2148int
2149freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
2150{
2151	struct sigaction32 s32;
2152	struct sigaction sa, osa, *sap;
2153	int error;
2154
2155	if (uap->act) {
2156		error = copyin(uap->act, &s32, sizeof(s32));
2157		if (error)
2158			return (error);
2159		sa.sa_handler = PTRIN(s32.sa_u);
2160		CP(s32, sa, sa_flags);
2161		CP(s32, sa, sa_mask);
2162		sap = &sa;
2163	} else
2164		sap = NULL;
2165	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
2166	if (error == 0 && uap->oact != NULL) {
2167		s32.sa_u = PTROUT(osa.sa_handler);
2168		CP(osa, s32, sa_flags);
2169		CP(osa, s32, sa_mask);
2170		error = copyout(&s32, uap->oact, sizeof(s32));
2171	}
2172	return (error);
2173}
2174
2175#ifdef COMPAT_FREEBSD4
2176int
2177freebsd4_freebsd32_sigaction(struct thread *td,
2178			     struct freebsd4_freebsd32_sigaction_args *uap)
2179{
2180	struct sigaction32 s32;
2181	struct sigaction sa, osa, *sap;
2182	int error;
2183
2184	if (uap->act) {
2185		error = copyin(uap->act, &s32, sizeof(s32));
2186		if (error)
2187			return (error);
2188		sa.sa_handler = PTRIN(s32.sa_u);
2189		CP(s32, sa, sa_flags);
2190		CP(s32, sa, sa_mask);
2191		sap = &sa;
2192	} else
2193		sap = NULL;
2194	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
2195	if (error == 0 && uap->oact != NULL) {
2196		s32.sa_u = PTROUT(osa.sa_handler);
2197		CP(osa, s32, sa_flags);
2198		CP(osa, s32, sa_mask);
2199		error = copyout(&s32, uap->oact, sizeof(s32));
2200	}
2201	return (error);
2202}
2203#endif
2204
2205#ifdef COMPAT_43
2206struct osigaction32 {
2207	u_int32_t	sa_u;
2208	osigset_t	sa_mask;
2209	int		sa_flags;
2210};
2211
2212#define	ONSIG	32
2213
2214int
2215ofreebsd32_sigaction(struct thread *td,
2216			     struct ofreebsd32_sigaction_args *uap)
2217{
2218	struct osigaction32 s32;
2219	struct sigaction sa, osa, *sap;
2220	int error;
2221
2222	if (uap->signum <= 0 || uap->signum >= ONSIG)
2223		return (EINVAL);
2224
2225	if (uap->nsa) {
2226		error = copyin(uap->nsa, &s32, sizeof(s32));
2227		if (error)
2228			return (error);
2229		sa.sa_handler = PTRIN(s32.sa_u);
2230		CP(s32, sa, sa_flags);
2231		OSIG2SIG(s32.sa_mask, sa.sa_mask);
2232		sap = &sa;
2233	} else
2234		sap = NULL;
2235	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2236	if (error == 0 && uap->osa != NULL) {
2237		s32.sa_u = PTROUT(osa.sa_handler);
2238		CP(osa, s32, sa_flags);
2239		SIG2OSIG(osa.sa_mask, s32.sa_mask);
2240		error = copyout(&s32, uap->osa, sizeof(s32));
2241	}
2242	return (error);
2243}
2244
2245int
2246ofreebsd32_sigprocmask(struct thread *td,
2247			       struct ofreebsd32_sigprocmask_args *uap)
2248{
2249	sigset_t set, oset;
2250	int error;
2251
2252	OSIG2SIG(uap->mask, set);
2253	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
2254	SIG2OSIG(oset, td->td_retval[0]);
2255	return (error);
2256}
2257
2258int
2259ofreebsd32_sigpending(struct thread *td,
2260			      struct ofreebsd32_sigpending_args *uap)
2261{
2262	struct proc *p = td->td_proc;
2263	sigset_t siglist;
2264
2265	PROC_LOCK(p);
2266	siglist = p->p_siglist;
2267	SIGSETOR(siglist, td->td_siglist);
2268	PROC_UNLOCK(p);
2269	SIG2OSIG(siglist, td->td_retval[0]);
2270	return (0);
2271}
2272
2273struct sigvec32 {
2274	u_int32_t	sv_handler;
2275	int		sv_mask;
2276	int		sv_flags;
2277};
2278
2279int
2280ofreebsd32_sigvec(struct thread *td,
2281			  struct ofreebsd32_sigvec_args *uap)
2282{
2283	struct sigvec32 vec;
2284	struct sigaction sa, osa, *sap;
2285	int error;
2286
2287	if (uap->signum <= 0 || uap->signum >= ONSIG)
2288		return (EINVAL);
2289
2290	if (uap->nsv) {
2291		error = copyin(uap->nsv, &vec, sizeof(vec));
2292		if (error)
2293			return (error);
2294		sa.sa_handler = PTRIN(vec.sv_handler);
2295		OSIG2SIG(vec.sv_mask, sa.sa_mask);
2296		sa.sa_flags = vec.sv_flags;
2297		sa.sa_flags ^= SA_RESTART;
2298		sap = &sa;
2299	} else
2300		sap = NULL;
2301	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2302	if (error == 0 && uap->osv != NULL) {
2303		vec.sv_handler = PTROUT(osa.sa_handler);
2304		SIG2OSIG(osa.sa_mask, vec.sv_mask);
2305		vec.sv_flags = osa.sa_flags;
2306		vec.sv_flags &= ~SA_NOCLDWAIT;
2307		vec.sv_flags ^= SA_RESTART;
2308		error = copyout(&vec, uap->osv, sizeof(vec));
2309	}
2310	return (error);
2311}
2312
2313int
2314ofreebsd32_sigblock(struct thread *td,
2315			    struct ofreebsd32_sigblock_args *uap)
2316{
2317	struct proc *p = td->td_proc;
2318	sigset_t set;
2319
2320	OSIG2SIG(uap->mask, set);
2321	SIG_CANTMASK(set);
2322	PROC_LOCK(p);
2323	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2324	SIGSETOR(td->td_sigmask, set);
2325	PROC_UNLOCK(p);
2326	return (0);
2327}
2328
2329int
2330ofreebsd32_sigsetmask(struct thread *td,
2331			      struct ofreebsd32_sigsetmask_args *uap)
2332{
2333	struct proc *p = td->td_proc;
2334	sigset_t set;
2335
2336	OSIG2SIG(uap->mask, set);
2337	SIG_CANTMASK(set);
2338	PROC_LOCK(p);
2339	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2340	SIGSETLO(td->td_sigmask, set);
2341	signotify(td);
2342	PROC_UNLOCK(p);
2343	return (0);
2344}
2345
2346int
2347ofreebsd32_sigsuspend(struct thread *td,
2348			      struct ofreebsd32_sigsuspend_args *uap)
2349{
2350	struct proc *p = td->td_proc;
2351	sigset_t mask;
2352
2353	PROC_LOCK(p);
2354	td->td_oldsigmask = td->td_sigmask;
2355	td->td_pflags |= TDP_OLDMASK;
2356	OSIG2SIG(uap->mask, mask);
2357	SIG_CANTMASK(mask);
2358	SIGSETLO(td->td_sigmask, mask);
2359	signotify(td);
2360	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
2361		/* void */;
2362	PROC_UNLOCK(p);
2363	/* always return EINTR rather than ERESTART... */
2364	return (EINTR);
2365}
2366
2367struct sigstack32 {
2368	u_int32_t	ss_sp;
2369	int		ss_onstack;
2370};
2371
2372int
2373ofreebsd32_sigstack(struct thread *td,
2374			    struct ofreebsd32_sigstack_args *uap)
2375{
2376	struct sigstack32 s32;
2377	struct sigstack nss, oss;
2378	int error = 0, unss;
2379
2380	if (uap->nss != NULL) {
2381		error = copyin(uap->nss, &s32, sizeof(s32));
2382		if (error)
2383			return (error);
2384		nss.ss_sp = PTRIN(s32.ss_sp);
2385		CP(s32, nss, ss_onstack);
2386		unss = 1;
2387	} else {
2388		unss = 0;
2389	}
2390	oss.ss_sp = td->td_sigstk.ss_sp;
2391	oss.ss_onstack = sigonstack(cpu_getstack(td));
2392	if (unss) {
2393		td->td_sigstk.ss_sp = nss.ss_sp;
2394		td->td_sigstk.ss_size = 0;
2395		td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK);
2396		td->td_pflags |= TDP_ALTSTACK;
2397	}
2398	if (uap->oss != NULL) {
2399		s32.ss_sp = PTROUT(oss.ss_sp);
2400		CP(oss, s32, ss_onstack);
2401		error = copyout(&s32, uap->oss, sizeof(s32));
2402	}
2403	return (error);
2404}
2405#endif
2406
2407int
2408freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
2409{
2410	struct timespec32 rmt32, rqt32;
2411	struct timespec rmt, rqt;
2412	int error;
2413
2414	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
2415	if (error)
2416		return (error);
2417
2418	CP(rqt32, rqt, tv_sec);
2419	CP(rqt32, rqt, tv_nsec);
2420
2421	if (uap->rmtp &&
2422	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
2423		return (EFAULT);
2424	error = kern_nanosleep(td, &rqt, &rmt);
2425	if (error && uap->rmtp) {
2426		int error2;
2427
2428		CP(rmt, rmt32, tv_sec);
2429		CP(rmt, rmt32, tv_nsec);
2430
2431		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
2432		if (error2)
2433			error = error2;
2434	}
2435	return (error);
2436}
2437
2438int
2439freebsd32_clock_gettime(struct thread *td,
2440			struct freebsd32_clock_gettime_args *uap)
2441{
2442	struct timespec	ats;
2443	struct timespec32 ats32;
2444	int error;
2445
2446	error = kern_clock_gettime(td, uap->clock_id, &ats);
2447	if (error == 0) {
2448		CP(ats, ats32, tv_sec);
2449		CP(ats, ats32, tv_nsec);
2450		error = copyout(&ats32, uap->tp, sizeof(ats32));
2451	}
2452	return (error);
2453}
2454
2455int
2456freebsd32_clock_settime(struct thread *td,
2457			struct freebsd32_clock_settime_args *uap)
2458{
2459	struct timespec	ats;
2460	struct timespec32 ats32;
2461	int error;
2462
2463	error = copyin(uap->tp, &ats32, sizeof(ats32));
2464	if (error)
2465		return (error);
2466	CP(ats32, ats, tv_sec);
2467	CP(ats32, ats, tv_nsec);
2468
2469	return (kern_clock_settime(td, uap->clock_id, &ats));
2470}
2471
2472int
2473freebsd32_clock_getres(struct thread *td,
2474		       struct freebsd32_clock_getres_args *uap)
2475{
2476	struct timespec	ts;
2477	struct timespec32 ts32;
2478	int error;
2479
2480	if (uap->tp == NULL)
2481		return (0);
2482	error = kern_clock_getres(td, uap->clock_id, &ts);
2483	if (error == 0) {
2484		CP(ts, ts32, tv_sec);
2485		CP(ts, ts32, tv_nsec);
2486		error = copyout(&ts32, uap->tp, sizeof(ts32));
2487	}
2488	return (error);
2489}
2490
2491int
2492freebsd32_thr_new(struct thread *td,
2493		  struct freebsd32_thr_new_args *uap)
2494{
2495	struct thr_param32 param32;
2496	struct thr_param param;
2497	int error;
2498
2499	if (uap->param_size < 0 ||
2500	    uap->param_size > sizeof(struct thr_param32))
2501		return (EINVAL);
2502	bzero(&param, sizeof(struct thr_param));
2503	bzero(&param32, sizeof(struct thr_param32));
2504	error = copyin(uap->param, &param32, uap->param_size);
2505	if (error != 0)
2506		return (error);
2507	param.start_func = PTRIN(param32.start_func);
2508	param.arg = PTRIN(param32.arg);
2509	param.stack_base = PTRIN(param32.stack_base);
2510	param.stack_size = param32.stack_size;
2511	param.tls_base = PTRIN(param32.tls_base);
2512	param.tls_size = param32.tls_size;
2513	param.child_tid = PTRIN(param32.child_tid);
2514	param.parent_tid = PTRIN(param32.parent_tid);
2515	param.flags = param32.flags;
2516	param.rtp = PTRIN(param32.rtp);
2517	param.spare[0] = PTRIN(param32.spare[0]);
2518	param.spare[1] = PTRIN(param32.spare[1]);
2519	param.spare[2] = PTRIN(param32.spare[2]);
2520
2521	return (kern_thr_new(td, &param));
2522}
2523
2524int
2525freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
2526{
2527	struct timespec32 ts32;
2528	struct timespec ts, *tsp;
2529	int error;
2530
2531	error = 0;
2532	tsp = NULL;
2533	if (uap->timeout != NULL) {
2534		error = copyin((const void *)uap->timeout, (void *)&ts32,
2535		    sizeof(struct timespec32));
2536		if (error != 0)
2537			return (error);
2538		ts.tv_sec = ts32.tv_sec;
2539		ts.tv_nsec = ts32.tv_nsec;
2540		tsp = &ts;
2541	}
2542	return (kern_thr_suspend(td, tsp));
2543}
2544
2545void
2546siginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst)
2547{
2548	bzero(dst, sizeof(*dst));
2549	dst->si_signo = src->si_signo;
2550	dst->si_errno = src->si_errno;
2551	dst->si_code = src->si_code;
2552	dst->si_pid = src->si_pid;
2553	dst->si_uid = src->si_uid;
2554	dst->si_status = src->si_status;
2555	dst->si_addr = (uintptr_t)src->si_addr;
2556	dst->si_value.sigval_int = src->si_value.sival_int;
2557	dst->si_timerid = src->si_timerid;
2558	dst->si_overrun = src->si_overrun;
2559}
2560
2561int
2562freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
2563{
2564	struct timespec32 ts32;
2565	struct timespec ts;
2566	struct timespec *timeout;
2567	sigset_t set;
2568	ksiginfo_t ksi;
2569	struct siginfo32 si32;
2570	int error;
2571
2572	if (uap->timeout) {
2573		error = copyin(uap->timeout, &ts32, sizeof(ts32));
2574		if (error)
2575			return (error);
2576		ts.tv_sec = ts32.tv_sec;
2577		ts.tv_nsec = ts32.tv_nsec;
2578		timeout = &ts;
2579	} else
2580		timeout = NULL;
2581
2582	error = copyin(uap->set, &set, sizeof(set));
2583	if (error)
2584		return (error);
2585
2586	error = kern_sigtimedwait(td, set, &ksi, timeout);
2587	if (error)
2588		return (error);
2589
2590	if (uap->info) {
2591		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2592		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2593	}
2594
2595	if (error == 0)
2596		td->td_retval[0] = ksi.ksi_signo;
2597	return (error);
2598}
2599
2600/*
2601 * MPSAFE
2602 */
2603int
2604freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
2605{
2606	ksiginfo_t ksi;
2607	struct siginfo32 si32;
2608	sigset_t set;
2609	int error;
2610
2611	error = copyin(uap->set, &set, sizeof(set));
2612	if (error)
2613		return (error);
2614
2615	error = kern_sigtimedwait(td, set, &ksi, NULL);
2616	if (error)
2617		return (error);
2618
2619	if (uap->info) {
2620		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2621		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2622	}
2623	if (error == 0)
2624		td->td_retval[0] = ksi.ksi_signo;
2625	return (error);
2626}
2627
2628int
2629freebsd32_cpuset_setid(struct thread *td,
2630    struct freebsd32_cpuset_setid_args *uap)
2631{
2632	struct cpuset_setid_args ap;
2633
2634	ap.which = uap->which;
2635	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2636	ap.setid = uap->setid;
2637
2638	return (cpuset_setid(td, &ap));
2639}
2640
2641int
2642freebsd32_cpuset_getid(struct thread *td,
2643    struct freebsd32_cpuset_getid_args *uap)
2644{
2645	struct cpuset_getid_args ap;
2646
2647	ap.level = uap->level;
2648	ap.which = uap->which;
2649	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2650	ap.setid = uap->setid;
2651
2652	return (cpuset_getid(td, &ap));
2653}
2654
2655int
2656freebsd32_cpuset_getaffinity(struct thread *td,
2657    struct freebsd32_cpuset_getaffinity_args *uap)
2658{
2659	struct cpuset_getaffinity_args ap;
2660
2661	ap.level = uap->level;
2662	ap.which = uap->which;
2663	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2664	ap.cpusetsize = uap->cpusetsize;
2665	ap.mask = uap->mask;
2666
2667	return (cpuset_getaffinity(td, &ap));
2668}
2669
2670int
2671freebsd32_cpuset_setaffinity(struct thread *td,
2672    struct freebsd32_cpuset_setaffinity_args *uap)
2673{
2674	struct cpuset_setaffinity_args ap;
2675
2676	ap.level = uap->level;
2677	ap.which = uap->which;
2678	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2679	ap.cpusetsize = uap->cpusetsize;
2680	ap.mask = uap->mask;
2681
2682	return (cpuset_setaffinity(td, &ap));
2683}
2684
2685int
2686freebsd32_nmount(struct thread *td,
2687    struct freebsd32_nmount_args /* {
2688    	struct iovec *iovp;
2689    	unsigned int iovcnt;
2690    	int flags;
2691    } */ *uap)
2692{
2693	struct uio *auio;
2694	int error;
2695
2696	AUDIT_ARG(fflags, uap->flags);
2697
2698	/*
2699	 * Filter out MNT_ROOTFS.  We do not want clients of nmount() in
2700	 * userspace to set this flag, but we must filter it out if we want
2701	 * MNT_UPDATE on the root file system to work.
2702	 * MNT_ROOTFS should only be set in the kernel in vfs_mountroot_try().
2703	 */
2704	uap->flags &= ~MNT_ROOTFS;
2705
2706	/*
2707	 * check that we have an even number of iovec's
2708	 * and that we have at least two options.
2709	 */
2710	if ((uap->iovcnt & 1) || (uap->iovcnt < 4))
2711		return (EINVAL);
2712
2713	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2714	if (error)
2715		return (error);
2716	error = vfs_donmount(td, uap->flags, auio);
2717
2718	free(auio, M_IOV);
2719	return error;
2720}
2721
2722#if 0
2723int
2724freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
2725{
2726	struct yyy32 *p32, s32;
2727	struct yyy *p = NULL, s;
2728	struct xxx_arg ap;
2729	int error;
2730
2731	if (uap->zzz) {
2732		error = copyin(uap->zzz, &s32, sizeof(s32));
2733		if (error)
2734			return (error);
2735		/* translate in */
2736		p = &s;
2737	}
2738	error = kern_xxx(td, p);
2739	if (error)
2740		return (error);
2741	if (uap->zzz) {
2742		/* translate out */
2743		error = copyout(&s32, p32, sizeof(s32));
2744	}
2745	return (error);
2746}
2747#endif
2748
2749int
2750syscall32_register(int *offset, struct sysent *new_sysent,
2751    struct sysent *old_sysent)
2752{
2753	if (*offset == NO_SYSCALL) {
2754		int i;
2755
2756		for (i = 1; i < SYS_MAXSYSCALL; ++i)
2757			if (freebsd32_sysent[i].sy_call ==
2758			    (sy_call_t *)lkmnosys)
2759				break;
2760		if (i == SYS_MAXSYSCALL)
2761			return (ENFILE);
2762		*offset = i;
2763	} else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
2764		return (EINVAL);
2765	else if (freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
2766	    freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmressys)
2767		return (EEXIST);
2768
2769	*old_sysent = freebsd32_sysent[*offset];
2770	freebsd32_sysent[*offset] = *new_sysent;
2771	return 0;
2772}
2773
2774int
2775syscall32_deregister(int *offset, struct sysent *old_sysent)
2776{
2777
2778	if (*offset)
2779		freebsd32_sysent[*offset] = *old_sysent;
2780	return 0;
2781}
2782
2783int
2784syscall32_module_handler(struct module *mod, int what, void *arg)
2785{
2786	struct syscall_module_data *data = (struct syscall_module_data*)arg;
2787	modspecific_t ms;
2788	int error;
2789
2790	switch (what) {
2791	case MOD_LOAD:
2792		error = syscall32_register(data->offset, data->new_sysent,
2793		    &data->old_sysent);
2794		if (error) {
2795			/* Leave a mark so we know to safely unload below. */
2796			data->offset = NULL;
2797			return error;
2798		}
2799		ms.intval = *data->offset;
2800		MOD_XLOCK;
2801		module_setspecific(mod, &ms);
2802		MOD_XUNLOCK;
2803		if (data->chainevh)
2804			error = data->chainevh(mod, what, data->chainarg);
2805		return (error);
2806	case MOD_UNLOAD:
2807		/*
2808		 * MOD_LOAD failed, so just return without calling the
2809		 * chained handler since we didn't pass along the MOD_LOAD
2810		 * event.
2811		 */
2812		if (data->offset == NULL)
2813			return (0);
2814		if (data->chainevh) {
2815			error = data->chainevh(mod, what, data->chainarg);
2816			if (error)
2817				return (error);
2818		}
2819		error = syscall32_deregister(data->offset, &data->old_sysent);
2820		return (error);
2821	default:
2822		error = EOPNOTSUPP;
2823		if (data->chainevh)
2824			error = data->chainevh(mod, what, data->chainarg);
2825		return (error);
2826	}
2827}
2828