freebsd32_misc.c revision 220791
141502Swpaul/*-
241502Swpaul * Copyright (c) 2002 Doug Rabson
341502Swpaul * All rights reserved.
441502Swpaul *
541502Swpaul * Redistribution and use in source and binary forms, with or without
641502Swpaul * modification, are permitted provided that the following conditions
741502Swpaul * are met:
841502Swpaul * 1. Redistributions of source code must retain the above copyright
941502Swpaul *    notice, this list of conditions and the following disclaimer.
1041502Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1141502Swpaul *    notice, this list of conditions and the following disclaimer in the
1241502Swpaul *    documentation and/or other materials provided with the distribution.
1341502Swpaul *
1441502Swpaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1541502Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1641502Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1741502Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1841502Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1941502Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2041502Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2141502Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2241502Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2341502Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2441502Swpaul * SUCH DAMAGE.
2541502Swpaul */
2641502Swpaul
2741502Swpaul#include <sys/cdefs.h>
2841502Swpaul__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 220791 2011-04-18 16:32:22Z mdf $");
2941502Swpaul
3041502Swpaul#include "opt_compat.h"
3141502Swpaul#include "opt_inet.h"
3243515Swpaul#include "opt_inet6.h"
3341502Swpaul
3441502Swpaul#define __ELF_WORD_SIZE 32
3541502Swpaul
3641502Swpaul#include <sys/param.h>
3741502Swpaul#include <sys/bus.h>
3841502Swpaul#include <sys/clock.h>
3941502Swpaul#include <sys/exec.h>
4041502Swpaul#include <sys/fcntl.h>
4141502Swpaul#include <sys/filedesc.h>
4241502Swpaul#include <sys/imgact.h>
4341502Swpaul#include <sys/jail.h>
4441502Swpaul#include <sys/kernel.h>
4541502Swpaul#include <sys/limits.h>
4641502Swpaul#include <sys/linker.h>
4741502Swpaul#include <sys/lock.h>
4841502Swpaul#include <sys/malloc.h>
4941502Swpaul#include <sys/file.h>		/* Must come after sys/malloc.h */
5041502Swpaul#include <sys/imgact.h>
5141502Swpaul#include <sys/mbuf.h>
5241502Swpaul#include <sys/mman.h>
5341502Swpaul#include <sys/module.h>
5441502Swpaul#include <sys/mount.h>
5541502Swpaul#include <sys/mutex.h>
5641502Swpaul#include <sys/namei.h>
5741502Swpaul#include <sys/proc.h>
5841502Swpaul#include <sys/reboot.h>
5941502Swpaul#include <sys/resource.h>
6041502Swpaul#include <sys/resourcevar.h>
6141502Swpaul#include <sys/selinfo.h>
6241502Swpaul#include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
6341502Swpaul#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
6441502Swpaul#include <sys/signal.h>
6541502Swpaul#include <sys/signalvar.h>
6641502Swpaul#include <sys/socket.h>
6741502Swpaul#include <sys/socketvar.h>
6841502Swpaul#include <sys/stat.h>
6941502Swpaul#include <sys/syscall.h>
7041502Swpaul#include <sys/syscallsubr.h>
7141502Swpaul#include <sys/sysctl.h>
7241502Swpaul#include <sys/sysent.h>
7341502Swpaul#include <sys/sysproto.h>
7441502Swpaul#include <sys/systm.h>
7541502Swpaul#include <sys/thr.h>
7641502Swpaul#include <sys/unistd.h>
7741502Swpaul#include <sys/ucontext.h>
7841502Swpaul#include <sys/vnode.h>
7941502Swpaul#include <sys/wait.h>
8041502Swpaul#include <sys/ipc.h>
8141502Swpaul#include <sys/msg.h>
8241502Swpaul#include <sys/sem.h>
8341502Swpaul#include <sys/shm.h>
8441502Swpaul
8541502Swpaul#ifdef INET
8641502Swpaul#include <netinet/in.h>
8741502Swpaul#endif
8841502Swpaul
8941502Swpaul#include <vm/vm.h>
9041502Swpaul#include <vm/vm_param.h>
9141502Swpaul#include <vm/pmap.h>
9241502Swpaul#include <vm/vm_map.h>
9341502Swpaul#include <vm/vm_object.h>
9441502Swpaul#include <vm/vm_extern.h>
9541502Swpaul
9641502Swpaul#include <machine/cpu.h>
9741502Swpaul#include <machine/elf.h>
9841502Swpaul
9941591Sarchie#include <security/audit/audit.h>
10043515Swpaul
10141502Swpaul#include <compat/freebsd32/freebsd32_util.h>
10241502Swpaul#include <compat/freebsd32/freebsd32.h>
10341502Swpaul#include <compat/freebsd32/freebsd32_ipc.h>
10441502Swpaul#include <compat/freebsd32/freebsd32_signal.h>
10541502Swpaul#include <compat/freebsd32/freebsd32_proto.h>
10641502Swpaul
10741502SwpaulCTASSERT(sizeof(struct timeval32) == 8);
10841502SwpaulCTASSERT(sizeof(struct timespec32) == 8);
10941502SwpaulCTASSERT(sizeof(struct itimerval32) == 16);
11041502SwpaulCTASSERT(sizeof(struct statfs32) == 256);
11141502SwpaulCTASSERT(sizeof(struct rusage32) == 72);
11241502SwpaulCTASSERT(sizeof(struct sigaltstack32) == 12);
11341502SwpaulCTASSERT(sizeof(struct kevent32) == 20);
11441502SwpaulCTASSERT(sizeof(struct iovec32) == 8);
11541502SwpaulCTASSERT(sizeof(struct msghdr32) == 28);
11641502SwpaulCTASSERT(sizeof(struct stat32) == 96);
11741502SwpaulCTASSERT(sizeof(struct sigaction32) == 24);
11841502Swpaul
11941502Swpaulstatic int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
12041502Swpaulstatic int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
12141502Swpaul
12241502Swpaul#if BYTE_ORDER == BIG_ENDIAN
12341502Swpaul#define PAIR32TO64(type, name) ((name ## 2) | ((type)(name ## 1) << 32))
12441502Swpaul#define RETVAL_HI 0
12541502Swpaul#define RETVAL_LO 1
12641502Swpaul#else
12741502Swpaul#define PAIR32TO64(type, name) ((name ## 1) | ((type)(name ## 2) << 32))
12841502Swpaul#define RETVAL_HI 1
12941502Swpaul#define RETVAL_LO 0
13041502Swpaul#endif
13141771Sdillon
13241502Swpaulvoid
13341502Swpaulfreebsd32_rusage_out(const struct rusage *s, struct rusage32 *s32)
13441502Swpaul{
13541502Swpaul
13641502Swpaul	TV_CP(*s, *s32, ru_utime);
13741502Swpaul	TV_CP(*s, *s32, ru_stime);
13841502Swpaul	CP(*s, *s32, ru_maxrss);
13941502Swpaul	CP(*s, *s32, ru_ixrss);
14041502Swpaul	CP(*s, *s32, ru_idrss);
14141502Swpaul	CP(*s, *s32, ru_isrss);
14241502Swpaul	CP(*s, *s32, ru_minflt);
14341502Swpaul	CP(*s, *s32, ru_majflt);
14441502Swpaul	CP(*s, *s32, ru_nswap);
14541502Swpaul	CP(*s, *s32, ru_inblock);
14641502Swpaul	CP(*s, *s32, ru_oublock);
14741502Swpaul	CP(*s, *s32, ru_msgsnd);
14841502Swpaul	CP(*s, *s32, ru_msgrcv);
14941502Swpaul	CP(*s, *s32, ru_nsignals);
15041502Swpaul	CP(*s, *s32, ru_nvcsw);
15141502Swpaul	CP(*s, *s32, ru_nivcsw);
15241502Swpaul}
15341502Swpaul
15441502Swpaulint
15541502Swpaulfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
15641502Swpaul{
15741502Swpaul	int error, status;
15841502Swpaul	struct rusage32 ru32;
15941502Swpaul	struct rusage ru, *rup;
16041502Swpaul
16141502Swpaul	if (uap->rusage != NULL)
16241502Swpaul		rup = &ru;
16341502Swpaul	else
16441502Swpaul		rup = NULL;
16541502Swpaul	error = kern_wait(td, uap->pid, &status, uap->options, rup);
16641502Swpaul	if (error)
16741502Swpaul		return (error);
16841502Swpaul	if (uap->status != NULL)
16941502Swpaul		error = copyout(&status, uap->status, sizeof(status));
17041502Swpaul	if (uap->rusage != NULL && error == 0) {
17141502Swpaul		freebsd32_rusage_out(&ru, &ru32);
17241502Swpaul		error = copyout(&ru32, uap->rusage, sizeof(ru32));
17341502Swpaul	}
17441502Swpaul	return (error);
17541502Swpaul}
17641502Swpaul
17741502Swpaul#ifdef COMPAT_FREEBSD4
17841502Swpaulstatic void
17941502Swpaulcopy_statfs(struct statfs *in, struct statfs32 *out)
18041502Swpaul{
18141502Swpaul
18241502Swpaul	statfs_scale_blocks(in, INT32_MAX);
18341502Swpaul	bzero(out, sizeof(*out));
18441502Swpaul	CP(*in, *out, f_bsize);
18541502Swpaul	out->f_iosize = MIN(in->f_iosize, INT32_MAX);
18641502Swpaul	CP(*in, *out, f_blocks);
18741502Swpaul	CP(*in, *out, f_bfree);
18841502Swpaul	CP(*in, *out, f_bavail);
18941502Swpaul	out->f_files = MIN(in->f_files, INT32_MAX);
19041502Swpaul	out->f_ffree = MIN(in->f_ffree, INT32_MAX);
19141502Swpaul	CP(*in, *out, f_fsid);
19241502Swpaul	CP(*in, *out, f_owner);
19341502Swpaul	CP(*in, *out, f_type);
19441502Swpaul	CP(*in, *out, f_flags);
19541502Swpaul	out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
19641502Swpaul	out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
19741502Swpaul	strlcpy(out->f_fstypename,
19841502Swpaul	      in->f_fstypename, MFSNAMELEN);
19941502Swpaul	strlcpy(out->f_mntonname,
20041502Swpaul	      in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
20141502Swpaul	out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
20241502Swpaul	out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
20341502Swpaul	strlcpy(out->f_mntfromname,
20441502Swpaul	      in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
20541502Swpaul}
20641502Swpaul#endif
20741502Swpaul
20841502Swpaul#ifdef COMPAT_FREEBSD4
20941502Swpaulint
21041502Swpaulfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
21141502Swpaul{
21241502Swpaul	struct statfs *buf, *sp;
21341502Swpaul	struct statfs32 stat32;
21441502Swpaul	size_t count, size;
21541502Swpaul	int error;
21641502Swpaul
21741502Swpaul	count = uap->bufsize / sizeof(struct statfs32);
21841502Swpaul	size = count * sizeof(struct statfs);
21941502Swpaul	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
22041502Swpaul	if (size > 0) {
22141502Swpaul		count = td->td_retval[0];
22241502Swpaul		sp = buf;
22341502Swpaul		while (count > 0 && error == 0) {
22441502Swpaul			copy_statfs(sp, &stat32);
22541502Swpaul			error = copyout(&stat32, uap->buf, sizeof(stat32));
22641502Swpaul			sp++;
22741502Swpaul			uap->buf++;
22841502Swpaul			count--;
22941502Swpaul		}
23041502Swpaul		free(buf, M_TEMP);
23141502Swpaul	}
23241502Swpaul	return (error);
23341502Swpaul}
23441502Swpaul#endif
23541502Swpaul
23641502Swpaulint
23741502Swpaulfreebsd32_sigaltstack(struct thread *td,
23841502Swpaul		      struct freebsd32_sigaltstack_args *uap)
23941502Swpaul{
24041502Swpaul	struct sigaltstack32 s32;
24141502Swpaul	struct sigaltstack ss, oss, *ssp;
24241502Swpaul	int error;
24341502Swpaul
24441502Swpaul	if (uap->ss != NULL) {
24541502Swpaul		error = copyin(uap->ss, &s32, sizeof(s32));
24641502Swpaul		if (error)
24741502Swpaul			return (error);
24841502Swpaul		PTRIN_CP(s32, ss, ss_sp);
24941502Swpaul		CP(s32, ss, ss_size);
25041502Swpaul		CP(s32, ss, ss_flags);
25141502Swpaul		ssp = &ss;
25241502Swpaul	} else
25341502Swpaul		ssp = NULL;
25441502Swpaul	error = kern_sigaltstack(td, ssp, &oss);
25541502Swpaul	if (error == 0 && uap->oss != NULL) {
25641502Swpaul		PTROUT_CP(oss, s32, ss_sp);
25741502Swpaul		CP(oss, s32, ss_size);
25841502Swpaul		CP(oss, s32, ss_flags);
25941502Swpaul		error = copyout(&s32, uap->oss, sizeof(s32));
26041502Swpaul	}
26141502Swpaul	return (error);
26241502Swpaul}
26341502Swpaul
26441502Swpaul/*
26541502Swpaul * Custom version of exec_copyin_args() so that we can translate
26641502Swpaul * the pointers.
26741502Swpaul */
26841502Swpaulint
26941502Swpaulfreebsd32_exec_copyin_args(struct image_args *args, char *fname,
27041502Swpaul    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
27141502Swpaul{
27241502Swpaul	char *argp, *envp;
27341502Swpaul	u_int32_t *p32, arg;
27441502Swpaul	size_t length;
27541502Swpaul	int error;
27641502Swpaul
27741502Swpaul	bzero(args, sizeof(*args));
27841502Swpaul	if (argv == NULL)
27941502Swpaul		return (EFAULT);
28041502Swpaul
28141502Swpaul	/*
28241502Swpaul	 * Allocate demand-paged memory for the file name, argument, and
28341502Swpaul	 * environment strings.
28441502Swpaul	 */
28541502Swpaul	error = exec_alloc_args(args);
28641502Swpaul	if (error != 0)
28741502Swpaul		return (error);
28841502Swpaul
28941502Swpaul	/*
29041502Swpaul	 * Copy the file name.
29141502Swpaul	 */
29241502Swpaul	if (fname != NULL) {
29341502Swpaul		args->fname = args->buf;
29441502Swpaul		error = (segflg == UIO_SYSSPACE) ?
29541502Swpaul		    copystr(fname, args->fname, PATH_MAX, &length) :
29641502Swpaul		    copyinstr(fname, args->fname, PATH_MAX, &length);
29741502Swpaul		if (error != 0)
29841502Swpaul			goto err_exit;
29941502Swpaul	} else
30041502Swpaul		length = 0;
30141502Swpaul
30241502Swpaul	args->begin_argv = args->buf + length;
30341502Swpaul	args->endp = args->begin_argv;
30441502Swpaul	args->stringspace = ARG_MAX;
30541502Swpaul
30641502Swpaul	/*
30741502Swpaul	 * extract arguments first
30841502Swpaul	 */
30941502Swpaul	p32 = argv;
31041502Swpaul	for (;;) {
31141502Swpaul		error = copyin(p32++, &arg, sizeof(arg));
31241502Swpaul		if (error)
31341502Swpaul			goto err_exit;
31441502Swpaul		if (arg == 0)
31541502Swpaul			break;
31641502Swpaul		argp = PTRIN(arg);
31741502Swpaul		error = copyinstr(argp, args->endp, args->stringspace, &length);
31841502Swpaul		if (error) {
31941502Swpaul			if (error == ENAMETOOLONG)
32041502Swpaul				error = E2BIG;
32141502Swpaul			goto err_exit;
32241502Swpaul		}
32341502Swpaul		args->stringspace -= length;
32441502Swpaul		args->endp += length;
32541502Swpaul		args->argc++;
32641502Swpaul	}
32741502Swpaul
32841502Swpaul	args->begin_envv = args->endp;
32941502Swpaul
33041502Swpaul	/*
33141502Swpaul	 * extract environment strings
33241502Swpaul	 */
33341502Swpaul	if (envv) {
33441502Swpaul		p32 = envv;
33541502Swpaul		for (;;) {
33641502Swpaul			error = copyin(p32++, &arg, sizeof(arg));
33741502Swpaul			if (error)
33841502Swpaul				goto err_exit;
33941502Swpaul			if (arg == 0)
34041502Swpaul				break;
34141502Swpaul			envp = PTRIN(arg);
34241502Swpaul			error = copyinstr(envp, args->endp, args->stringspace,
34341502Swpaul			    &length);
34441502Swpaul			if (error) {
34541502Swpaul				if (error == ENAMETOOLONG)
34641502Swpaul					error = E2BIG;
34741502Swpaul				goto err_exit;
34841502Swpaul			}
34941502Swpaul			args->stringspace -= length;
35041502Swpaul			args->endp += length;
35141502Swpaul			args->envc++;
35241502Swpaul		}
35341502Swpaul	}
35441502Swpaul
35541502Swpaul	return (0);
35641502Swpaul
35741502Swpaulerr_exit:
35841502Swpaul	exec_free_args(args);
35941502Swpaul	return (error);
36041502Swpaul}
36141502Swpaul
36241502Swpaulint
36341502Swpaulfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
36441502Swpaul{
36541502Swpaul	struct image_args eargs;
36641502Swpaul	int error;
36741502Swpaul
36841502Swpaul	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
36941502Swpaul	    uap->argv, uap->envv);
37041502Swpaul	if (error == 0)
37141502Swpaul		error = kern_execve(td, &eargs, NULL);
37241502Swpaul	return (error);
37341502Swpaul}
37441502Swpaul
37541502Swpaulint
37641502Swpaulfreebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
37741502Swpaul{
37841502Swpaul	struct image_args eargs;
37941502Swpaul	int error;
38041502Swpaul
38141502Swpaul	error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE,
38241502Swpaul	    uap->argv, uap->envv);
38341502Swpaul	if (error == 0) {
38441502Swpaul		eargs.fd = uap->fd;
38541502Swpaul		error = kern_execve(td, &eargs, NULL);
38641502Swpaul	}
38741502Swpaul	return (error);
38841502Swpaul}
38941502Swpaul
39041502Swpaul#ifdef __ia64__
39141502Swpaulstatic int
39241502Swpaulfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
39341502Swpaul		       int prot, int fd, off_t pos)
39441502Swpaul{
39541502Swpaul	vm_map_t map;
39641502Swpaul	vm_map_entry_t entry;
39741502Swpaul	int rv;
39841502Swpaul
39941502Swpaul	map = &td->td_proc->p_vmspace->vm_map;
40041502Swpaul	if (fd != -1)
40141502Swpaul		prot |= VM_PROT_WRITE;
40241502Swpaul
40341502Swpaul	if (vm_map_lookup_entry(map, start, &entry)) {
40441502Swpaul		if ((entry->protection & prot) != prot) {
40541502Swpaul			rv = vm_map_protect(map,
40641502Swpaul					    trunc_page(start),
40741502Swpaul					    round_page(end),
40841502Swpaul					    entry->protection | prot,
40941502Swpaul					    FALSE);
41041502Swpaul			if (rv != KERN_SUCCESS)
41141502Swpaul				return (EINVAL);
41241502Swpaul		}
41341502Swpaul	} else {
41441502Swpaul		vm_offset_t addr = trunc_page(start);
41541502Swpaul		rv = vm_map_find(map, 0, 0,
41641502Swpaul				 &addr, PAGE_SIZE, FALSE, prot,
41741502Swpaul				 VM_PROT_ALL, 0);
41841502Swpaul		if (rv != KERN_SUCCESS)
41941502Swpaul			return (EINVAL);
42041502Swpaul	}
42141502Swpaul
42241502Swpaul	if (fd != -1) {
42341502Swpaul		struct pread_args r;
42441502Swpaul		r.fd = fd;
42541502Swpaul		r.buf = (void *) start;
42641502Swpaul		r.nbyte = end - start;
42741502Swpaul		r.offset = pos;
42841502Swpaul		return (pread(td, &r));
42941502Swpaul	} else {
43041502Swpaul		while (start < end) {
43141502Swpaul			subyte((void *) start, 0);
43241502Swpaul			start++;
43341502Swpaul		}
43441502Swpaul		return (0);
43541502Swpaul	}
43641502Swpaul}
43741502Swpaul#endif
43841502Swpaul
43941502Swpaulint
44041502Swpaulfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
44141502Swpaul{
44241502Swpaul	struct mmap_args ap;
44341502Swpaul	vm_offset_t addr = (vm_offset_t) uap->addr;
44441502Swpaul	vm_size_t len	 = uap->len;
44541502Swpaul	int prot	 = uap->prot;
44641502Swpaul	int flags	 = uap->flags;
44741502Swpaul	int fd		 = uap->fd;
44841502Swpaul	off_t pos	 = PAIR32TO64(off_t,uap->pos);
44941502Swpaul#ifdef __ia64__
45041502Swpaul	vm_size_t pageoff;
45141502Swpaul	int error;
45241502Swpaul
45341502Swpaul	/*
45441502Swpaul	 * Attempt to handle page size hassles.
45541502Swpaul	 */
45641502Swpaul	pageoff = (pos & PAGE_MASK);
45741502Swpaul	if (flags & MAP_FIXED) {
45841502Swpaul		vm_offset_t start, end;
45941502Swpaul		start = addr;
46041502Swpaul		end = addr + len;
46141502Swpaul
46241502Swpaul		if (start != trunc_page(start)) {
46341502Swpaul			error = freebsd32_mmap_partial(td, start,
46441502Swpaul						       round_page(start), prot,
46541502Swpaul						       fd, pos);
46641502Swpaul			if (fd != -1)
46741502Swpaul				pos += round_page(start) - start;
46841502Swpaul			start = round_page(start);
46941502Swpaul		}
47041502Swpaul		if (end != round_page(end)) {
47141502Swpaul			vm_offset_t t = trunc_page(end);
47241502Swpaul			error = freebsd32_mmap_partial(td, t, end,
47341502Swpaul						  prot, fd,
47441502Swpaul						  pos + t - start);
47541502Swpaul			end = trunc_page(end);
47641502Swpaul		}
47741502Swpaul		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
47841502Swpaul			/*
47941502Swpaul			 * We can't map this region at all. The specified
48041502Swpaul			 * address doesn't have the same alignment as the file
48141502Swpaul			 * position. Fake the mapping by simply reading the
48241502Swpaul			 * entire region into memory. First we need to make
48341502Swpaul			 * sure the region exists.
48441502Swpaul			 */
48541502Swpaul			vm_map_t map;
48641502Swpaul			struct pread_args r;
48741502Swpaul			int rv;
48841502Swpaul
48941502Swpaul			prot |= VM_PROT_WRITE;
49041502Swpaul			map = &td->td_proc->p_vmspace->vm_map;
49141502Swpaul			rv = vm_map_remove(map, start, end);
49241502Swpaul			if (rv != KERN_SUCCESS)
49341502Swpaul				return (EINVAL);
49441502Swpaul			rv = vm_map_find(map, 0, 0,
49541502Swpaul					 &start, end - start, FALSE,
49641502Swpaul					 prot, VM_PROT_ALL, 0);
49741502Swpaul			if (rv != KERN_SUCCESS)
49841502Swpaul				return (EINVAL);
49941502Swpaul			r.fd = fd;
50041502Swpaul			r.buf = (void *) start;
50141502Swpaul			r.nbyte = end - start;
50241502Swpaul			r.offset = pos;
50341502Swpaul			error = pread(td, &r);
50441502Swpaul			if (error)
50541502Swpaul				return (error);
50641502Swpaul
50741502Swpaul			td->td_retval[0] = addr;
50841502Swpaul			return (0);
50941502Swpaul		}
51041502Swpaul		if (end == start) {
51141502Swpaul			/*
51241502Swpaul			 * After dealing with the ragged ends, there
51341502Swpaul			 * might be none left.
51441502Swpaul			 */
51541502Swpaul			td->td_retval[0] = addr;
51641502Swpaul			return (0);
51741502Swpaul		}
51841502Swpaul		addr = start;
51941502Swpaul		len = end - start;
52041502Swpaul	}
52141502Swpaul#endif
52241502Swpaul
52341502Swpaul	ap.addr = (void *) addr;
52441502Swpaul	ap.len = len;
52541502Swpaul	ap.prot = prot;
52641502Swpaul	ap.flags = flags;
52741502Swpaul	ap.fd = fd;
52841502Swpaul	ap.pos = pos;
52941502Swpaul
53041502Swpaul	return (mmap(td, &ap));
53141502Swpaul}
53241502Swpaul
53341502Swpaul#ifdef COMPAT_FREEBSD6
53441502Swpaulint
53541502Swpaulfreebsd6_freebsd32_mmap(struct thread *td, struct freebsd6_freebsd32_mmap_args *uap)
53641502Swpaul{
53741502Swpaul	struct freebsd32_mmap_args ap;
53841502Swpaul
53941502Swpaul	ap.addr = uap->addr;
54041502Swpaul	ap.len = uap->len;
54141502Swpaul	ap.prot = uap->prot;
54241502Swpaul	ap.flags = uap->flags;
54341502Swpaul	ap.fd = uap->fd;
54441502Swpaul	ap.pos1 = uap->pos1;
54541502Swpaul	ap.pos2 = uap->pos2;
54641502Swpaul
54741502Swpaul	return (freebsd32_mmap(td, &ap));
54841502Swpaul}
54941502Swpaul#endif
55041502Swpaul
55141502Swpaulint
55241502Swpaulfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
55341502Swpaul{
55441502Swpaul	struct itimerval itv, oitv, *itvp;
55541502Swpaul	struct itimerval32 i32;
55641502Swpaul	int error;
55741502Swpaul
55841502Swpaul	if (uap->itv != NULL) {
55941502Swpaul		error = copyin(uap->itv, &i32, sizeof(i32));
56041502Swpaul		if (error)
56141502Swpaul			return (error);
56241502Swpaul		TV_CP(i32, itv, it_interval);
56341502Swpaul		TV_CP(i32, itv, it_value);
56441502Swpaul		itvp = &itv;
56541502Swpaul	} else
56641502Swpaul		itvp = NULL;
56741502Swpaul	error = kern_setitimer(td, uap->which, itvp, &oitv);
56841502Swpaul	if (error || uap->oitv == NULL)
56941502Swpaul		return (error);
57041502Swpaul	TV_CP(oitv, i32, it_interval);
57141502Swpaul	TV_CP(oitv, i32, it_value);
57241502Swpaul	return (copyout(&i32, uap->oitv, sizeof(i32)));
57341502Swpaul}
57441502Swpaul
57541502Swpaulint
57641502Swpaulfreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
57741502Swpaul{
57841502Swpaul	struct itimerval itv;
57941502Swpaul	struct itimerval32 i32;
58041502Swpaul	int error;
58141502Swpaul
58241502Swpaul	error = kern_getitimer(td, uap->which, &itv);
58341502Swpaul	if (error || uap->itv == NULL)
58441502Swpaul		return (error);
58541502Swpaul	TV_CP(itv, i32, it_interval);
58641502Swpaul	TV_CP(itv, i32, it_value);
58741502Swpaul	return (copyout(&i32, uap->itv, sizeof(i32)));
58841502Swpaul}
58941502Swpaul
59041502Swpaulint
59141502Swpaulfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
59241502Swpaul{
59341502Swpaul	struct timeval32 tv32;
59441502Swpaul	struct timeval tv, *tvp;
59541502Swpaul	int error;
59641502Swpaul
59741502Swpaul	if (uap->tv != NULL) {
59841502Swpaul		error = copyin(uap->tv, &tv32, sizeof(tv32));
59941502Swpaul		if (error)
60041502Swpaul			return (error);
60141502Swpaul		CP(tv32, tv, tv_sec);
60241502Swpaul		CP(tv32, tv, tv_usec);
60341502Swpaul		tvp = &tv;
60441502Swpaul	} else
60541502Swpaul		tvp = NULL;
60641502Swpaul	/*
60741502Swpaul	 * XXX Do pointers need PTRIN()?
60841502Swpaul	 */
60941502Swpaul	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
61041502Swpaul	    sizeof(int32_t) * 8));
61141502Swpaul}
61241502Swpaul
61341502Swpaulint
61441502Swpaulfreebsd32_pselect(struct thread *td, struct freebsd32_pselect_args *uap)
61541502Swpaul{
61641502Swpaul	struct timespec32 ts32;
61741502Swpaul	struct timespec ts;
61841502Swpaul	struct timeval tv, *tvp;
61941502Swpaul	sigset_t set, *uset;
62041502Swpaul	int error;
62141502Swpaul
62241502Swpaul	if (uap->ts != NULL) {
62341502Swpaul		error = copyin(uap->ts, &ts32, sizeof(ts32));
62441502Swpaul		if (error != 0)
62541502Swpaul			return (error);
62641502Swpaul		CP(ts32, ts, tv_sec);
62741502Swpaul		CP(ts32, ts, tv_nsec);
62841502Swpaul		TIMESPEC_TO_TIMEVAL(&tv, &ts);
62941502Swpaul		tvp = &tv;
63041502Swpaul	} else
63141502Swpaul		tvp = NULL;
63241502Swpaul	if (uap->sm != NULL) {
63341502Swpaul		error = copyin(uap->sm, &set, sizeof(set));
63441502Swpaul		if (error != 0)
63541502Swpaul			return (error);
63641502Swpaul		uset = &set;
63741502Swpaul	} else
63841502Swpaul		uset = NULL;
63941502Swpaul	/*
64041502Swpaul	 * XXX Do pointers need PTRIN()?
64141502Swpaul	 */
64241502Swpaul	error = kern_pselect(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
64341502Swpaul	    uset, sizeof(int32_t) * 8);
64441502Swpaul	return (error);
64541502Swpaul}
64641502Swpaul
64741502Swpaul/*
64841502Swpaul * Copy 'count' items into the destination list pointed to by uap->eventlist.
64941502Swpaul */
65041502Swpaulstatic int
65141502Swpaulfreebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
65241502Swpaul{
65341502Swpaul	struct freebsd32_kevent_args *uap;
65441502Swpaul	struct kevent32	ks32[KQ_NEVENTS];
65541502Swpaul	int i, error = 0;
65641502Swpaul
65741502Swpaul	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
65841502Swpaul	uap = (struct freebsd32_kevent_args *)arg;
65941502Swpaul
66041502Swpaul	for (i = 0; i < count; i++) {
66141502Swpaul		CP(kevp[i], ks32[i], ident);
66241502Swpaul		CP(kevp[i], ks32[i], filter);
66341502Swpaul		CP(kevp[i], ks32[i], flags);
66441502Swpaul		CP(kevp[i], ks32[i], fflags);
66541502Swpaul		CP(kevp[i], ks32[i], data);
66641502Swpaul		PTROUT_CP(kevp[i], ks32[i], udata);
66741502Swpaul	}
66841502Swpaul	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
66941502Swpaul	if (error == 0)
67041502Swpaul		uap->eventlist += count;
67141502Swpaul	return (error);
67241502Swpaul}
67341502Swpaul
67441502Swpaul/*
67541502Swpaul * Copy 'count' items from the list pointed to by uap->changelist.
67641502Swpaul */
67741502Swpaulstatic int
67841502Swpaulfreebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
67941502Swpaul{
68041502Swpaul	struct freebsd32_kevent_args *uap;
68141502Swpaul	struct kevent32	ks32[KQ_NEVENTS];
68241502Swpaul	int i, error = 0;
68341502Swpaul
68441502Swpaul	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
68541502Swpaul	uap = (struct freebsd32_kevent_args *)arg;
68641502Swpaul
68741502Swpaul	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
68841502Swpaul	if (error)
68941502Swpaul		goto done;
69041502Swpaul	uap->changelist += count;
69141502Swpaul
69241502Swpaul	for (i = 0; i < count; i++) {
69341502Swpaul		CP(ks32[i], kevp[i], ident);
69441502Swpaul		CP(ks32[i], kevp[i], filter);
69541502Swpaul		CP(ks32[i], kevp[i], flags);
69641502Swpaul		CP(ks32[i], kevp[i], fflags);
69741502Swpaul		CP(ks32[i], kevp[i], data);
69841502Swpaul		PTRIN_CP(ks32[i], kevp[i], udata);
69941502Swpaul	}
70041502Swpauldone:
70141502Swpaul	return (error);
70241502Swpaul}
70341502Swpaul
70441502Swpaulint
70541502Swpaulfreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
70641502Swpaul{
70741502Swpaul	struct timespec32 ts32;
70841502Swpaul	struct timespec ts, *tsp;
70941502Swpaul	struct kevent_copyops k_ops = { uap,
71041502Swpaul					freebsd32_kevent_copyout,
71141502Swpaul					freebsd32_kevent_copyin};
71241502Swpaul	int error;
71341502Swpaul
71441502Swpaul
71541502Swpaul	if (uap->timeout) {
71641502Swpaul		error = copyin(uap->timeout, &ts32, sizeof(ts32));
71741502Swpaul		if (error)
71841502Swpaul			return (error);
71941502Swpaul		CP(ts32, ts, tv_sec);
72041502Swpaul		CP(ts32, ts, tv_nsec);
72141502Swpaul		tsp = &ts;
72241502Swpaul	} else
72341502Swpaul		tsp = NULL;
72441502Swpaul	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
72541502Swpaul	    &k_ops, tsp);
72641502Swpaul	return (error);
72741502Swpaul}
72841502Swpaul
72941502Swpaulint
73041502Swpaulfreebsd32_gettimeofday(struct thread *td,
73141502Swpaul		       struct freebsd32_gettimeofday_args *uap)
73241502Swpaul{
73341502Swpaul	struct timeval atv;
73441502Swpaul	struct timeval32 atv32;
73541502Swpaul	struct timezone rtz;
73641502Swpaul	int error = 0;
73741502Swpaul
73841502Swpaul	if (uap->tp) {
73941502Swpaul		microtime(&atv);
74041502Swpaul		CP(atv, atv32, tv_sec);
74141502Swpaul		CP(atv, atv32, tv_usec);
74241502Swpaul		error = copyout(&atv32, uap->tp, sizeof (atv32));
74341502Swpaul	}
74441502Swpaul	if (error == 0 && uap->tzp != NULL) {
74541502Swpaul		rtz.tz_minuteswest = tz_minuteswest;
74641502Swpaul		rtz.tz_dsttime = tz_dsttime;
74741502Swpaul		error = copyout(&rtz, uap->tzp, sizeof (rtz));
74841502Swpaul	}
74941502Swpaul	return (error);
75041502Swpaul}
75141502Swpaul
75241502Swpaulint
75341502Swpaulfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
75441502Swpaul{
75541502Swpaul	struct rusage32 s32;
75641502Swpaul	struct rusage s;
75741502Swpaul	int error;
75841502Swpaul
75941502Swpaul	error = kern_getrusage(td, uap->who, &s);
76041502Swpaul	if (error)
76141502Swpaul		return (error);
76241502Swpaul	if (uap->rusage != NULL) {
76341502Swpaul		freebsd32_rusage_out(&s, &s32);
76441502Swpaul		error = copyout(&s32, uap->rusage, sizeof(s32));
76541502Swpaul	}
76641502Swpaul	return (error);
76741502Swpaul}
76841502Swpaul
76941502Swpaulstatic int
77041502Swpaulfreebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
77141502Swpaul{
77241502Swpaul	struct iovec32 iov32;
77341502Swpaul	struct iovec *iov;
77441502Swpaul	struct uio *uio;
77541502Swpaul	u_int iovlen;
77641502Swpaul	int error, i;
77741502Swpaul
77841502Swpaul	*uiop = NULL;
77941502Swpaul	if (iovcnt > UIO_MAXIOV)
78041502Swpaul		return (EINVAL);
78141502Swpaul	iovlen = iovcnt * sizeof(struct iovec);
78241502Swpaul	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
78341502Swpaul	iov = (struct iovec *)(uio + 1);
78441502Swpaul	for (i = 0; i < iovcnt; i++) {
78541502Swpaul		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
78641502Swpaul		if (error) {
78741502Swpaul			free(uio, M_IOV);
78841502Swpaul			return (error);
78941502Swpaul		}
79041502Swpaul		iov[i].iov_base = PTRIN(iov32.iov_base);
79141502Swpaul		iov[i].iov_len = iov32.iov_len;
79241502Swpaul	}
79341502Swpaul	uio->uio_iov = iov;
79441502Swpaul	uio->uio_iovcnt = iovcnt;
79541502Swpaul	uio->uio_segflg = UIO_USERSPACE;
79641502Swpaul	uio->uio_offset = -1;
79741502Swpaul	uio->uio_resid = 0;
79841502Swpaul	for (i = 0; i < iovcnt; i++) {
79941502Swpaul		if (iov->iov_len > INT_MAX - uio->uio_resid) {
80041502Swpaul			free(uio, M_IOV);
80141502Swpaul			return (EINVAL);
80241502Swpaul		}
80341502Swpaul		uio->uio_resid += iov->iov_len;
80441502Swpaul		iov++;
80541502Swpaul	}
80641502Swpaul	*uiop = uio;
80741502Swpaul	return (0);
80841502Swpaul}
80941502Swpaul
81041502Swpaulint
81141502Swpaulfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
81241502Swpaul{
81341502Swpaul	struct uio *auio;
81441502Swpaul	int error;
81541502Swpaul
81641502Swpaul	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
81741502Swpaul	if (error)
81841502Swpaul		return (error);
81941502Swpaul	error = kern_readv(td, uap->fd, auio);
82041502Swpaul	free(auio, M_IOV);
82141502Swpaul	return (error);
82241502Swpaul}
82341502Swpaul
82441502Swpaulint
82541502Swpaulfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
82641502Swpaul{
82741502Swpaul	struct uio *auio;
82841502Swpaul	int error;
82941502Swpaul
83041502Swpaul	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
83141502Swpaul	if (error)
83241502Swpaul		return (error);
83341502Swpaul	error = kern_writev(td, uap->fd, auio);
83441502Swpaul	free(auio, M_IOV);
83541502Swpaul	return (error);
83641502Swpaul}
83741502Swpaul
83841502Swpaulint
83941502Swpaulfreebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
84041502Swpaul{
84141502Swpaul	struct uio *auio;
84241502Swpaul	int error;
84341502Swpaul
84441502Swpaul	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
84541502Swpaul	if (error)
84641502Swpaul		return (error);
84741502Swpaul	error = kern_preadv(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
84841502Swpaul	free(auio, M_IOV);
84941502Swpaul	return (error);
85041502Swpaul}
85141502Swpaul
85241502Swpaulint
85341502Swpaulfreebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
85441502Swpaul{
85541502Swpaul	struct uio *auio;
85641502Swpaul	int error;
85741502Swpaul
85841502Swpaul	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
85941502Swpaul	if (error)
86041502Swpaul		return (error);
86141502Swpaul	error = kern_pwritev(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
86241502Swpaul	free(auio, M_IOV);
86341502Swpaul	return (error);
86441502Swpaul}
86541502Swpaul
86641502Swpaulint
86741502Swpaulfreebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
86841771Sdillon    int error)
86941502Swpaul{
87041502Swpaul	struct iovec32 iov32;
87141502Swpaul	struct iovec *iov;
87241502Swpaul	u_int iovlen;
87341502Swpaul	int i;
87441502Swpaul
87541502Swpaul	*iovp = NULL;
87641502Swpaul	if (iovcnt > UIO_MAXIOV)
87741502Swpaul		return (error);
87841502Swpaul	iovlen = iovcnt * sizeof(struct iovec);
87941502Swpaul	iov = malloc(iovlen, M_IOV, M_WAITOK);
88041502Swpaul	for (i = 0; i < iovcnt; i++) {
88141502Swpaul		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
88241502Swpaul		if (error) {
88341502Swpaul			free(iov, M_IOV);
88441502Swpaul			return (error);
88541502Swpaul		}
88641502Swpaul		iov[i].iov_base = PTRIN(iov32.iov_base);
88741502Swpaul		iov[i].iov_len = iov32.iov_len;
88841502Swpaul	}
88941502Swpaul	*iovp = iov;
89041502Swpaul	return (0);
89141502Swpaul}
89241502Swpaul
89341502Swpaulstatic int
89441502Swpaulfreebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
89541502Swpaul{
89641502Swpaul	struct msghdr32 m32;
89741502Swpaul	int error;
89841502Swpaul
89941502Swpaul	error = copyin(msg32, &m32, sizeof(m32));
90041502Swpaul	if (error)
90141502Swpaul		return (error);
90241502Swpaul	msg->msg_name = PTRIN(m32.msg_name);
90341502Swpaul	msg->msg_namelen = m32.msg_namelen;
90441502Swpaul	msg->msg_iov = PTRIN(m32.msg_iov);
90541502Swpaul	msg->msg_iovlen = m32.msg_iovlen;
90641502Swpaul	msg->msg_control = PTRIN(m32.msg_control);
90741502Swpaul	msg->msg_controllen = m32.msg_controllen;
90841502Swpaul	msg->msg_flags = m32.msg_flags;
90941502Swpaul	return (0);
91041502Swpaul}
91141502Swpaul
91241502Swpaulstatic int
91341502Swpaulfreebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
91441502Swpaul{
91541502Swpaul	struct msghdr32 m32;
91641502Swpaul	int error;
91741502Swpaul
91841502Swpaul	m32.msg_name = PTROUT(msg->msg_name);
91941502Swpaul	m32.msg_namelen = msg->msg_namelen;
92041502Swpaul	m32.msg_iov = PTROUT(msg->msg_iov);
92141502Swpaul	m32.msg_iovlen = msg->msg_iovlen;
92241502Swpaul	m32.msg_control = PTROUT(msg->msg_control);
92341502Swpaul	m32.msg_controllen = msg->msg_controllen;
92441502Swpaul	m32.msg_flags = msg->msg_flags;
92541502Swpaul	error = copyout(&m32, msg32, sizeof(m32));
92641502Swpaul	return (error);
92741502Swpaul}
92841502Swpaul
92941502Swpaul#define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
93041502Swpaul#define FREEBSD32_ALIGN(p)	\
93141502Swpaul	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
93241502Swpaul#define	FREEBSD32_CMSG_SPACE(l)	\
93341502Swpaul	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
93441502Swpaul
93541502Swpaul#define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
93641502Swpaul				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
93741502Swpaulstatic int
93841502Swpaulfreebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
93941502Swpaul{
94041502Swpaul	struct cmsghdr *cm;
94141502Swpaul	void *data;
94241502Swpaul	socklen_t clen, datalen;
94341502Swpaul	int error;
94441502Swpaul	caddr_t ctlbuf;
94541502Swpaul	int len, maxlen, copylen;
94641502Swpaul	struct mbuf *m;
94741502Swpaul	error = 0;
94841502Swpaul
94941502Swpaul	len    = msg->msg_controllen;
95041502Swpaul	maxlen = msg->msg_controllen;
95141502Swpaul	msg->msg_controllen = 0;
95241502Swpaul
95341502Swpaul	m = control;
95441502Swpaul	ctlbuf = msg->msg_control;
95541502Swpaul
95641502Swpaul	while (m && len > 0) {
95741502Swpaul		cm = mtod(m, struct cmsghdr *);
95841502Swpaul		clen = m->m_len;
95941502Swpaul
96041502Swpaul		while (cm != NULL) {
96141502Swpaul
96241502Swpaul			if (sizeof(struct cmsghdr) > clen ||
96341502Swpaul			    cm->cmsg_len > clen) {
96441502Swpaul				error = EINVAL;
96541502Swpaul				break;
96641502Swpaul			}
96741502Swpaul
96841502Swpaul			data   = CMSG_DATA(cm);
96941502Swpaul			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
97041502Swpaul
97141502Swpaul			/* Adjust message length */
97241502Swpaul			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
97341502Swpaul			    datalen;
97441502Swpaul
97541502Swpaul
97641502Swpaul			/* Copy cmsghdr */
97741502Swpaul			copylen = sizeof(struct cmsghdr);
97841502Swpaul			if (len < copylen) {
97941502Swpaul				msg->msg_flags |= MSG_CTRUNC;
98041502Swpaul				copylen = len;
98141502Swpaul			}
98241502Swpaul
98341502Swpaul			error = copyout(cm,ctlbuf,copylen);
98441502Swpaul			if (error)
98541502Swpaul				goto exit;
98641502Swpaul
98741502Swpaul			ctlbuf += FREEBSD32_ALIGN(copylen);
98841502Swpaul			len    -= FREEBSD32_ALIGN(copylen);
98941502Swpaul
99041502Swpaul			if (len <= 0)
99141502Swpaul				break;
99241502Swpaul
99341502Swpaul			/* Copy data */
99441502Swpaul			copylen = datalen;
99541502Swpaul			if (len < copylen) {
99641502Swpaul				msg->msg_flags |= MSG_CTRUNC;
99741502Swpaul				copylen = len;
99841502Swpaul			}
99941502Swpaul
100041502Swpaul			error = copyout(data,ctlbuf,copylen);
100141502Swpaul			if (error)
100241502Swpaul				goto exit;
100341502Swpaul
100441502Swpaul			ctlbuf += FREEBSD32_ALIGN(copylen);
100541502Swpaul			len    -= FREEBSD32_ALIGN(copylen);
100641502Swpaul
100741502Swpaul			if (CMSG_SPACE(datalen) < clen) {
100841502Swpaul				clen -= CMSG_SPACE(datalen);
100941502Swpaul				cm = (struct cmsghdr *)
101041502Swpaul					((caddr_t)cm + CMSG_SPACE(datalen));
101141502Swpaul			} else {
101241502Swpaul				clen = 0;
101341502Swpaul				cm = NULL;
101441502Swpaul			}
101541502Swpaul		}
101641502Swpaul		m = m->m_next;
101741502Swpaul	}
101841502Swpaul
101941502Swpaul	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
102041502Swpaul
102141502Swpaulexit:
102241502Swpaul	return (error);
102341502Swpaul
102441502Swpaul}
102541502Swpaul
102641502Swpaulint
102741502Swpaulfreebsd32_recvmsg(td, uap)
102841502Swpaul	struct thread *td;
102941502Swpaul	struct freebsd32_recvmsg_args /* {
103041502Swpaul		int	s;
103141502Swpaul		struct	msghdr32 *msg;
103241502Swpaul		int	flags;
103341502Swpaul	} */ *uap;
103441502Swpaul{
103541502Swpaul	struct msghdr msg;
103641502Swpaul	struct msghdr32 m32;
103741502Swpaul	struct iovec *uiov, *iov;
103841502Swpaul	struct mbuf *control = NULL;
103941502Swpaul	struct mbuf **controlp;
104041502Swpaul
104141502Swpaul	int error;
104241502Swpaul	error = copyin(uap->msg, &m32, sizeof(m32));
104341502Swpaul	if (error)
104441502Swpaul		return (error);
104541502Swpaul	error = freebsd32_copyinmsghdr(uap->msg, &msg);
104641502Swpaul	if (error)
104743515Swpaul		return (error);
104841502Swpaul	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
104941502Swpaul	    EMSGSIZE);
105041502Swpaul	if (error)
105141502Swpaul		return (error);
105241502Swpaul	msg.msg_flags = uap->flags;
105341502Swpaul	uiov = msg.msg_iov;
105441502Swpaul	msg.msg_iov = iov;
105541502Swpaul
105641502Swpaul	controlp = (msg.msg_control != NULL) ?  &control : NULL;
105741502Swpaul	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
105841502Swpaul	if (error == 0) {
105941502Swpaul		msg.msg_iov = uiov;
106041502Swpaul
106141502Swpaul		if (control != NULL)
106241502Swpaul			error = freebsd32_copy_msg_out(&msg, control);
106341502Swpaul		else
106441502Swpaul			msg.msg_controllen = 0;
106541502Swpaul
106641502Swpaul		if (error == 0)
106741502Swpaul			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
106841502Swpaul	}
106941502Swpaul	free(iov, M_IOV);
107041502Swpaul
107141502Swpaul	if (control != NULL)
107241502Swpaul		m_freem(control);
107341502Swpaul
107441502Swpaul	return (error);
107541502Swpaul}
107641502Swpaul
107741502Swpaul
107841502Swpaulstatic int
107941502Swpaulfreebsd32_convert_msg_in(struct mbuf **controlp)
108041502Swpaul{
108141502Swpaul	struct mbuf *control = *controlp;
108241502Swpaul	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
108341502Swpaul	void *data;
108441502Swpaul	socklen_t clen = control->m_len, datalen;
108541502Swpaul	int error;
108641502Swpaul
108741502Swpaul	error = 0;
108841502Swpaul	*controlp = NULL;
108941502Swpaul
109041502Swpaul	while (cm != NULL) {
109141502Swpaul		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
109241502Swpaul			error = EINVAL;
109341502Swpaul			break;
109441502Swpaul		}
109541502Swpaul
109641502Swpaul		data = FREEBSD32_CMSG_DATA(cm);
109741502Swpaul		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
109841502Swpaul
109941502Swpaul		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
110041502Swpaul		    cm->cmsg_level);
110141502Swpaul		controlp = &(*controlp)->m_next;
110241502Swpaul
110341502Swpaul		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
110441502Swpaul			clen -= FREEBSD32_CMSG_SPACE(datalen);
110541502Swpaul			cm = (struct cmsghdr *)
110641502Swpaul				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
110741502Swpaul		} else {
110841502Swpaul			clen = 0;
110941502Swpaul			cm = NULL;
111041502Swpaul		}
111141502Swpaul	}
111241502Swpaul
111341502Swpaul	m_freem(control);
111441502Swpaul	return (error);
111541502Swpaul}
111641502Swpaul
111741502Swpaul
111841502Swpaulint
111941502Swpaulfreebsd32_sendmsg(struct thread *td,
112041502Swpaul		  struct freebsd32_sendmsg_args *uap)
112141502Swpaul{
112241502Swpaul	struct msghdr msg;
112341502Swpaul	struct msghdr32 m32;
112441502Swpaul	struct iovec *iov;
112541502Swpaul	struct mbuf *control = NULL;
112641502Swpaul	struct sockaddr *to = NULL;
112741502Swpaul	int error;
112841502Swpaul
112941502Swpaul	error = copyin(uap->msg, &m32, sizeof(m32));
113041502Swpaul	if (error)
113141502Swpaul		return (error);
113241502Swpaul	error = freebsd32_copyinmsghdr(uap->msg, &msg);
113341502Swpaul	if (error)
113441502Swpaul		return (error);
113541502Swpaul	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
113641502Swpaul	    EMSGSIZE);
113741502Swpaul	if (error)
113841502Swpaul		return (error);
113941502Swpaul	msg.msg_iov = iov;
114041502Swpaul	if (msg.msg_name != NULL) {
114141502Swpaul		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
114241502Swpaul		if (error) {
114341502Swpaul			to = NULL;
114441502Swpaul			goto out;
114541502Swpaul		}
114641502Swpaul		msg.msg_name = to;
114741502Swpaul	}
114841502Swpaul
114941502Swpaul	if (msg.msg_control) {
115041502Swpaul		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
115141502Swpaul			error = EINVAL;
115241502Swpaul			goto out;
115341502Swpaul		}
115441502Swpaul
115541502Swpaul		error = sockargs(&control, msg.msg_control,
115641502Swpaul		    msg.msg_controllen, MT_CONTROL);
115741502Swpaul		if (error)
115841502Swpaul			goto out;
115941502Swpaul
116041502Swpaul		error = freebsd32_convert_msg_in(&control);
116141502Swpaul		if (error)
116241502Swpaul			goto out;
116341502Swpaul	}
116441502Swpaul
116541502Swpaul	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
116641502Swpaul	    UIO_USERSPACE);
116741502Swpaul
116841502Swpaulout:
116941502Swpaul	free(iov, M_IOV);
117041502Swpaul	if (to)
117141502Swpaul		free(to, M_SONAME);
117241502Swpaul	return (error);
117341502Swpaul}
117441502Swpaul
117541502Swpaulint
117641502Swpaulfreebsd32_recvfrom(struct thread *td,
117741502Swpaul		   struct freebsd32_recvfrom_args *uap)
117841502Swpaul{
117941502Swpaul	struct msghdr msg;
118041502Swpaul	struct iovec aiov;
118141502Swpaul	int error;
118241502Swpaul
118341502Swpaul	if (uap->fromlenaddr) {
118441502Swpaul		error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
118541502Swpaul		    sizeof(msg.msg_namelen));
118641502Swpaul		if (error)
118741502Swpaul			return (error);
118841502Swpaul	} else {
118941502Swpaul		msg.msg_namelen = 0;
119041502Swpaul	}
119141502Swpaul
119241502Swpaul	msg.msg_name = PTRIN(uap->from);
119341502Swpaul	msg.msg_iov = &aiov;
119441502Swpaul	msg.msg_iovlen = 1;
119541502Swpaul	aiov.iov_base = PTRIN(uap->buf);
119641502Swpaul	aiov.iov_len = uap->len;
119741502Swpaul	msg.msg_control = NULL;
119841502Swpaul	msg.msg_flags = uap->flags;
119941502Swpaul	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
120041502Swpaul	if (error == 0 && uap->fromlenaddr)
120141502Swpaul		error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
120241502Swpaul		    sizeof (msg.msg_namelen));
120341502Swpaul	return (error);
120441502Swpaul}
120541502Swpaul
120641502Swpaulint
120741502Swpaulfreebsd32_settimeofday(struct thread *td,
120841502Swpaul		       struct freebsd32_settimeofday_args *uap)
120941502Swpaul{
121041502Swpaul	struct timeval32 tv32;
121141502Swpaul	struct timeval tv, *tvp;
121241502Swpaul	struct timezone tz, *tzp;
121341502Swpaul	int error;
121441502Swpaul
121541502Swpaul	if (uap->tv) {
121641502Swpaul		error = copyin(uap->tv, &tv32, sizeof(tv32));
121741502Swpaul		if (error)
121842491Swpaul			return (error);
121941502Swpaul		CP(tv32, tv, tv_sec);
122041502Swpaul		CP(tv32, tv, tv_usec);
122141502Swpaul		tvp = &tv;
122241502Swpaul	} else
122341502Swpaul		tvp = NULL;
122441502Swpaul	if (uap->tzp) {
122541502Swpaul		error = copyin(uap->tzp, &tz, sizeof(tz));
122641502Swpaul		if (error)
122741502Swpaul			return (error);
122841502Swpaul		tzp = &tz;
122941502Swpaul	} else
123041502Swpaul		tzp = NULL;
123141502Swpaul	return (kern_settimeofday(td, tvp, tzp));
123241502Swpaul}
123341502Swpaul
123441502Swpaulint
123541502Swpaulfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
123641502Swpaul{
123741502Swpaul	struct timeval32 s32[2];
123841502Swpaul	struct timeval s[2], *sp;
123941502Swpaul	int error;
124041502Swpaul
124141502Swpaul	if (uap->tptr != NULL) {
124241502Swpaul		error = copyin(uap->tptr, s32, sizeof(s32));
124341502Swpaul		if (error)
124441502Swpaul			return (error);
124541502Swpaul		CP(s32[0], s[0], tv_sec);
124641502Swpaul		CP(s32[0], s[0], tv_usec);
124741502Swpaul		CP(s32[1], s[1], tv_sec);
124841502Swpaul		CP(s32[1], s[1], tv_usec);
124941502Swpaul		sp = s;
125041502Swpaul	} else
125141502Swpaul		sp = NULL;
125241502Swpaul	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
125341502Swpaul}
125441502Swpaul
125541502Swpaulint
125641502Swpaulfreebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
125741502Swpaul{
125841502Swpaul	struct timeval32 s32[2];
125941502Swpaul	struct timeval s[2], *sp;
126041502Swpaul	int error;
126141502Swpaul
126241502Swpaul	if (uap->tptr != NULL) {
126341502Swpaul		error = copyin(uap->tptr, s32, sizeof(s32));
126441502Swpaul		if (error)
126541502Swpaul			return (error);
126641502Swpaul		CP(s32[0], s[0], tv_sec);
126741502Swpaul		CP(s32[0], s[0], tv_usec);
126841502Swpaul		CP(s32[1], s[1], tv_sec);
126941502Swpaul		CP(s32[1], s[1], tv_usec);
127041502Swpaul		sp = s;
127141502Swpaul	} else
127241502Swpaul		sp = NULL;
127341502Swpaul	return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
127441502Swpaul}
127541502Swpaul
127641502Swpaulint
127741502Swpaulfreebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
127841502Swpaul{
127941502Swpaul	struct timeval32 s32[2];
128042491Swpaul	struct timeval s[2], *sp;
128141502Swpaul	int error;
128241502Swpaul
128341502Swpaul	if (uap->tptr != NULL) {
128441502Swpaul		error = copyin(uap->tptr, s32, sizeof(s32));
128541502Swpaul		if (error)
128641502Swpaul			return (error);
128741502Swpaul		CP(s32[0], s[0], tv_sec);
128841502Swpaul		CP(s32[0], s[0], tv_usec);
128942048Swpaul		CP(s32[1], s[1], tv_sec);
129042048Swpaul		CP(s32[1], s[1], tv_usec);
129142048Swpaul		sp = s;
129242048Swpaul	} else
129342048Swpaul		sp = NULL;
129442048Swpaul	return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
129542048Swpaul}
129642048Swpaul
129742048Swpaulint
129841502Swpaulfreebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)
129941502Swpaul{
130041502Swpaul	struct timeval32 s32[2];
130141502Swpaul	struct timeval s[2], *sp;
130241502Swpaul	int error;
130341502Swpaul
130441502Swpaul	if (uap->times != NULL) {
130541502Swpaul		error = copyin(uap->times, s32, sizeof(s32));
130642260Swpaul		if (error)
130742491Swpaul			return (error);
130841502Swpaul		CP(s32[0], s[0], tv_sec);
130941502Swpaul		CP(s32[0], s[0], tv_usec);
131041502Swpaul		CP(s32[1], s[1], tv_sec);
131141502Swpaul		CP(s32[1], s[1], tv_usec);
131241502Swpaul		sp = s;
131341502Swpaul	} else
131441502Swpaul		sp = NULL;
131541502Swpaul	return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,
131641502Swpaul		sp, UIO_SYSSPACE));
131741502Swpaul}
131841502Swpaul
131941502Swpaulint
132041502Swpaulfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
132141502Swpaul{
132241502Swpaul	struct timeval32 tv32;
132341502Swpaul	struct timeval delta, olddelta, *deltap;
132441502Swpaul	int error;
132541502Swpaul
132641502Swpaul	if (uap->delta) {
132741502Swpaul		error = copyin(uap->delta, &tv32, sizeof(tv32));
132841502Swpaul		if (error)
132941502Swpaul			return (error);
133041502Swpaul		CP(tv32, delta, tv_sec);
133141502Swpaul		CP(tv32, delta, tv_usec);
133241502Swpaul		deltap = &delta;
133341502Swpaul	} else
133441502Swpaul		deltap = NULL;
133541502Swpaul	error = kern_adjtime(td, deltap, &olddelta);
133641502Swpaul	if (uap->olddelta && error == 0) {
133741502Swpaul		CP(olddelta, tv32, tv_sec);
133841502Swpaul		CP(olddelta, tv32, tv_usec);
133941502Swpaul		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
134041502Swpaul	}
134141502Swpaul	return (error);
134241502Swpaul}
134341502Swpaul
134441502Swpaul#ifdef COMPAT_FREEBSD4
134541502Swpaulint
134641502Swpaulfreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
134741502Swpaul{
134841502Swpaul	struct statfs32 s32;
134941502Swpaul	struct statfs s;
135041502Swpaul	int error;
135141502Swpaul
135241502Swpaul	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
135341502Swpaul	if (error)
135441502Swpaul		return (error);
135541502Swpaul	copy_statfs(&s, &s32);
135641502Swpaul	return (copyout(&s32, uap->buf, sizeof(s32)));
135741502Swpaul}
135841502Swpaul#endif
135941502Swpaul
136041502Swpaul#ifdef COMPAT_FREEBSD4
136141502Swpaulint
136241502Swpaulfreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
136341502Swpaul{
136441502Swpaul	struct statfs32 s32;
136541502Swpaul	struct statfs s;
136641502Swpaul	int error;
136741502Swpaul
136841502Swpaul	error = kern_fstatfs(td, uap->fd, &s);
136941502Swpaul	if (error)
137041502Swpaul		return (error);
137141502Swpaul	copy_statfs(&s, &s32);
137241502Swpaul	return (copyout(&s32, uap->buf, sizeof(s32)));
137341502Swpaul}
137441502Swpaul#endif
137541502Swpaul
137641502Swpaul#ifdef COMPAT_FREEBSD4
137741502Swpaulint
137841502Swpaulfreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
137941502Swpaul{
138041502Swpaul	struct statfs32 s32;
138141502Swpaul	struct statfs s;
138241502Swpaul	fhandle_t fh;
138341502Swpaul	int error;
138441502Swpaul
138542491Swpaul	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
138641502Swpaul		return (error);
138741502Swpaul	error = kern_fhstatfs(td, fh, &s);
138841502Swpaul	if (error)
138941502Swpaul		return (error);
139041502Swpaul	copy_statfs(&s, &s32);
139141502Swpaul	return (copyout(&s32, uap->buf, sizeof(s32)));
139241502Swpaul}
139341502Swpaul#endif
139441502Swpaul
139541502Swpaulint
139641502Swpaulfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
139741502Swpaul{
139841502Swpaul	struct pread_args ap;
139941502Swpaul
140041502Swpaul	ap.fd = uap->fd;
140141502Swpaul	ap.buf = uap->buf;
140241502Swpaul	ap.nbyte = uap->nbyte;
140341502Swpaul	ap.offset = PAIR32TO64(off_t,uap->offset);
140441502Swpaul	return (pread(td, &ap));
140541502Swpaul}
140641502Swpaul
140741502Swpaulint
140841502Swpaulfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
140941502Swpaul{
141041502Swpaul	struct pwrite_args ap;
141141502Swpaul
141241502Swpaul	ap.fd = uap->fd;
141341502Swpaul	ap.buf = uap->buf;
141441502Swpaul	ap.nbyte = uap->nbyte;
141541502Swpaul	ap.offset = PAIR32TO64(off_t,uap->offset);
141641502Swpaul	return (pwrite(td, &ap));
141741502Swpaul}
141841502Swpaul
141941502Swpaulint
142041502Swpaulfreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
142141502Swpaul{
142241502Swpaul	int error;
142341502Swpaul	struct lseek_args ap;
142441502Swpaul	off_t pos;
142541502Swpaul
142641502Swpaul	ap.fd = uap->fd;
142741502Swpaul	ap.offset = PAIR32TO64(off_t,uap->offset);
142841502Swpaul	ap.whence = uap->whence;
142941502Swpaul	error = lseek(td, &ap);
143041502Swpaul	/* Expand the quad return into two parts for eax and edx */
143141502Swpaul	pos = *(off_t *)(td->td_retval);
143241502Swpaul	td->td_retval[RETVAL_LO] = pos & 0xffffffff;	/* %eax */
143341502Swpaul	td->td_retval[RETVAL_HI] = pos >> 32;		/* %edx */
143441502Swpaul	return error;
143541502Swpaul}
143641502Swpaul
143741502Swpaulint
143841502Swpaulfreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
143941502Swpaul{
144041502Swpaul	struct truncate_args ap;
144141502Swpaul
144241502Swpaul	ap.path = uap->path;
144341502Swpaul	ap.length = PAIR32TO64(off_t,uap->length);
144441502Swpaul	return (truncate(td, &ap));
144541502Swpaul}
144641502Swpaul
144741502Swpaulint
144841502Swpaulfreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
144941502Swpaul{
145041502Swpaul	struct ftruncate_args ap;
145141502Swpaul
145241502Swpaul	ap.fd = uap->fd;
145341502Swpaul	ap.length = PAIR32TO64(off_t,uap->length);
145441502Swpaul	return (ftruncate(td, &ap));
145541502Swpaul}
145641502Swpaul
145741502Swpaul#ifdef COMPAT_43
145841502Swpaulint
145941502Swpaulofreebsd32_getdirentries(struct thread *td,
146041502Swpaul    struct ofreebsd32_getdirentries_args *uap)
146141502Swpaul{
146241502Swpaul	struct ogetdirentries_args ap;
146341502Swpaul	int error;
146441502Swpaul	long loff;
146541502Swpaul	int32_t loff_cut;
146641502Swpaul
146741502Swpaul	ap.fd = uap->fd;
146841502Swpaul	ap.buf = uap->buf;
146941502Swpaul	ap.count = uap->count;
147041502Swpaul	ap.basep = NULL;
147141502Swpaul	error = kern_ogetdirentries(td, &ap, &loff);
147241502Swpaul	if (error == 0) {
147341502Swpaul		loff_cut = loff;
147441502Swpaul		error = copyout(&loff_cut, uap->basep, sizeof(int32_t));
147541502Swpaul	}
147641502Swpaul	return (error);
147741502Swpaul}
147841502Swpaul#endif
147941502Swpaul
148041502Swpaulint
148141502Swpaulfreebsd32_getdirentries(struct thread *td,
148241502Swpaul    struct freebsd32_getdirentries_args *uap)
148341502Swpaul{
148441502Swpaul	long base;
148541502Swpaul	int32_t base32;
148641502Swpaul	int error;
148741502Swpaul
148841502Swpaul	error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base);
148941502Swpaul	if (error)
149041502Swpaul		return (error);
149141502Swpaul	if (uap->basep != NULL) {
149241502Swpaul		base32 = base;
149341502Swpaul		error = copyout(&base32, uap->basep, sizeof(int32_t));
149441502Swpaul	}
149541502Swpaul	return (error);
149641502Swpaul}
149741502Swpaul
149841502Swpaul#ifdef COMPAT_FREEBSD6
149941502Swpaul/* versions with the 'int pad' argument */
150041502Swpaulint
150141502Swpaulfreebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap)
150241502Swpaul{
150341502Swpaul	struct pread_args ap;
150441502Swpaul
150541502Swpaul	ap.fd = uap->fd;
150641502Swpaul	ap.buf = uap->buf;
150741502Swpaul	ap.nbyte = uap->nbyte;
150841502Swpaul	ap.offset = PAIR32TO64(off_t,uap->offset);
150941502Swpaul	return (pread(td, &ap));
151041502Swpaul}
151141502Swpaul
151241502Swpaulint
151341502Swpaulfreebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap)
151441502Swpaul{
151541502Swpaul	struct pwrite_args ap;
151641502Swpaul
151741502Swpaul	ap.fd = uap->fd;
151841502Swpaul	ap.buf = uap->buf;
151941502Swpaul	ap.nbyte = uap->nbyte;
152041502Swpaul	ap.offset = PAIR32TO64(off_t,uap->offset);
152141502Swpaul	return (pwrite(td, &ap));
152241502Swpaul}
152341502Swpaul
152441502Swpaulint
152541502Swpaulfreebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap)
152641502Swpaul{
152741502Swpaul	int error;
152841502Swpaul	struct lseek_args ap;
152941502Swpaul	off_t pos;
153041502Swpaul
153141502Swpaul	ap.fd = uap->fd;
153241502Swpaul	ap.offset = PAIR32TO64(off_t,uap->offset);
153341502Swpaul	ap.whence = uap->whence;
153441502Swpaul	error = lseek(td, &ap);
153541502Swpaul	/* Expand the quad return into two parts for eax and edx */
153641502Swpaul	pos = *(off_t *)(td->td_retval);
153741502Swpaul	td->td_retval[RETVAL_LO] = pos & 0xffffffff;	/* %eax */
153841502Swpaul	td->td_retval[RETVAL_HI] = pos >> 32;		/* %edx */
153941502Swpaul	return error;
154041502Swpaul}
154141502Swpaul
154241502Swpaulint
154341502Swpaulfreebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap)
154441502Swpaul{
154541502Swpaul	struct truncate_args ap;
154641502Swpaul
154741502Swpaul	ap.path = uap->path;
154841502Swpaul	ap.length = PAIR32TO64(off_t,uap->length);
154941502Swpaul	return (truncate(td, &ap));
155041502Swpaul}
155141502Swpaul
155241502Swpaulint
155341502Swpaulfreebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap)
155441502Swpaul{
155541502Swpaul	struct ftruncate_args ap;
155641502Swpaul
155741502Swpaul	ap.fd = uap->fd;
155841502Swpaul	ap.length = PAIR32TO64(off_t,uap->length);
155941502Swpaul	return (ftruncate(td, &ap));
156041502Swpaul}
156141502Swpaul#endif /* COMPAT_FREEBSD6 */
156241502Swpaul
156341502Swpaulstruct sf_hdtr32 {
156441502Swpaul	uint32_t headers;
156541502Swpaul	int hdr_cnt;
156641502Swpaul	uint32_t trailers;
156742491Swpaul	int trl_cnt;
156841502Swpaul};
156941502Swpaul
157041502Swpaulstatic int
157141502Swpaulfreebsd32_do_sendfile(struct thread *td,
157241502Swpaul    struct freebsd32_sendfile_args *uap, int compat)
157341502Swpaul{
157441502Swpaul	struct sendfile_args ap;
157541502Swpaul	struct sf_hdtr32 hdtr32;
157641502Swpaul	struct sf_hdtr hdtr;
157741502Swpaul	struct uio *hdr_uio, *trl_uio;
157841502Swpaul	struct iovec32 *iov32;
157941502Swpaul	int error;
158041502Swpaul
158141502Swpaul	hdr_uio = trl_uio = NULL;
158241502Swpaul
158341502Swpaul	ap.fd = uap->fd;
158441502Swpaul	ap.s = uap->s;
158541502Swpaul	ap.offset = PAIR32TO64(off_t,uap->offset);
158641502Swpaul	ap.nbytes = uap->nbytes;
158741502Swpaul	ap.hdtr = (struct sf_hdtr *)uap->hdtr;		/* XXX not used */
158841502Swpaul	ap.sbytes = uap->sbytes;
158941502Swpaul	ap.flags = uap->flags;
159041502Swpaul
159141502Swpaul	if (uap->hdtr != NULL) {
159241502Swpaul		error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
159341502Swpaul		if (error)
159441502Swpaul			goto out;
159541502Swpaul		PTRIN_CP(hdtr32, hdtr, headers);
159641502Swpaul		CP(hdtr32, hdtr, hdr_cnt);
159741502Swpaul		PTRIN_CP(hdtr32, hdtr, trailers);
159841502Swpaul		CP(hdtr32, hdtr, trl_cnt);
159941502Swpaul
160041502Swpaul		if (hdtr.headers != NULL) {
160141502Swpaul			iov32 = PTRIN(hdtr32.headers);
160241502Swpaul			error = freebsd32_copyinuio(iov32,
160341502Swpaul			    hdtr32.hdr_cnt, &hdr_uio);
160441502Swpaul			if (error)
160541502Swpaul				goto out;
160641502Swpaul		}
160741502Swpaul		if (hdtr.trailers != NULL) {
160841502Swpaul			iov32 = PTRIN(hdtr32.trailers);
160941502Swpaul			error = freebsd32_copyinuio(iov32,
161041502Swpaul			    hdtr32.trl_cnt, &trl_uio);
161141502Swpaul			if (error)
161241502Swpaul				goto out;
161341502Swpaul		}
161441502Swpaul	}
161541502Swpaul
161641502Swpaul	error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
161741502Swpaulout:
161841502Swpaul	if (hdr_uio)
161941502Swpaul		free(hdr_uio, M_IOV);
162041502Swpaul	if (trl_uio)
162141502Swpaul		free(trl_uio, M_IOV);
162241502Swpaul	return (error);
162341502Swpaul}
162441502Swpaul
162541502Swpaul#ifdef COMPAT_FREEBSD4
162641502Swpaulint
162741502Swpaulfreebsd4_freebsd32_sendfile(struct thread *td,
162842491Swpaul    struct freebsd4_freebsd32_sendfile_args *uap)
162942491Swpaul{
163041502Swpaul	return (freebsd32_do_sendfile(td,
163141502Swpaul	    (struct freebsd32_sendfile_args *)uap, 1));
163241502Swpaul}
163341526Swpaul#endif
163441526Swpaul
163541526Swpaulint
163641526Swpaulfreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
163741526Swpaul{
163841502Swpaul
163941502Swpaul	return (freebsd32_do_sendfile(td, uap, 0));
164042491Swpaul}
164141502Swpaul
164241502Swpaulstatic void
164341502Swpaulcopy_stat(struct stat *in, struct stat32 *out)
164441502Swpaul{
164541502Swpaul
164641502Swpaul	CP(*in, *out, st_dev);
164741502Swpaul	CP(*in, *out, st_ino);
164841502Swpaul	CP(*in, *out, st_mode);
164941502Swpaul	CP(*in, *out, st_nlink);
165041502Swpaul	CP(*in, *out, st_uid);
165141502Swpaul	CP(*in, *out, st_gid);
165241502Swpaul	CP(*in, *out, st_rdev);
165341502Swpaul	TS_CP(*in, *out, st_atim);
165441502Swpaul	TS_CP(*in, *out, st_mtim);
165541502Swpaul	TS_CP(*in, *out, st_ctim);
165641502Swpaul	CP(*in, *out, st_size);
165741502Swpaul	CP(*in, *out, st_blocks);
165841502Swpaul	CP(*in, *out, st_blksize);
165941502Swpaul	CP(*in, *out, st_flags);
166041502Swpaul	CP(*in, *out, st_gen);
166141502Swpaul	TS_CP(*in, *out, st_birthtim);
166241502Swpaul}
166341502Swpaul
166441502Swpaul#ifdef COMPAT_43
166541502Swpaulstatic void
166641502Swpaulcopy_ostat(struct stat *in, struct ostat32 *out)
166741502Swpaul{
166841502Swpaul
166941502Swpaul	CP(*in, *out, st_dev);
167041502Swpaul	CP(*in, *out, st_ino);
167141502Swpaul	CP(*in, *out, st_mode);
167241502Swpaul	CP(*in, *out, st_nlink);
167341502Swpaul	CP(*in, *out, st_uid);
167441502Swpaul	CP(*in, *out, st_gid);
167541502Swpaul	CP(*in, *out, st_rdev);
167641502Swpaul	CP(*in, *out, st_size);
167741502Swpaul	TS_CP(*in, *out, st_atim);
167841502Swpaul	TS_CP(*in, *out, st_mtim);
167941502Swpaul	TS_CP(*in, *out, st_ctim);
168041502Swpaul	CP(*in, *out, st_blksize);
168141502Swpaul	CP(*in, *out, st_blocks);
168241502Swpaul	CP(*in, *out, st_flags);
168341502Swpaul	CP(*in, *out, st_gen);
168441502Swpaul}
168541502Swpaul#endif
168641502Swpaul
168741502Swpaulint
168841502Swpaulfreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
168941502Swpaul{
169041502Swpaul	struct stat sb;
169141502Swpaul	struct stat32 sb32;
169241502Swpaul	int error;
169341502Swpaul
169441502Swpaul	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
169541502Swpaul	if (error)
169641502Swpaul		return (error);
169741502Swpaul	copy_stat(&sb, &sb32);
169841502Swpaul	error = copyout(&sb32, uap->ub, sizeof (sb32));
169941502Swpaul	return (error);
170041502Swpaul}
170141502Swpaul
170241502Swpaul#ifdef COMPAT_43
170341502Swpaulint
170441502Swpaulofreebsd32_stat(struct thread *td, struct ofreebsd32_stat_args *uap)
170541502Swpaul{
170641502Swpaul	struct stat sb;
170741502Swpaul	struct ostat32 sb32;
170841502Swpaul	int error;
170941502Swpaul
171041502Swpaul	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
171141502Swpaul	if (error)
171241502Swpaul		return (error);
171341502Swpaul	copy_ostat(&sb, &sb32);
171441502Swpaul	error = copyout(&sb32, uap->ub, sizeof (sb32));
171541502Swpaul	return (error);
171641502Swpaul}
171741502Swpaul#endif
171841502Swpaul
171941502Swpaulint
172041502Swpaulfreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
172141502Swpaul{
172241502Swpaul	struct stat ub;
172341502Swpaul	struct stat32 ub32;
172441502Swpaul	int error;
172541502Swpaul
172641502Swpaul	error = kern_fstat(td, uap->fd, &ub);
172741502Swpaul	if (error)
172841502Swpaul		return (error);
172941502Swpaul	copy_stat(&ub, &ub32);
173041502Swpaul	error = copyout(&ub32, uap->ub, sizeof(ub32));
173141502Swpaul	return (error);
173241502Swpaul}
173341502Swpaul
173441502Swpaul#ifdef COMPAT_43
173541502Swpaulint
173641502Swpaulofreebsd32_fstat(struct thread *td, struct ofreebsd32_fstat_args *uap)
173741502Swpaul{
173841502Swpaul	struct stat ub;
173941502Swpaul	struct ostat32 ub32;
174041502Swpaul	int error;
174141502Swpaul
174241502Swpaul	error = kern_fstat(td, uap->fd, &ub);
174341502Swpaul	if (error)
174441502Swpaul		return (error);
174541502Swpaul	copy_ostat(&ub, &ub32);
174641502Swpaul	error = copyout(&ub32, uap->ub, sizeof(ub32));
174741502Swpaul	return (error);
174841502Swpaul}
174941502Swpaul#endif
175041502Swpaul
175141502Swpaulint
175241502Swpaulfreebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
175341502Swpaul{
175441502Swpaul	struct stat ub;
175541502Swpaul	struct stat32 ub32;
175641502Swpaul	int error;
175741502Swpaul
175841502Swpaul	error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE, &ub);
175941502Swpaul	if (error)
176041502Swpaul		return (error);
176141502Swpaul	copy_stat(&ub, &ub32);
176241502Swpaul	error = copyout(&ub32, uap->buf, sizeof(ub32));
176341502Swpaul	return (error);
176441502Swpaul}
176541502Swpaul
176641502Swpaulint
176741502Swpaulfreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
176841502Swpaul{
176941502Swpaul	struct stat sb;
177041502Swpaul	struct stat32 sb32;
177141502Swpaul	int error;
177241502Swpaul
177341502Swpaul	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
177441502Swpaul	if (error)
177541502Swpaul		return (error);
177641502Swpaul	copy_stat(&sb, &sb32);
177741502Swpaul	error = copyout(&sb32, uap->ub, sizeof (sb32));
177841502Swpaul	return (error);
177941502Swpaul}
178041502Swpaul
178141502Swpaul#ifdef COMPAT_43
178241502Swpaulint
178341502Swpaulofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap)
178441502Swpaul{
178541502Swpaul	struct stat sb;
178641502Swpaul	struct ostat32 sb32;
178741502Swpaul	int error;
178841502Swpaul
178941502Swpaul	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
179041502Swpaul	if (error)
179141502Swpaul		return (error);
179241502Swpaul	copy_ostat(&sb, &sb32);
179341502Swpaul	error = copyout(&sb32, uap->ub, sizeof (sb32));
179441502Swpaul	return (error);
179541502Swpaul}
179641502Swpaul#endif
179741502Swpaul
179841502Swpaulint
179941502Swpaulfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
180041502Swpaul{
180141502Swpaul	int error, name[CTL_MAXNAME];
180241502Swpaul	size_t j, oldlen;
180341502Swpaul
180441502Swpaul	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
180541502Swpaul		return (EINVAL);
180641502Swpaul 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
180741502Swpaul 	if (error)
180841502Swpaul		return (error);
180941502Swpaul	if (uap->oldlenp)
181041502Swpaul		oldlen = fuword32(uap->oldlenp);
181141502Swpaul	else
181241502Swpaul		oldlen = 0;
181341502Swpaul	error = userland_sysctl(td, name, uap->namelen,
181441502Swpaul		uap->old, &oldlen, 1,
181541502Swpaul		uap->new, uap->newlen, &j, SCTL_MASK32);
181641502Swpaul	if (error && error != ENOMEM)
181741502Swpaul		return (error);
181841502Swpaul	if (uap->oldlenp)
181941502Swpaul		suword32(uap->oldlenp, j);
182041502Swpaul	return (0);
182141502Swpaul}
182241502Swpaul
182341502Swpaulint
182441502Swpaulfreebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
182541502Swpaul{
182641502Swpaul	uint32_t version;
182741502Swpaul	int error;
182841502Swpaul	struct jail j;
182941502Swpaul
183041502Swpaul	error = copyin(uap->jail, &version, sizeof(uint32_t));
183141502Swpaul	if (error)
183241502Swpaul		return (error);
183341502Swpaul
183441502Swpaul	switch (version) {
183541502Swpaul	case 0:
183641502Swpaul	{
183741502Swpaul		/* FreeBSD single IPv4 jails. */
183841502Swpaul		struct jail32_v0 j32_v0;
183941502Swpaul
184041502Swpaul		bzero(&j, sizeof(struct jail));
184141502Swpaul		error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));
184241502Swpaul		if (error)
184341502Swpaul			return (error);
184441502Swpaul		CP(j32_v0, j, version);
184541502Swpaul		PTRIN_CP(j32_v0, j, path);
184641502Swpaul		PTRIN_CP(j32_v0, j, hostname);
184741502Swpaul		j.ip4s = j32_v0.ip_number;
184841502Swpaul		break;
184941502Swpaul	}
185041502Swpaul
185141502Swpaul	case 1:
185241502Swpaul		/*
185341502Swpaul		 * Version 1 was used by multi-IPv4 jail implementations
185441502Swpaul		 * that never made it into the official kernel.
185541502Swpaul		 */
185641502Swpaul		return (EINVAL);
185741502Swpaul
185841502Swpaul	case 2:	/* JAIL_API_VERSION */
185941502Swpaul	{
186041502Swpaul		/* FreeBSD multi-IPv4/IPv6,noIP jails. */
186141502Swpaul		struct jail32 j32;
186241502Swpaul
186341502Swpaul		error = copyin(uap->jail, &j32, sizeof(struct jail32));
186441502Swpaul		if (error)
186541502Swpaul			return (error);
186641502Swpaul		CP(j32, j, version);
186741502Swpaul		PTRIN_CP(j32, j, path);
186841502Swpaul		PTRIN_CP(j32, j, hostname);
186941502Swpaul		PTRIN_CP(j32, j, jailname);
187041502Swpaul		CP(j32, j, ip4s);
187141502Swpaul		CP(j32, j, ip6s);
187241502Swpaul		PTRIN_CP(j32, j, ip4);
187341502Swpaul		PTRIN_CP(j32, j, ip6);
187441502Swpaul		break;
187541502Swpaul	}
187641502Swpaul
187741502Swpaul	default:
187841502Swpaul		/* Sci-Fi jails are not supported, sorry. */
187941502Swpaul		return (EINVAL);
188041502Swpaul	}
188141502Swpaul	return (kern_jail(td, &j));
188241502Swpaul}
188341502Swpaul
188441502Swpaulint
188541502Swpaulfreebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)
188641502Swpaul{
188741502Swpaul	struct uio *auio;
188841502Swpaul	int error;
188941502Swpaul
189041502Swpaul	/* Check that we have an even number of iovecs. */
189141502Swpaul	if (uap->iovcnt & 1)
189241502Swpaul		return (EINVAL);
189341502Swpaul
189441502Swpaul	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
189541502Swpaul	if (error)
189641502Swpaul		return (error);
189741502Swpaul	error = kern_jail_set(td, auio, uap->flags);
189841502Swpaul	free(auio, M_IOV);
189941502Swpaul	return (error);
190041502Swpaul}
190141502Swpaul
190241502Swpaulint
190341502Swpaulfreebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)
190441502Swpaul{
190541502Swpaul	struct iovec32 iov32;
190641502Swpaul	struct uio *auio;
190741502Swpaul	int error, i;
190841502Swpaul
190941502Swpaul	/* Check that we have an even number of iovecs. */
191041502Swpaul	if (uap->iovcnt & 1)
191141502Swpaul		return (EINVAL);
191241502Swpaul
191341502Swpaul	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
191441502Swpaul	if (error)
191541502Swpaul		return (error);
191641502Swpaul	error = kern_jail_get(td, auio, uap->flags);
191741502Swpaul	if (error == 0)
191841502Swpaul		for (i = 0; i < uap->iovcnt; i++) {
191941502Swpaul			PTROUT_CP(auio->uio_iov[i], iov32, iov_base);
192041502Swpaul			CP(auio->uio_iov[i], iov32, iov_len);
192141502Swpaul			error = copyout(&iov32, uap->iovp + i, sizeof(iov32));
192241502Swpaul			if (error != 0)
192341502Swpaul				break;
192441502Swpaul		}
192541502Swpaul	free(auio, M_IOV);
192641502Swpaul	return (error);
192741502Swpaul}
192841502Swpaul
192941502Swpaulint
193041502Swpaulfreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
193141502Swpaul{
193241502Swpaul	struct sigaction32 s32;
193341502Swpaul	struct sigaction sa, osa, *sap;
193441502Swpaul	int error;
193541502Swpaul
193641502Swpaul	if (uap->act) {
193741502Swpaul		error = copyin(uap->act, &s32, sizeof(s32));
193841502Swpaul		if (error)
193941502Swpaul			return (error);
194041502Swpaul		sa.sa_handler = PTRIN(s32.sa_u);
194141502Swpaul		CP(s32, sa, sa_flags);
194241502Swpaul		CP(s32, sa, sa_mask);
194341502Swpaul		sap = &sa;
194441502Swpaul	} else
194541502Swpaul		sap = NULL;
194641502Swpaul	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
194741502Swpaul	if (error == 0 && uap->oact != NULL) {
194841502Swpaul		s32.sa_u = PTROUT(osa.sa_handler);
194941502Swpaul		CP(osa, s32, sa_flags);
195041502Swpaul		CP(osa, s32, sa_mask);
195141502Swpaul		error = copyout(&s32, uap->oact, sizeof(s32));
195241502Swpaul	}
195341502Swpaul	return (error);
195441502Swpaul}
195541502Swpaul
195641502Swpaul#ifdef COMPAT_FREEBSD4
195741502Swpaulint
195841502Swpaulfreebsd4_freebsd32_sigaction(struct thread *td,
1959			     struct freebsd4_freebsd32_sigaction_args *uap)
1960{
1961	struct sigaction32 s32;
1962	struct sigaction sa, osa, *sap;
1963	int error;
1964
1965	if (uap->act) {
1966		error = copyin(uap->act, &s32, sizeof(s32));
1967		if (error)
1968			return (error);
1969		sa.sa_handler = PTRIN(s32.sa_u);
1970		CP(s32, sa, sa_flags);
1971		CP(s32, sa, sa_mask);
1972		sap = &sa;
1973	} else
1974		sap = NULL;
1975	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1976	if (error == 0 && uap->oact != NULL) {
1977		s32.sa_u = PTROUT(osa.sa_handler);
1978		CP(osa, s32, sa_flags);
1979		CP(osa, s32, sa_mask);
1980		error = copyout(&s32, uap->oact, sizeof(s32));
1981	}
1982	return (error);
1983}
1984#endif
1985
1986#ifdef COMPAT_43
1987struct osigaction32 {
1988	u_int32_t	sa_u;
1989	osigset_t	sa_mask;
1990	int		sa_flags;
1991};
1992
1993#define	ONSIG	32
1994
1995int
1996ofreebsd32_sigaction(struct thread *td,
1997			     struct ofreebsd32_sigaction_args *uap)
1998{
1999	struct osigaction32 s32;
2000	struct sigaction sa, osa, *sap;
2001	int error;
2002
2003	if (uap->signum <= 0 || uap->signum >= ONSIG)
2004		return (EINVAL);
2005
2006	if (uap->nsa) {
2007		error = copyin(uap->nsa, &s32, sizeof(s32));
2008		if (error)
2009			return (error);
2010		sa.sa_handler = PTRIN(s32.sa_u);
2011		CP(s32, sa, sa_flags);
2012		OSIG2SIG(s32.sa_mask, sa.sa_mask);
2013		sap = &sa;
2014	} else
2015		sap = NULL;
2016	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2017	if (error == 0 && uap->osa != NULL) {
2018		s32.sa_u = PTROUT(osa.sa_handler);
2019		CP(osa, s32, sa_flags);
2020		SIG2OSIG(osa.sa_mask, s32.sa_mask);
2021		error = copyout(&s32, uap->osa, sizeof(s32));
2022	}
2023	return (error);
2024}
2025
2026int
2027ofreebsd32_sigprocmask(struct thread *td,
2028			       struct ofreebsd32_sigprocmask_args *uap)
2029{
2030	sigset_t set, oset;
2031	int error;
2032
2033	OSIG2SIG(uap->mask, set);
2034	error = kern_sigprocmask(td, uap->how, &set, &oset, SIGPROCMASK_OLD);
2035	SIG2OSIG(oset, td->td_retval[0]);
2036	return (error);
2037}
2038
2039int
2040ofreebsd32_sigpending(struct thread *td,
2041			      struct ofreebsd32_sigpending_args *uap)
2042{
2043	struct proc *p = td->td_proc;
2044	sigset_t siglist;
2045
2046	PROC_LOCK(p);
2047	siglist = p->p_siglist;
2048	SIGSETOR(siglist, td->td_siglist);
2049	PROC_UNLOCK(p);
2050	SIG2OSIG(siglist, td->td_retval[0]);
2051	return (0);
2052}
2053
2054struct sigvec32 {
2055	u_int32_t	sv_handler;
2056	int		sv_mask;
2057	int		sv_flags;
2058};
2059
2060int
2061ofreebsd32_sigvec(struct thread *td,
2062			  struct ofreebsd32_sigvec_args *uap)
2063{
2064	struct sigvec32 vec;
2065	struct sigaction sa, osa, *sap;
2066	int error;
2067
2068	if (uap->signum <= 0 || uap->signum >= ONSIG)
2069		return (EINVAL);
2070
2071	if (uap->nsv) {
2072		error = copyin(uap->nsv, &vec, sizeof(vec));
2073		if (error)
2074			return (error);
2075		sa.sa_handler = PTRIN(vec.sv_handler);
2076		OSIG2SIG(vec.sv_mask, sa.sa_mask);
2077		sa.sa_flags = vec.sv_flags;
2078		sa.sa_flags ^= SA_RESTART;
2079		sap = &sa;
2080	} else
2081		sap = NULL;
2082	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2083	if (error == 0 && uap->osv != NULL) {
2084		vec.sv_handler = PTROUT(osa.sa_handler);
2085		SIG2OSIG(osa.sa_mask, vec.sv_mask);
2086		vec.sv_flags = osa.sa_flags;
2087		vec.sv_flags &= ~SA_NOCLDWAIT;
2088		vec.sv_flags ^= SA_RESTART;
2089		error = copyout(&vec, uap->osv, sizeof(vec));
2090	}
2091	return (error);
2092}
2093
2094int
2095ofreebsd32_sigblock(struct thread *td,
2096			    struct ofreebsd32_sigblock_args *uap)
2097{
2098	sigset_t set, oset;
2099
2100	OSIG2SIG(uap->mask, set);
2101	kern_sigprocmask(td, SIG_BLOCK, &set, &oset, 0);
2102	SIG2OSIG(oset, td->td_retval[0]);
2103	return (0);
2104}
2105
2106int
2107ofreebsd32_sigsetmask(struct thread *td,
2108			      struct ofreebsd32_sigsetmask_args *uap)
2109{
2110	sigset_t set, oset;
2111
2112	OSIG2SIG(uap->mask, set);
2113	kern_sigprocmask(td, SIG_SETMASK, &set, &oset, 0);
2114	SIG2OSIG(oset, td->td_retval[0]);
2115	return (0);
2116}
2117
2118int
2119ofreebsd32_sigsuspend(struct thread *td,
2120			      struct ofreebsd32_sigsuspend_args *uap)
2121{
2122	sigset_t mask;
2123
2124	OSIG2SIG(uap->mask, mask);
2125	return (kern_sigsuspend(td, mask));
2126}
2127
2128struct sigstack32 {
2129	u_int32_t	ss_sp;
2130	int		ss_onstack;
2131};
2132
2133int
2134ofreebsd32_sigstack(struct thread *td,
2135			    struct ofreebsd32_sigstack_args *uap)
2136{
2137	struct sigstack32 s32;
2138	struct sigstack nss, oss;
2139	int error = 0, unss;
2140
2141	if (uap->nss != NULL) {
2142		error = copyin(uap->nss, &s32, sizeof(s32));
2143		if (error)
2144			return (error);
2145		nss.ss_sp = PTRIN(s32.ss_sp);
2146		CP(s32, nss, ss_onstack);
2147		unss = 1;
2148	} else {
2149		unss = 0;
2150	}
2151	oss.ss_sp = td->td_sigstk.ss_sp;
2152	oss.ss_onstack = sigonstack(cpu_getstack(td));
2153	if (unss) {
2154		td->td_sigstk.ss_sp = nss.ss_sp;
2155		td->td_sigstk.ss_size = 0;
2156		td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK);
2157		td->td_pflags |= TDP_ALTSTACK;
2158	}
2159	if (uap->oss != NULL) {
2160		s32.ss_sp = PTROUT(oss.ss_sp);
2161		CP(oss, s32, ss_onstack);
2162		error = copyout(&s32, uap->oss, sizeof(s32));
2163	}
2164	return (error);
2165}
2166#endif
2167
2168int
2169freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
2170{
2171	struct timespec32 rmt32, rqt32;
2172	struct timespec rmt, rqt;
2173	int error;
2174
2175	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
2176	if (error)
2177		return (error);
2178
2179	CP(rqt32, rqt, tv_sec);
2180	CP(rqt32, rqt, tv_nsec);
2181
2182	if (uap->rmtp &&
2183	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
2184		return (EFAULT);
2185	error = kern_nanosleep(td, &rqt, &rmt);
2186	if (error && uap->rmtp) {
2187		int error2;
2188
2189		CP(rmt, rmt32, tv_sec);
2190		CP(rmt, rmt32, tv_nsec);
2191
2192		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
2193		if (error2)
2194			error = error2;
2195	}
2196	return (error);
2197}
2198
2199int
2200freebsd32_clock_gettime(struct thread *td,
2201			struct freebsd32_clock_gettime_args *uap)
2202{
2203	struct timespec	ats;
2204	struct timespec32 ats32;
2205	int error;
2206
2207	error = kern_clock_gettime(td, uap->clock_id, &ats);
2208	if (error == 0) {
2209		CP(ats, ats32, tv_sec);
2210		CP(ats, ats32, tv_nsec);
2211		error = copyout(&ats32, uap->tp, sizeof(ats32));
2212	}
2213	return (error);
2214}
2215
2216int
2217freebsd32_clock_settime(struct thread *td,
2218			struct freebsd32_clock_settime_args *uap)
2219{
2220	struct timespec	ats;
2221	struct timespec32 ats32;
2222	int error;
2223
2224	error = copyin(uap->tp, &ats32, sizeof(ats32));
2225	if (error)
2226		return (error);
2227	CP(ats32, ats, tv_sec);
2228	CP(ats32, ats, tv_nsec);
2229
2230	return (kern_clock_settime(td, uap->clock_id, &ats));
2231}
2232
2233int
2234freebsd32_clock_getres(struct thread *td,
2235		       struct freebsd32_clock_getres_args *uap)
2236{
2237	struct timespec	ts;
2238	struct timespec32 ts32;
2239	int error;
2240
2241	if (uap->tp == NULL)
2242		return (0);
2243	error = kern_clock_getres(td, uap->clock_id, &ts);
2244	if (error == 0) {
2245		CP(ts, ts32, tv_sec);
2246		CP(ts, ts32, tv_nsec);
2247		error = copyout(&ts32, uap->tp, sizeof(ts32));
2248	}
2249	return (error);
2250}
2251
2252int
2253freebsd32_thr_new(struct thread *td,
2254		  struct freebsd32_thr_new_args *uap)
2255{
2256	struct thr_param32 param32;
2257	struct thr_param param;
2258	int error;
2259
2260	if (uap->param_size < 0 ||
2261	    uap->param_size > sizeof(struct thr_param32))
2262		return (EINVAL);
2263	bzero(&param, sizeof(struct thr_param));
2264	bzero(&param32, sizeof(struct thr_param32));
2265	error = copyin(uap->param, &param32, uap->param_size);
2266	if (error != 0)
2267		return (error);
2268	param.start_func = PTRIN(param32.start_func);
2269	param.arg = PTRIN(param32.arg);
2270	param.stack_base = PTRIN(param32.stack_base);
2271	param.stack_size = param32.stack_size;
2272	param.tls_base = PTRIN(param32.tls_base);
2273	param.tls_size = param32.tls_size;
2274	param.child_tid = PTRIN(param32.child_tid);
2275	param.parent_tid = PTRIN(param32.parent_tid);
2276	param.flags = param32.flags;
2277	param.rtp = PTRIN(param32.rtp);
2278	param.spare[0] = PTRIN(param32.spare[0]);
2279	param.spare[1] = PTRIN(param32.spare[1]);
2280	param.spare[2] = PTRIN(param32.spare[2]);
2281
2282	return (kern_thr_new(td, &param));
2283}
2284
2285int
2286freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
2287{
2288	struct timespec32 ts32;
2289	struct timespec ts, *tsp;
2290	int error;
2291
2292	error = 0;
2293	tsp = NULL;
2294	if (uap->timeout != NULL) {
2295		error = copyin((const void *)uap->timeout, (void *)&ts32,
2296		    sizeof(struct timespec32));
2297		if (error != 0)
2298			return (error);
2299		ts.tv_sec = ts32.tv_sec;
2300		ts.tv_nsec = ts32.tv_nsec;
2301		tsp = &ts;
2302	}
2303	return (kern_thr_suspend(td, tsp));
2304}
2305
2306void
2307siginfo_to_siginfo32(const siginfo_t *src, struct siginfo32 *dst)
2308{
2309	bzero(dst, sizeof(*dst));
2310	dst->si_signo = src->si_signo;
2311	dst->si_errno = src->si_errno;
2312	dst->si_code = src->si_code;
2313	dst->si_pid = src->si_pid;
2314	dst->si_uid = src->si_uid;
2315	dst->si_status = src->si_status;
2316	dst->si_addr = (uintptr_t)src->si_addr;
2317	dst->si_value.sigval_int = src->si_value.sival_int;
2318	dst->si_timerid = src->si_timerid;
2319	dst->si_overrun = src->si_overrun;
2320}
2321
2322int
2323freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
2324{
2325	struct timespec32 ts32;
2326	struct timespec ts;
2327	struct timespec *timeout;
2328	sigset_t set;
2329	ksiginfo_t ksi;
2330	struct siginfo32 si32;
2331	int error;
2332
2333	if (uap->timeout) {
2334		error = copyin(uap->timeout, &ts32, sizeof(ts32));
2335		if (error)
2336			return (error);
2337		ts.tv_sec = ts32.tv_sec;
2338		ts.tv_nsec = ts32.tv_nsec;
2339		timeout = &ts;
2340	} else
2341		timeout = NULL;
2342
2343	error = copyin(uap->set, &set, sizeof(set));
2344	if (error)
2345		return (error);
2346
2347	error = kern_sigtimedwait(td, set, &ksi, timeout);
2348	if (error)
2349		return (error);
2350
2351	if (uap->info) {
2352		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2353		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2354	}
2355
2356	if (error == 0)
2357		td->td_retval[0] = ksi.ksi_signo;
2358	return (error);
2359}
2360
2361/*
2362 * MPSAFE
2363 */
2364int
2365freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
2366{
2367	ksiginfo_t ksi;
2368	struct siginfo32 si32;
2369	sigset_t set;
2370	int error;
2371
2372	error = copyin(uap->set, &set, sizeof(set));
2373	if (error)
2374		return (error);
2375
2376	error = kern_sigtimedwait(td, set, &ksi, NULL);
2377	if (error)
2378		return (error);
2379
2380	if (uap->info) {
2381		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2382		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2383	}
2384	if (error == 0)
2385		td->td_retval[0] = ksi.ksi_signo;
2386	return (error);
2387}
2388
2389int
2390freebsd32_cpuset_setid(struct thread *td,
2391    struct freebsd32_cpuset_setid_args *uap)
2392{
2393	struct cpuset_setid_args ap;
2394
2395	ap.which = uap->which;
2396	ap.id = PAIR32TO64(id_t,uap->id);
2397	ap.setid = uap->setid;
2398
2399	return (cpuset_setid(td, &ap));
2400}
2401
2402int
2403freebsd32_cpuset_getid(struct thread *td,
2404    struct freebsd32_cpuset_getid_args *uap)
2405{
2406	struct cpuset_getid_args ap;
2407
2408	ap.level = uap->level;
2409	ap.which = uap->which;
2410	ap.id = PAIR32TO64(id_t,uap->id);
2411	ap.setid = uap->setid;
2412
2413	return (cpuset_getid(td, &ap));
2414}
2415
2416int
2417freebsd32_cpuset_getaffinity(struct thread *td,
2418    struct freebsd32_cpuset_getaffinity_args *uap)
2419{
2420	struct cpuset_getaffinity_args ap;
2421
2422	ap.level = uap->level;
2423	ap.which = uap->which;
2424	ap.id = PAIR32TO64(id_t,uap->id);
2425	ap.cpusetsize = uap->cpusetsize;
2426	ap.mask = uap->mask;
2427
2428	return (cpuset_getaffinity(td, &ap));
2429}
2430
2431int
2432freebsd32_cpuset_setaffinity(struct thread *td,
2433    struct freebsd32_cpuset_setaffinity_args *uap)
2434{
2435	struct cpuset_setaffinity_args ap;
2436
2437	ap.level = uap->level;
2438	ap.which = uap->which;
2439	ap.id = PAIR32TO64(id_t,uap->id);
2440	ap.cpusetsize = uap->cpusetsize;
2441	ap.mask = uap->mask;
2442
2443	return (cpuset_setaffinity(td, &ap));
2444}
2445
2446int
2447freebsd32_nmount(struct thread *td,
2448    struct freebsd32_nmount_args /* {
2449    	struct iovec *iovp;
2450    	unsigned int iovcnt;
2451    	int flags;
2452    } */ *uap)
2453{
2454	struct uio *auio;
2455	int error;
2456
2457	AUDIT_ARG_FFLAGS(uap->flags);
2458
2459	/*
2460	 * Filter out MNT_ROOTFS.  We do not want clients of nmount() in
2461	 * userspace to set this flag, but we must filter it out if we want
2462	 * MNT_UPDATE on the root file system to work.
2463	 * MNT_ROOTFS should only be set by the kernel when mounting its
2464	 * root file system.
2465	 */
2466	uap->flags &= ~MNT_ROOTFS;
2467
2468	/*
2469	 * check that we have an even number of iovec's
2470	 * and that we have at least two options.
2471	 */
2472	if ((uap->iovcnt & 1) || (uap->iovcnt < 4))
2473		return (EINVAL);
2474
2475	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2476	if (error)
2477		return (error);
2478	error = vfs_donmount(td, uap->flags, auio);
2479
2480	free(auio, M_IOV);
2481	return error;
2482}
2483
2484#if 0
2485int
2486freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
2487{
2488	struct yyy32 *p32, s32;
2489	struct yyy *p = NULL, s;
2490	struct xxx_arg ap;
2491	int error;
2492
2493	if (uap->zzz) {
2494		error = copyin(uap->zzz, &s32, sizeof(s32));
2495		if (error)
2496			return (error);
2497		/* translate in */
2498		p = &s;
2499	}
2500	error = kern_xxx(td, p);
2501	if (error)
2502		return (error);
2503	if (uap->zzz) {
2504		/* translate out */
2505		error = copyout(&s32, p32, sizeof(s32));
2506	}
2507	return (error);
2508}
2509#endif
2510
2511int
2512syscall32_register(int *offset, struct sysent *new_sysent,
2513    struct sysent *old_sysent)
2514{
2515	if (*offset == NO_SYSCALL) {
2516		int i;
2517
2518		for (i = 1; i < SYS_MAXSYSCALL; ++i)
2519			if (freebsd32_sysent[i].sy_call ==
2520			    (sy_call_t *)lkmnosys)
2521				break;
2522		if (i == SYS_MAXSYSCALL)
2523			return (ENFILE);
2524		*offset = i;
2525	} else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
2526		return (EINVAL);
2527	else if (freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
2528	    freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmressys)
2529		return (EEXIST);
2530
2531	*old_sysent = freebsd32_sysent[*offset];
2532	freebsd32_sysent[*offset] = *new_sysent;
2533	return 0;
2534}
2535
2536int
2537syscall32_deregister(int *offset, struct sysent *old_sysent)
2538{
2539
2540	if (*offset)
2541		freebsd32_sysent[*offset] = *old_sysent;
2542	return 0;
2543}
2544
2545int
2546syscall32_module_handler(struct module *mod, int what, void *arg)
2547{
2548	struct syscall_module_data *data = (struct syscall_module_data*)arg;
2549	modspecific_t ms;
2550	int error;
2551
2552	switch (what) {
2553	case MOD_LOAD:
2554		error = syscall32_register(data->offset, data->new_sysent,
2555		    &data->old_sysent);
2556		if (error) {
2557			/* Leave a mark so we know to safely unload below. */
2558			data->offset = NULL;
2559			return error;
2560		}
2561		ms.intval = *data->offset;
2562		MOD_XLOCK;
2563		module_setspecific(mod, &ms);
2564		MOD_XUNLOCK;
2565		if (data->chainevh)
2566			error = data->chainevh(mod, what, data->chainarg);
2567		return (error);
2568	case MOD_UNLOAD:
2569		/*
2570		 * MOD_LOAD failed, so just return without calling the
2571		 * chained handler since we didn't pass along the MOD_LOAD
2572		 * event.
2573		 */
2574		if (data->offset == NULL)
2575			return (0);
2576		if (data->chainevh) {
2577			error = data->chainevh(mod, what, data->chainarg);
2578			if (error)
2579				return (error);
2580		}
2581		error = syscall32_deregister(data->offset, &data->old_sysent);
2582		return (error);
2583	default:
2584		error = EOPNOTSUPP;
2585		if (data->chainevh)
2586			error = data->chainevh(mod, what, data->chainarg);
2587		return (error);
2588	}
2589}
2590
2591int
2592syscall32_helper_register(struct syscall_helper_data *sd)
2593{
2594	struct syscall_helper_data *sd1;
2595	int error;
2596
2597	for (sd1 = sd; sd1->syscall_no != NO_SYSCALL; sd1++) {
2598		error = syscall32_register(&sd1->syscall_no, &sd1->new_sysent,
2599		    &sd1->old_sysent);
2600		if (error != 0) {
2601			syscall32_helper_unregister(sd);
2602			return (error);
2603		}
2604		sd1->registered = 1;
2605	}
2606	return (0);
2607}
2608
2609int
2610syscall32_helper_unregister(struct syscall_helper_data *sd)
2611{
2612	struct syscall_helper_data *sd1;
2613
2614	for (sd1 = sd; sd1->registered != 0; sd1++) {
2615		syscall32_deregister(&sd1->syscall_no, &sd1->old_sysent);
2616		sd1->registered = 0;
2617	}
2618	return (0);
2619}
2620
2621register_t *
2622freebsd32_copyout_strings(struct image_params *imgp)
2623{
2624	int argc, envc, i;
2625	u_int32_t *vectp;
2626	char *stringp, *destp;
2627	u_int32_t *stack_base;
2628	struct freebsd32_ps_strings *arginfo;
2629	char canary[sizeof(long) * 8];
2630	int32_t pagesizes32[MAXPAGESIZES];
2631	size_t execpath_len;
2632	int szsigcode;
2633
2634	/*
2635	 * Calculate string base and vector table pointers.
2636	 * Also deal with signal trampoline code for this exec type.
2637	 */
2638	if (imgp->execpath != NULL && imgp->auxargs != NULL)
2639		execpath_len = strlen(imgp->execpath) + 1;
2640	else
2641		execpath_len = 0;
2642	arginfo = (struct freebsd32_ps_strings *)curproc->p_sysent->
2643	    sv_psstrings;
2644	if (imgp->proc->p_sysent->sv_sigcode_base == 0)
2645		szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
2646	else
2647		szsigcode = 0;
2648	destp =	(caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
2649	    roundup(execpath_len, sizeof(char *)) -
2650	    roundup(sizeof(canary), sizeof(char *)) -
2651	    roundup(sizeof(pagesizes32), sizeof(char *)) -
2652	    roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
2653
2654	/*
2655	 * install sigcode
2656	 */
2657	if (szsigcode != 0)
2658		copyout(imgp->proc->p_sysent->sv_sigcode,
2659			((caddr_t)arginfo - szsigcode), szsigcode);
2660
2661	/*
2662	 * Copy the image path for the rtld.
2663	 */
2664	if (execpath_len != 0) {
2665		imgp->execpathp = (uintptr_t)arginfo - szsigcode - execpath_len;
2666		copyout(imgp->execpath, (void *)imgp->execpathp,
2667		    execpath_len);
2668	}
2669
2670	/*
2671	 * Prepare the canary for SSP.
2672	 */
2673	arc4rand(canary, sizeof(canary), 0);
2674	imgp->canary = (uintptr_t)arginfo - szsigcode - execpath_len -
2675	    sizeof(canary);
2676	copyout(canary, (void *)imgp->canary, sizeof(canary));
2677	imgp->canarylen = sizeof(canary);
2678
2679	/*
2680	 * Prepare the pagesizes array.
2681	 */
2682	for (i = 0; i < MAXPAGESIZES; i++)
2683		pagesizes32[i] = (uint32_t)pagesizes[i];
2684	imgp->pagesizes = (uintptr_t)arginfo - szsigcode - execpath_len -
2685	    roundup(sizeof(canary), sizeof(char *)) - sizeof(pagesizes32);
2686	copyout(pagesizes32, (void *)imgp->pagesizes, sizeof(pagesizes32));
2687	imgp->pagesizeslen = sizeof(pagesizes32);
2688
2689	/*
2690	 * If we have a valid auxargs ptr, prepare some room
2691	 * on the stack.
2692	 */
2693	if (imgp->auxargs) {
2694		/*
2695		 * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
2696		 * lower compatibility.
2697		 */
2698		imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
2699			: (AT_COUNT * 2);
2700		/*
2701		 * The '+ 2' is for the null pointers at the end of each of
2702		 * the arg and env vector sets,and imgp->auxarg_size is room
2703		 * for argument of Runtime loader.
2704		 */
2705		vectp = (u_int32_t *) (destp - (imgp->args->argc +
2706		    imgp->args->envc + 2 + imgp->auxarg_size + execpath_len) *
2707		    sizeof(u_int32_t));
2708	} else
2709		/*
2710		 * The '+ 2' is for the null pointers at the end of each of
2711		 * the arg and env vector sets
2712		 */
2713		vectp = (u_int32_t *)
2714			(destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(u_int32_t));
2715
2716	/*
2717	 * vectp also becomes our initial stack base
2718	 */
2719	stack_base = vectp;
2720
2721	stringp = imgp->args->begin_argv;
2722	argc = imgp->args->argc;
2723	envc = imgp->args->envc;
2724	/*
2725	 * Copy out strings - arguments and environment.
2726	 */
2727	copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);
2728
2729	/*
2730	 * Fill in "ps_strings" struct for ps, w, etc.
2731	 */
2732	suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
2733	suword32(&arginfo->ps_nargvstr, argc);
2734
2735	/*
2736	 * Fill in argument portion of vector table.
2737	 */
2738	for (; argc > 0; --argc) {
2739		suword32(vectp++, (u_int32_t)(intptr_t)destp);
2740		while (*stringp++ != 0)
2741			destp++;
2742		destp++;
2743	}
2744
2745	/* a null vector table pointer separates the argp's from the envp's */
2746	suword32(vectp++, 0);
2747
2748	suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
2749	suword32(&arginfo->ps_nenvstr, envc);
2750
2751	/*
2752	 * Fill in environment portion of vector table.
2753	 */
2754	for (; envc > 0; --envc) {
2755		suword32(vectp++, (u_int32_t)(intptr_t)destp);
2756		while (*stringp++ != 0)
2757			destp++;
2758		destp++;
2759	}
2760
2761	/* end of vector table is a null pointer */
2762	suword32(vectp, 0);
2763
2764	return ((register_t *)stack_base);
2765}
2766
2767int
2768freebsd32_kldstat(struct thread *td, struct freebsd32_kldstat_args *uap)
2769{
2770	struct kld_file_stat stat;
2771	struct kld32_file_stat stat32;
2772	int error, version;
2773
2774	if ((error = copyin(&uap->stat->version, &version, sizeof(version)))
2775	    != 0)
2776		return (error);
2777	if (version != sizeof(struct kld32_file_stat_1) &&
2778	    version != sizeof(struct kld32_file_stat))
2779		return (EINVAL);
2780
2781	error = kern_kldstat(td, uap->fileid, &stat);
2782	if (error != 0)
2783		return (error);
2784
2785	bcopy(&stat.name[0], &stat32.name[0], sizeof(stat.name));
2786	CP(stat, stat32, refs);
2787	CP(stat, stat32, id);
2788	PTROUT_CP(stat, stat32, address);
2789	CP(stat, stat32, size);
2790	bcopy(&stat.pathname[0], &stat32.pathname[0], sizeof(stat.pathname));
2791	return (copyout(&stat32, uap->stat, version));
2792}
2793
2794int
2795freebsd32_posix_fallocate(struct thread *td,
2796    struct freebsd32_posix_fallocate_args *uap)
2797{
2798	struct posix_fallocate_args ap;
2799
2800	ap.fd = uap->fd;
2801	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
2802	ap.len = (uap->lenlo | ((off_t)uap->lenhi << 32));
2803	return (posix_fallocate(td, &ap));
2804}
2805