freebsd32_misc.c revision 151909
1100384Speter/*-
2100384Speter * Copyright (c) 2002 Doug Rabson
3100384Speter * All rights reserved.
4100384Speter *
5100384Speter * Redistribution and use in source and binary forms, with or without
6100384Speter * modification, are permitted provided that the following conditions
7100384Speter * are met:
8100384Speter * 1. Redistributions of source code must retain the above copyright
9100384Speter *    notice, this list of conditions and the following disclaimer.
10100384Speter * 2. Redistributions in binary form must reproduce the above copyright
11100384Speter *    notice, this list of conditions and the following disclaimer in the
12100384Speter *    documentation and/or other materials provided with the distribution.
13100384Speter *
14100384Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15100384Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16100384Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17100384Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18100384Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19100384Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20100384Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21100384Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22100384Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23100384Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24100384Speter * SUCH DAMAGE.
25100384Speter */
26100384Speter
27118031Sobrien#include <sys/cdefs.h>
28118031Sobrien__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 151909 2005-10-31 21:09:56Z ps $");
29118031Sobrien
30104738Speter#include "opt_compat.h"
31104738Speter
32100384Speter#include <sys/param.h>
33100384Speter#include <sys/systm.h>
34100384Speter#include <sys/bus.h>
35100384Speter#include <sys/exec.h>
36100384Speter#include <sys/fcntl.h>
37100384Speter#include <sys/filedesc.h>
38123746Speter#include <sys/namei.h>
39100384Speter#include <sys/imgact.h>
40100384Speter#include <sys/kernel.h>
41100384Speter#include <sys/lock.h>
42100384Speter#include <sys/malloc.h>
43100384Speter#include <sys/file.h>		/* Must come after sys/malloc.h */
44151909Sps#include <sys/mbuf.h>
45100384Speter#include <sys/mman.h>
46100384Speter#include <sys/module.h>
47100384Speter#include <sys/mount.h>
48100384Speter#include <sys/mutex.h>
49100384Speter#include <sys/namei.h>
50100384Speter#include <sys/param.h>
51100384Speter#include <sys/proc.h>
52100384Speter#include <sys/reboot.h>
53100384Speter#include <sys/resource.h>
54100384Speter#include <sys/resourcevar.h>
55100384Speter#include <sys/selinfo.h>
56146950Sps#include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
57100384Speter#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
58100384Speter#include <sys/signal.h>
59100384Speter#include <sys/signalvar.h>
60100384Speter#include <sys/socket.h>
61100384Speter#include <sys/socketvar.h>
62100384Speter#include <sys/stat.h>
63150883Sjhb#include <sys/syscall.h>
64113859Sjhb#include <sys/syscallsubr.h>
65100384Speter#include <sys/sysctl.h>
66100384Speter#include <sys/sysent.h>
67100384Speter#include <sys/sysproto.h>
68100384Speter#include <sys/systm.h>
69100384Speter#include <sys/unistd.h>
70100384Speter#include <sys/vnode.h>
71127140Sjhb#include <sys/wait.h>
72100384Speter
73100384Speter#include <vm/vm.h>
74100384Speter#include <vm/vm_kern.h>
75100384Speter#include <vm/vm_param.h>
76100384Speter#include <vm/pmap.h>
77100384Speter#include <vm/vm_map.h>
78100384Speter#include <vm/vm_object.h>
79100384Speter#include <vm/vm_extern.h>
80100384Speter
81151582Sps#include <machine/cpu.h>
82151582Sps
83119333Speter#include <compat/freebsd32/freebsd32_util.h>
84119333Speter#include <compat/freebsd32/freebsd32.h>
85119333Speter#include <compat/freebsd32/freebsd32_proto.h>
86100384Speter
87121719SpeterCTASSERT(sizeof(struct timeval32) == 8);
88121719SpeterCTASSERT(sizeof(struct timespec32) == 8);
89121719SpeterCTASSERT(sizeof(struct statfs32) == 256);
90121719SpeterCTASSERT(sizeof(struct rusage32) == 72);
91121719Speter
92100384Speterint
93119333Speterfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
94100384Speter{
95127140Sjhb	int error, status;
96127140Sjhb	struct rusage32 ru32;
97136152Sjhb	struct rusage ru, *rup;
98100384Speter
99136152Sjhb	if (uap->rusage != NULL)
100136152Sjhb		rup = &ru;
101136152Sjhb	else
102136152Sjhb		rup = NULL;
103136152Sjhb	error = kern_wait(td, uap->pid, &status, uap->options, rup);
104100384Speter	if (error)
105100384Speter		return (error);
106127140Sjhb	if (uap->status != NULL)
107127140Sjhb		error = copyout(&status, uap->status, sizeof(status));
108127140Sjhb	if (uap->rusage != NULL && error == 0) {
109100384Speter		TV_CP(ru, ru32, ru_utime);
110100384Speter		TV_CP(ru, ru32, ru_stime);
111100384Speter		CP(ru, ru32, ru_maxrss);
112100384Speter		CP(ru, ru32, ru_ixrss);
113100384Speter		CP(ru, ru32, ru_idrss);
114100384Speter		CP(ru, ru32, ru_isrss);
115100384Speter		CP(ru, ru32, ru_minflt);
116100384Speter		CP(ru, ru32, ru_majflt);
117100384Speter		CP(ru, ru32, ru_nswap);
118100384Speter		CP(ru, ru32, ru_inblock);
119100384Speter		CP(ru, ru32, ru_oublock);
120100384Speter		CP(ru, ru32, ru_msgsnd);
121100384Speter		CP(ru, ru32, ru_msgrcv);
122100384Speter		CP(ru, ru32, ru_nsignals);
123100384Speter		CP(ru, ru32, ru_nvcsw);
124100384Speter		CP(ru, ru32, ru_nivcsw);
125127140Sjhb		error = copyout(&ru32, uap->rusage, sizeof(ru32));
126100384Speter	}
127100384Speter	return (error);
128100384Speter}
129100384Speter
130128597Smarcel#ifdef COMPAT_FREEBSD4
131100384Speterstatic void
132100384Spetercopy_statfs(struct statfs *in, struct statfs32 *out)
133100384Speter{
134100384Speter	CP(*in, *out, f_bsize);
135100384Speter	CP(*in, *out, f_iosize);
136100384Speter	CP(*in, *out, f_blocks);
137100384Speter	CP(*in, *out, f_bfree);
138100384Speter	CP(*in, *out, f_bavail);
139100384Speter	CP(*in, *out, f_files);
140100384Speter	CP(*in, *out, f_ffree);
141100384Speter	CP(*in, *out, f_fsid);
142100384Speter	CP(*in, *out, f_owner);
143100384Speter	CP(*in, *out, f_type);
144100384Speter	CP(*in, *out, f_flags);
145100384Speter	CP(*in, *out, f_flags);
146100384Speter	CP(*in, *out, f_syncwrites);
147100384Speter	CP(*in, *out, f_asyncwrites);
148100384Speter	bcopy(in->f_fstypename,
149100384Speter	      out->f_fstypename, MFSNAMELEN);
150100384Speter	bcopy(in->f_mntonname,
151128260Speter	      out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
152100384Speter	CP(*in, *out, f_syncreads);
153100384Speter	CP(*in, *out, f_asyncreads);
154100384Speter	bcopy(in->f_mntfromname,
155128260Speter	      out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
156100384Speter}
157128597Smarcel#endif
158100384Speter
159128597Smarcel#ifdef COMPAT_FREEBSD4
160100384Speterint
161128260Speterfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
162100384Speter{
163147178Spjd	struct statfs *buf, *sp;
164147178Spjd	struct statfs32 stat32;
165147178Spjd	size_t count, size;
166100384Speter	int error;
167100384Speter
168147178Spjd	count = uap->bufsize / sizeof(struct statfs32);
169147178Spjd	size = count * sizeof(struct statfs);
170147302Spjd	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
171147302Spjd	if (size > 0) {
172100384Speter		count = td->td_retval[0];
173147178Spjd		sp = buf;
174147178Spjd		while (count > 0 && error == 0) {
175147178Spjd			copy_statfs(sp, &stat32);
176147178Spjd			error = copyout(&stat32, uap->buf, sizeof(stat32));
177147178Spjd			sp++;
178147178Spjd			uap->buf++;
179147178Spjd			count--;
180100384Speter		}
181147178Spjd		free(buf, M_TEMP);
182100384Speter	}
183100384Speter	return (error);
184100384Speter}
185128597Smarcel#endif
186100384Speter
187100384Speterstruct sigaltstack32 {
188100384Speter	u_int32_t	ss_sp;
189100384Speter	u_int32_t	ss_size;
190100384Speter	int		ss_flags;
191100384Speter};
192100384Speter
193121719SpeterCTASSERT(sizeof(struct sigaltstack32) == 12);
194121719Speter
195100384Speterint
196119333Speterfreebsd32_sigaltstack(struct thread *td,
197119333Speter		      struct freebsd32_sigaltstack_args *uap)
198100384Speter{
199113859Sjhb	struct sigaltstack32 s32;
200113859Sjhb	struct sigaltstack ss, oss, *ssp;
201100384Speter	int error;
202100384Speter
203113859Sjhb	if (uap->ss != NULL) {
204113859Sjhb		error = copyin(uap->ss, &s32, sizeof(s32));
205100384Speter		if (error)
206100384Speter			return (error);
207113859Sjhb		PTRIN_CP(s32, ss, ss_sp);
208113859Sjhb		CP(s32, ss, ss_size);
209113859Sjhb		CP(s32, ss, ss_flags);
210113859Sjhb		ssp = &ss;
211113859Sjhb	} else
212113859Sjhb		ssp = NULL;
213113859Sjhb	error = kern_sigaltstack(td, ssp, &oss);
214113859Sjhb	if (error == 0 && uap->oss != NULL) {
215113859Sjhb		PTROUT_CP(oss, s32, ss_sp);
216113859Sjhb		CP(oss, s32, ss_size);
217113859Sjhb		CP(oss, s32, ss_flags);
218113859Sjhb		error = copyout(&s32, uap->oss, sizeof(s32));
219100384Speter	}
220100384Speter	return (error);
221100384Speter}
222100384Speter
223142059Sjhb/*
224142059Sjhb * Custom version of exec_copyin_args() so that we can translate
225142059Sjhb * the pointers.
226142059Sjhb */
227142059Sjhbstatic int
228142059Sjhbfreebsd32_exec_copyin_args(struct image_args *args, char *fname,
229142059Sjhb    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
230100384Speter{
231142059Sjhb	char *argp, *envp;
232142059Sjhb	u_int32_t *p32, arg;
233142059Sjhb	size_t length;
234100384Speter	int error;
235100384Speter
236142059Sjhb	bzero(args, sizeof(*args));
237142059Sjhb	if (argv == NULL)
238142059Sjhb		return (EFAULT);
239100384Speter
240142059Sjhb	/*
241142059Sjhb	 * Allocate temporary demand zeroed space for argument and
242142059Sjhb	 *	environment strings
243142059Sjhb	 */
244147588Sjhb	args->buf = (char *) kmem_alloc_wait(exec_map,
245147588Sjhb	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
246142059Sjhb	if (args->buf == NULL)
247142059Sjhb		return (ENOMEM);
248142059Sjhb	args->begin_argv = args->buf;
249142059Sjhb	args->endp = args->begin_argv;
250142059Sjhb	args->stringspace = ARG_MAX;
251142059Sjhb
252142059Sjhb	args->fname = args->buf + ARG_MAX;
253142059Sjhb
254142059Sjhb	/*
255142059Sjhb	 * Copy the file name.
256142059Sjhb	 */
257142059Sjhb	error = (segflg == UIO_SYSSPACE) ?
258142059Sjhb	    copystr(fname, args->fname, PATH_MAX, &length) :
259142059Sjhb	    copyinstr(fname, args->fname, PATH_MAX, &length);
260142059Sjhb	if (error != 0)
261142059Sjhb		return (error);
262142059Sjhb
263142059Sjhb	/*
264142059Sjhb	 * extract arguments first
265142059Sjhb	 */
266142059Sjhb	p32 = argv;
267142059Sjhb	for (;;) {
268142059Sjhb		error = copyin(p32++, &arg, sizeof(arg));
269142059Sjhb		if (error)
270142059Sjhb			return (error);
271142059Sjhb		if (arg == 0)
272142059Sjhb			break;
273142059Sjhb		argp = PTRIN(arg);
274142059Sjhb		error = copyinstr(argp, args->endp, args->stringspace, &length);
275142059Sjhb		if (error) {
276142059Sjhb			if (error == ENAMETOOLONG)
277142059Sjhb				return (E2BIG);
278142059Sjhb			else
279142059Sjhb				return (error);
280142059Sjhb		}
281142059Sjhb		args->stringspace -= length;
282142059Sjhb		args->endp += length;
283142059Sjhb		args->argc++;
284100384Speter	}
285142059Sjhb
286142059Sjhb	args->begin_envv = args->endp;
287142059Sjhb
288142059Sjhb	/*
289142059Sjhb	 * extract environment strings
290142059Sjhb	 */
291142059Sjhb	if (envv) {
292142059Sjhb		p32 = envv;
293142059Sjhb		for (;;) {
294100384Speter			error = copyin(p32++, &arg, sizeof(arg));
295100384Speter			if (error)
296142059Sjhb				return (error);
297142059Sjhb			if (arg == 0)
298142059Sjhb				break;
299142059Sjhb			envp = PTRIN(arg);
300142059Sjhb			error = copyinstr(envp, args->endp, args->stringspace,
301142059Sjhb			    &length);
302142059Sjhb			if (error) {
303142059Sjhb				if (error == ENAMETOOLONG)
304142059Sjhb					return (E2BIG);
305142059Sjhb				else
306142059Sjhb					return (error);
307142059Sjhb			}
308142059Sjhb			args->stringspace -= length;
309142059Sjhb			args->endp += length;
310142059Sjhb			args->envc++;
311142059Sjhb		}
312100384Speter	}
313100384Speter
314142059Sjhb	return (0);
315100384Speter}
316100384Speter
317142059Sjhbint
318142059Sjhbfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
319142059Sjhb{
320142059Sjhb	struct image_args eargs;
321142059Sjhb	int error;
322142059Sjhb
323142059Sjhb	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
324142059Sjhb	    uap->argv, uap->envv);
325142059Sjhb	if (error == 0)
326142059Sjhb		error = kern_execve(td, &eargs, NULL);
327142059Sjhb	exec_free_args(&eargs);
328142059Sjhb	return (error);
329142059Sjhb}
330142059Sjhb
331114987Speter#ifdef __ia64__
332100384Speterstatic int
333119333Speterfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
334119333Speter		       int prot, int fd, off_t pos)
335100384Speter{
336100384Speter	vm_map_t map;
337100384Speter	vm_map_entry_t entry;
338100384Speter	int rv;
339100384Speter
340100384Speter	map = &td->td_proc->p_vmspace->vm_map;
341100384Speter	if (fd != -1)
342100384Speter		prot |= VM_PROT_WRITE;
343100384Speter
344100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
345100384Speter		if ((entry->protection & prot) != prot) {
346100384Speter			rv = vm_map_protect(map,
347100384Speter					    trunc_page(start),
348100384Speter					    round_page(end),
349100384Speter					    entry->protection | prot,
350100384Speter					    FALSE);
351100384Speter			if (rv != KERN_SUCCESS)
352100384Speter				return (EINVAL);
353100384Speter		}
354100384Speter	} else {
355100384Speter		vm_offset_t addr = trunc_page(start);
356100384Speter		rv = vm_map_find(map, 0, 0,
357100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
358100384Speter				 VM_PROT_ALL, 0);
359100384Speter		if (rv != KERN_SUCCESS)
360100384Speter			return (EINVAL);
361100384Speter	}
362100384Speter
363100384Speter	if (fd != -1) {
364100384Speter		struct pread_args r;
365107849Salfred		r.fd = fd;
366107849Salfred		r.buf = (void *) start;
367107849Salfred		r.nbyte = end - start;
368107849Salfred		r.offset = pos;
369100384Speter		return (pread(td, &r));
370100384Speter	} else {
371100384Speter		while (start < end) {
372100384Speter			subyte((void *) start, 0);
373100384Speter			start++;
374100384Speter		}
375100384Speter		return (0);
376100384Speter	}
377100384Speter}
378114987Speter#endif
379100384Speter
380100384Speterint
381119333Speterfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
382100384Speter{
383100384Speter	struct mmap_args ap;
384107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
385107849Salfred	vm_size_t len	 = uap->len;
386107849Salfred	int prot	 = uap->prot;
387107849Salfred	int flags	 = uap->flags;
388107849Salfred	int fd		 = uap->fd;
389107849Salfred	off_t pos	 = (uap->poslo
390107849Salfred			    | ((off_t)uap->poshi << 32));
391114987Speter#ifdef __ia64__
392100384Speter	vm_size_t pageoff;
393100384Speter	int error;
394100384Speter
395100384Speter	/*
396100384Speter	 * Attempt to handle page size hassles.
397100384Speter	 */
398100384Speter	pageoff = (pos & PAGE_MASK);
399100384Speter	if (flags & MAP_FIXED) {
400100384Speter		vm_offset_t start, end;
401100384Speter		start = addr;
402100384Speter		end = addr + len;
403100384Speter
404147964Sjhb		mtx_lock(&Giant);
405100384Speter		if (start != trunc_page(start)) {
406119333Speter			error = freebsd32_mmap_partial(td, start,
407119333Speter						       round_page(start), prot,
408119333Speter						       fd, pos);
409100384Speter			if (fd != -1)
410100384Speter				pos += round_page(start) - start;
411100384Speter			start = round_page(start);
412100384Speter		}
413100384Speter		if (end != round_page(end)) {
414100384Speter			vm_offset_t t = trunc_page(end);
415119333Speter			error = freebsd32_mmap_partial(td, t, end,
416100384Speter						  prot, fd,
417100384Speter						  pos + t - start);
418100384Speter			end = trunc_page(end);
419100384Speter		}
420100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
421100384Speter			/*
422100384Speter			 * We can't map this region at all. The specified
423100384Speter			 * address doesn't have the same alignment as the file
424100384Speter			 * position. Fake the mapping by simply reading the
425100384Speter			 * entire region into memory. First we need to make
426100384Speter			 * sure the region exists.
427100384Speter			 */
428100384Speter			vm_map_t map;
429100384Speter			struct pread_args r;
430100384Speter			int rv;
431100384Speter
432100384Speter			prot |= VM_PROT_WRITE;
433100384Speter			map = &td->td_proc->p_vmspace->vm_map;
434100384Speter			rv = vm_map_remove(map, start, end);
435147964Sjhb			if (rv != KERN_SUCCESS) {
436147964Sjhb				mtx_unlock(&Giant);
437100384Speter				return (EINVAL);
438147964Sjhb			}
439100384Speter			rv = vm_map_find(map, 0, 0,
440100384Speter					 &start, end - start, FALSE,
441100384Speter					 prot, VM_PROT_ALL, 0);
442147964Sjhb			mtx_unlock(&Giant);
443100384Speter			if (rv != KERN_SUCCESS)
444100384Speter				return (EINVAL);
445107849Salfred			r.fd = fd;
446107849Salfred			r.buf = (void *) start;
447107849Salfred			r.nbyte = end - start;
448107849Salfred			r.offset = pos;
449100384Speter			error = pread(td, &r);
450100384Speter			if (error)
451100384Speter				return (error);
452100384Speter
453100384Speter			td->td_retval[0] = addr;
454100384Speter			return (0);
455100384Speter		}
456147964Sjhb		mtx_unlock(&Giant);
457100384Speter		if (end == start) {
458100384Speter			/*
459100384Speter			 * After dealing with the ragged ends, there
460100384Speter			 * might be none left.
461100384Speter			 */
462100384Speter			td->td_retval[0] = addr;
463100384Speter			return (0);
464100384Speter		}
465100384Speter		addr = start;
466100384Speter		len = end - start;
467100384Speter	}
468114987Speter#endif
469100384Speter
470107849Salfred	ap.addr = (void *) addr;
471107849Salfred	ap.len = len;
472107849Salfred	ap.prot = prot;
473107849Salfred	ap.flags = flags;
474107849Salfred	ap.fd = fd;
475107849Salfred	ap.pos = pos;
476100384Speter
477100384Speter	return (mmap(td, &ap));
478100384Speter}
479100384Speter
480100384Speterstruct itimerval32 {
481100384Speter	struct timeval32 it_interval;
482100384Speter	struct timeval32 it_value;
483100384Speter};
484100384Speter
485121719SpeterCTASSERT(sizeof(struct itimerval32) == 16);
486121719Speter
487100384Speterint
488119333Speterfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
489100384Speter{
490142059Sjhb	struct itimerval itv, oitv, *itvp;
491142059Sjhb	struct itimerval32 i32;
492100384Speter	int error;
493100384Speter
494142059Sjhb	if (uap->itv != NULL) {
495142059Sjhb		error = copyin(uap->itv, &i32, sizeof(i32));
496100384Speter		if (error)
497100384Speter			return (error);
498142059Sjhb		TV_CP(i32, itv, it_interval);
499142059Sjhb		TV_CP(i32, itv, it_value);
500142059Sjhb		itvp = &itv;
501142059Sjhb	} else
502142059Sjhb		itvp = NULL;
503142059Sjhb	error = kern_setitimer(td, uap->which, itvp, &oitv);
504142059Sjhb	if (error || uap->oitv == NULL)
505100384Speter		return (error);
506142059Sjhb	TV_CP(oitv, i32, it_interval);
507142059Sjhb	TV_CP(oitv, i32, it_value);
508142059Sjhb	return (copyout(&i32, uap->oitv, sizeof(i32)));
509100384Speter}
510100384Speter
511100384Speterint
512125171Speterfreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
513125171Speter{
514142059Sjhb	struct itimerval itv;
515142059Sjhb	struct itimerval32 i32;
516125171Speter	int error;
517125171Speter
518142059Sjhb	error = kern_getitimer(td, uap->which, &itv);
519142059Sjhb	if (error || uap->itv == NULL)
520125171Speter		return (error);
521142059Sjhb	TV_CP(itv, i32, it_interval);
522142059Sjhb	TV_CP(itv, i32, it_value);
523142059Sjhb	return (copyout(&i32, uap->itv, sizeof(i32)));
524125171Speter}
525125171Speter
526125171Speterint
527119333Speterfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
528100384Speter{
529142059Sjhb	struct timeval32 tv32;
530142059Sjhb	struct timeval tv, *tvp;
531100384Speter	int error;
532100384Speter
533142059Sjhb	if (uap->tv != NULL) {
534142059Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
535100384Speter		if (error)
536100384Speter			return (error);
537142059Sjhb		CP(tv32, tv, tv_sec);
538142059Sjhb		CP(tv32, tv, tv_usec);
539142059Sjhb		tvp = &tv;
540142059Sjhb	} else
541142059Sjhb		tvp = NULL;
542100384Speter	/*
543100384Speter	 * XXX big-endian needs to convert the fd_sets too.
544142059Sjhb	 * XXX Do pointers need PTRIN()?
545100384Speter	 */
546142059Sjhb	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
547100384Speter}
548100384Speter
549114987Speterstruct kevent32 {
550114987Speter	u_int32_t	ident;		/* identifier for this event */
551114987Speter	short		filter;		/* filter for event */
552114987Speter	u_short		flags;
553114987Speter	u_int		fflags;
554114987Speter	int32_t		data;
555114987Speter	u_int32_t	udata;		/* opaque user data identifier */
556114987Speter};
557114987Speter
558121719SpeterCTASSERT(sizeof(struct kevent32) == 20);
559146950Spsstatic int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
560146950Spsstatic int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
561121719Speter
562146950Sps/*
563146950Sps * Copy 'count' items into the destination list pointed to by uap->eventlist.
564146950Sps */
565146950Spsstatic int
566146950Spsfreebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
567146950Sps{
568146950Sps	struct freebsd32_kevent_args *uap;
569146950Sps	struct kevent32	ks32[KQ_NEVENTS];
570146950Sps	int i, error = 0;
571146950Sps
572146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
573146950Sps	uap = (struct freebsd32_kevent_args *)arg;
574146950Sps
575146950Sps	for (i = 0; i < count; i++) {
576146950Sps		CP(kevp[i], ks32[i], ident);
577146950Sps		CP(kevp[i], ks32[i], filter);
578146950Sps		CP(kevp[i], ks32[i], flags);
579146950Sps		CP(kevp[i], ks32[i], fflags);
580146950Sps		CP(kevp[i], ks32[i], data);
581146950Sps		PTROUT_CP(kevp[i], ks32[i], udata);
582146950Sps	}
583146950Sps	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
584146950Sps	if (error == 0)
585146950Sps		uap->eventlist += count;
586146950Sps	return (error);
587146950Sps}
588146950Sps
589146950Sps/*
590146950Sps * Copy 'count' items from the list pointed to by uap->changelist.
591146950Sps */
592146950Spsstatic int
593146950Spsfreebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
594146950Sps{
595146950Sps	struct freebsd32_kevent_args *uap;
596146950Sps	struct kevent32	ks32[KQ_NEVENTS];
597146950Sps	int i, error = 0;
598146950Sps
599146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
600146950Sps	uap = (struct freebsd32_kevent_args *)arg;
601146950Sps
602146950Sps	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
603146950Sps	if (error)
604146950Sps		goto done;
605146950Sps	uap->changelist += count;
606146950Sps
607146950Sps	for (i = 0; i < count; i++) {
608146950Sps		CP(ks32[i], kevp[i], ident);
609146950Sps		CP(ks32[i], kevp[i], filter);
610146950Sps		CP(ks32[i], kevp[i], flags);
611146950Sps		CP(ks32[i], kevp[i], fflags);
612146950Sps		CP(ks32[i], kevp[i], data);
613146950Sps		PTRIN_CP(ks32[i], kevp[i], udata);
614146950Sps	}
615146950Spsdone:
616146950Sps	return (error);
617146950Sps}
618146950Sps
619100384Speterint
620119333Speterfreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
621114987Speter{
622114987Speter	struct timespec32 ts32;
623142934Sps	struct timespec ts, *tsp;
624146950Sps	struct kevent_copyops k_ops = { uap,
625146950Sps					freebsd32_kevent_copyout,
626146950Sps					freebsd32_kevent_copyin};
627146950Sps	int error;
628114987Speter
629114987Speter
630114987Speter	if (uap->timeout) {
631114987Speter		error = copyin(uap->timeout, &ts32, sizeof(ts32));
632114987Speter		if (error)
633114987Speter			return (error);
634114987Speter		CP(ts32, ts, tv_sec);
635114987Speter		CP(ts32, ts, tv_nsec);
636142934Sps		tsp = &ts;
637142934Sps	} else
638142934Sps		tsp = NULL;
639146950Sps	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
640146950Sps	    &k_ops, tsp);
641142934Sps	return (error);
642114987Speter}
643114987Speter
644114987Speterint
645119333Speterfreebsd32_gettimeofday(struct thread *td,
646119333Speter		       struct freebsd32_gettimeofday_args *uap)
647100384Speter{
648123425Speter	struct timeval atv;
649123425Speter	struct timeval32 atv32;
650123425Speter	struct timezone rtz;
651123425Speter	int error = 0;
652100384Speter
653123425Speter	if (uap->tp) {
654123425Speter		microtime(&atv);
655123425Speter		CP(atv, atv32, tv_sec);
656123425Speter		CP(atv, atv32, tv_usec);
657123425Speter		error = copyout(&atv32, uap->tp, sizeof (atv32));
658100384Speter	}
659123425Speter	if (error == 0 && uap->tzp != NULL) {
660123425Speter		rtz.tz_minuteswest = tz_minuteswest;
661123425Speter		rtz.tz_dsttime = tz_dsttime;
662123425Speter		error = copyout(&rtz, uap->tzp, sizeof (rtz));
663100384Speter	}
664100384Speter	return (error);
665100384Speter}
666100384Speter
667100384Speterint
668119333Speterfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
669100384Speter{
670136152Sjhb	struct rusage32 s32;
671136152Sjhb	struct rusage s;
672100384Speter	int error;
673100384Speter
674136152Sjhb	error = kern_getrusage(td, uap->who, &s);
675100384Speter	if (error)
676100384Speter		return (error);
677136152Sjhb	if (uap->rusage != NULL) {
678100384Speter		TV_CP(s, s32, ru_utime);
679100384Speter		TV_CP(s, s32, ru_stime);
680100384Speter		CP(s, s32, ru_maxrss);
681100384Speter		CP(s, s32, ru_ixrss);
682100384Speter		CP(s, s32, ru_idrss);
683100384Speter		CP(s, s32, ru_isrss);
684100384Speter		CP(s, s32, ru_minflt);
685100384Speter		CP(s, s32, ru_majflt);
686100384Speter		CP(s, s32, ru_nswap);
687100384Speter		CP(s, s32, ru_inblock);
688100384Speter		CP(s, s32, ru_oublock);
689100384Speter		CP(s, s32, ru_msgsnd);
690100384Speter		CP(s, s32, ru_msgrcv);
691100384Speter		CP(s, s32, ru_nsignals);
692100384Speter		CP(s, s32, ru_nvcsw);
693100384Speter		CP(s, s32, ru_nivcsw);
694136152Sjhb		error = copyout(&s32, uap->rusage, sizeof(s32));
695100384Speter	}
696100384Speter	return (error);
697100384Speter}
698100384Speter
699100384Speterstruct iovec32 {
700100384Speter	u_int32_t iov_base;
701100384Speter	int	iov_len;
702100384Speter};
703100384Speter
704121719SpeterCTASSERT(sizeof(struct iovec32) == 8);
705121719Speter
706144450Sjhbstatic int
707144450Sjhbfreebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
708100384Speter{
709144450Sjhb	struct iovec32 iov32;
710144450Sjhb	struct iovec *iov;
711144450Sjhb	struct uio *uio;
712144450Sjhb	u_int iovlen;
713144450Sjhb	int error, i;
714100384Speter
715144450Sjhb	*uiop = NULL;
716144450Sjhb	if (iovcnt > UIO_MAXIOV)
717100384Speter		return (EINVAL);
718144450Sjhb	iovlen = iovcnt * sizeof(struct iovec);
719144450Sjhb	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
720144450Sjhb	iov = (struct iovec *)(uio + 1);
721144450Sjhb	for (i = 0; i < iovcnt; i++) {
722144450Sjhb		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
723144450Sjhb		if (error) {
724144450Sjhb			free(uio, M_IOV);
725144450Sjhb			return (error);
726144450Sjhb		}
727144450Sjhb		iov[i].iov_base = PTRIN(iov32.iov_base);
728144450Sjhb		iov[i].iov_len = iov32.iov_len;
729100384Speter	}
730144450Sjhb	uio->uio_iov = iov;
731144450Sjhb	uio->uio_iovcnt = iovcnt;
732144450Sjhb	uio->uio_segflg = UIO_USERSPACE;
733144450Sjhb	uio->uio_offset = -1;
734144450Sjhb	uio->uio_resid = 0;
735144450Sjhb	for (i = 0; i < iovcnt; i++) {
736144450Sjhb		if (iov->iov_len > INT_MAX - uio->uio_resid) {
737144450Sjhb			free(uio, M_IOV);
738144450Sjhb			return (EINVAL);
739144450Sjhb		}
740144450Sjhb		uio->uio_resid += iov->iov_len;
741144450Sjhb		iov++;
742144450Sjhb	}
743144450Sjhb	*uiop = uio;
744144450Sjhb	return (0);
745144450Sjhb}
746100384Speter
747144450Sjhbint
748144450Sjhbfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
749144450Sjhb{
750144450Sjhb	struct uio *auio;
751144450Sjhb	int error;
752100384Speter
753144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
754144450Sjhb	if (error)
755144450Sjhb		return (error);
756144450Sjhb	error = kern_readv(td, uap->fd, auio);
757144450Sjhb	free(auio, M_IOV);
758100384Speter	return (error);
759100384Speter}
760100384Speter
761100384Speterint
762119333Speterfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
763100384Speter{
764144450Sjhb	struct uio *auio;
765144450Sjhb	int error;
766100384Speter
767144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
768144450Sjhb	if (error)
769144450Sjhb		return (error);
770144450Sjhb	error = kern_writev(td, uap->fd, auio);
771144450Sjhb	free(auio, M_IOV);
772100384Speter	return (error);
773100384Speter}
774100384Speter
775100384Speterint
776147813Sjhbfreebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
777147813Sjhb{
778147813Sjhb	struct uio *auio;
779147813Sjhb	int error;
780147813Sjhb
781147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
782147813Sjhb	if (error)
783147813Sjhb		return (error);
784147813Sjhb	error = kern_preadv(td, uap->fd, auio, uap->offset);
785147813Sjhb	free(auio, M_IOV);
786147813Sjhb	return (error);
787147813Sjhb}
788147813Sjhb
789147813Sjhbint
790147813Sjhbfreebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
791147813Sjhb{
792147813Sjhb	struct uio *auio;
793147813Sjhb	int error;
794147813Sjhb
795147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
796147813Sjhb	if (error)
797147813Sjhb		return (error);
798147813Sjhb	error = kern_pwritev(td, uap->fd, auio, uap->offset);
799147813Sjhb	free(auio, M_IOV);
800147813Sjhb	return (error);
801147813Sjhb}
802147813Sjhb
803151359Spsstatic int
804151909Spsfreebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
805151359Sps    int error)
806151359Sps{
807151359Sps	struct iovec32 iov32;
808151909Sps	struct iovec *iov;
809151909Sps	u_int iovlen;
810151359Sps	int i;
811151359Sps
812151909Sps	*iovp = NULL;
813151359Sps	if (iovcnt > UIO_MAXIOV)
814151359Sps		return (error);
815151359Sps	iovlen = iovcnt * sizeof(struct iovec);
816151909Sps	iov = malloc(iovlen, M_IOV, M_WAITOK);
817151359Sps	for (i = 0; i < iovcnt; i++) {
818151909Sps		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
819151359Sps		if (error) {
820151909Sps			free(iov, M_IOV);
821151359Sps			return (error);
822151359Sps		}
823151909Sps		iov[i].iov_base = PTRIN(iov32.iov_base);
824151909Sps		iov[i].iov_len = iov32.iov_len;
825151359Sps	}
826151909Sps	*iovp = iov;
827151359Sps	return (0);
828151359Sps}
829151359Sps
830151909Spsstatic int
831151909Spsfreebsd32_copyoutiov(struct iovec *iov, u_int iovcnt, struct iovec32 *iovp,
832151909Sps    int error)
833151909Sps{
834151909Sps	struct iovec32 iov32;
835151909Sps	int i;
836151909Sps
837151909Sps	if (iovcnt > UIO_MAXIOV)
838151909Sps		return (error);
839151909Sps	for (i = 0; i < iovcnt; i++) {
840151909Sps		iov32.iov_base = PTROUT(iov[i].iov_base);
841151909Sps		iov32.iov_len = iov[i].iov_len;
842151909Sps		error = copyout(&iov32, &iovp[i], sizeof(iov32));
843151909Sps		if (error)
844151909Sps			return (error);
845151909Sps	}
846151909Sps	return (0);
847151909Sps}
848151909Sps
849151909Sps
850151359Spsstruct msghdr32 {
851151359Sps	u_int32_t	 msg_name;
852151359Sps	socklen_t	 msg_namelen;
853151359Sps	u_int32_t	 msg_iov;
854151359Sps	int		 msg_iovlen;
855151359Sps	u_int32_t	 msg_control;
856151359Sps	socklen_t	 msg_controllen;
857151359Sps	int		 msg_flags;
858151359Sps};
859151359SpsCTASSERT(sizeof(struct msghdr32) == 28);
860151359Sps
861151359Spsstatic int
862151359Spsfreebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
863151359Sps{
864151359Sps	struct msghdr32 m32;
865151359Sps	int error;
866151359Sps
867151359Sps	error = copyin(msg32, &m32, sizeof(m32));
868151359Sps	if (error)
869151359Sps		return (error);
870151359Sps	msg->msg_name = PTRIN(m32.msg_name);
871151359Sps	msg->msg_namelen = m32.msg_namelen;
872151359Sps	msg->msg_iov = PTRIN(m32.msg_iov);
873151359Sps	msg->msg_iovlen = m32.msg_iovlen;
874151359Sps	msg->msg_control = PTRIN(m32.msg_control);
875151359Sps	msg->msg_controllen = m32.msg_controllen;
876151359Sps	msg->msg_flags = m32.msg_flags;
877151909Sps	return (0);
878151359Sps}
879151359Sps
880151359Spsstatic int
881151359Spsfreebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
882151359Sps{
883151359Sps	struct msghdr32 m32;
884151359Sps	int error;
885151359Sps
886151359Sps	m32.msg_name = PTROUT(msg->msg_name);
887151359Sps	m32.msg_namelen = msg->msg_namelen;
888151359Sps	m32.msg_iov = PTROUT(msg->msg_iov);
889151359Sps	m32.msg_iovlen = msg->msg_iovlen;
890151359Sps	m32.msg_control = PTROUT(msg->msg_control);
891151359Sps	m32.msg_controllen = msg->msg_controllen;
892151359Sps	m32.msg_flags = msg->msg_flags;
893151359Sps	error = copyout(&m32, msg32, sizeof(m32));
894151359Sps	return (error);
895151359Sps}
896151359Sps
897151909Sps#define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
898151909Sps#define FREEBSD32_ALIGN(p)	\
899151909Sps	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
900151909Sps#define	FREEBSD32_CMSG_SPACE(l)	\
901151909Sps	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
902151909Sps
903151909Sps#define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
904151909Sps				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
905151909Spsstatic int
906151909Spsfreebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
907151909Sps{
908151909Sps	struct cmsghdr *cm;
909151909Sps	void *data;
910151909Sps	socklen_t clen, datalen;
911151909Sps	int error;
912151909Sps	caddr_t ctlbuf;
913151909Sps	int len, maxlen, copylen;
914151909Sps	struct mbuf *m;
915151909Sps	error = 0;
916151909Sps
917151909Sps	len    = msg->msg_controllen;
918151909Sps	maxlen = msg->msg_controllen;
919151909Sps	msg->msg_controllen = 0;
920151909Sps
921151909Sps	m = control;
922151909Sps	ctlbuf = msg->msg_control;
923151909Sps
924151909Sps	while (m && len > 0) {
925151909Sps		cm = mtod(m, struct cmsghdr *);
926151909Sps		clen = m->m_len;
927151909Sps
928151909Sps		while (cm != NULL) {
929151909Sps
930151909Sps			if (sizeof(struct cmsghdr) > clen ||
931151909Sps			    cm->cmsg_len > clen) {
932151909Sps				error = EINVAL;
933151909Sps				break;
934151909Sps			}
935151909Sps
936151909Sps			data   = CMSG_DATA(cm);
937151909Sps			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
938151909Sps
939151909Sps			/* Adjust message length */
940151909Sps			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
941151909Sps			    datalen;
942151909Sps
943151909Sps
944151909Sps			/* Copy cmsghdr */
945151909Sps			copylen = sizeof(struct cmsghdr);
946151909Sps			if (len < copylen) {
947151909Sps				msg->msg_flags |= MSG_CTRUNC;
948151909Sps				copylen = len;
949151909Sps			}
950151909Sps
951151909Sps			error = copyout(cm,ctlbuf,copylen);
952151909Sps			if (error)
953151909Sps				goto exit;
954151909Sps
955151909Sps			ctlbuf += FREEBSD32_ALIGN(copylen);
956151909Sps			len    -= FREEBSD32_ALIGN(copylen);
957151909Sps
958151909Sps			if (len <= 0)
959151909Sps				break;
960151909Sps
961151909Sps			/* Copy data */
962151909Sps			copylen = datalen;
963151909Sps			if (len < copylen) {
964151909Sps				msg->msg_flags |= MSG_CTRUNC;
965151909Sps				copylen = len;
966151909Sps			}
967151909Sps
968151909Sps			error = copyout(data,ctlbuf,copylen);
969151909Sps			if (error)
970151909Sps				goto exit;
971151909Sps
972151909Sps			ctlbuf += FREEBSD32_ALIGN(copylen);
973151909Sps			len    -= FREEBSD32_ALIGN(copylen);
974151909Sps
975151909Sps			if (CMSG_SPACE(datalen) < clen) {
976151909Sps				clen -= CMSG_SPACE(datalen);
977151909Sps				cm = (struct cmsghdr *)
978151909Sps					((caddr_t)cm + CMSG_SPACE(datalen));
979151909Sps			} else {
980151909Sps				clen = 0;
981151909Sps				cm = NULL;
982151909Sps			}
983151909Sps		}
984151909Sps		m = m->m_next;
985151909Sps	}
986151909Sps
987151909Sps	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
988151909Sps
989151909Spsexit:
990151909Sps	return (error);
991151909Sps
992151909Sps}
993151909Sps
994147813Sjhbint
995151359Spsfreebsd32_recvmsg(td, uap)
996151359Sps	struct thread *td;
997151359Sps	struct freebsd32_recvmsg_args /* {
998151359Sps		int	s;
999151359Sps		struct	msghdr32 *msg;
1000151359Sps		int	flags;
1001151359Sps	} */ *uap;
1002151359Sps{
1003151359Sps	struct msghdr msg;
1004151359Sps	struct msghdr32 m32;
1005151359Sps	struct iovec *uiov, *iov;
1006151909Sps	struct mbuf *control = NULL;
1007151909Sps	struct mbuf **controlp;
1008151909Sps
1009151359Sps	int error;
1010151359Sps	error = copyin(uap->msg, &m32, sizeof(m32));
1011151359Sps	if (error)
1012151359Sps		return (error);
1013151359Sps	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1014151359Sps	if (error)
1015151359Sps		return (error);
1016151359Sps	error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov,
1017151359Sps	    m32.msg_iovlen, &iov, EMSGSIZE);
1018151359Sps	if (error)
1019151359Sps		return (error);
1020151359Sps	msg.msg_flags = uap->flags;
1021151359Sps	uiov = msg.msg_iov;
1022151359Sps	msg.msg_iov = iov;
1023151909Sps
1024151909Sps	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1025151909Sps	error = kern_recvit(td, uap->s, &msg, NULL, UIO_USERSPACE, controlp);
1026151359Sps	if (error == 0) {
1027151359Sps		msg.msg_iov = uiov;
1028151909Sps
1029151909Sps		if (control != NULL)
1030151909Sps			error = freebsd32_copy_msg_out(&msg, control);
1031151909Sps
1032151909Sps		if (error == 0)
1033151909Sps			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1034151909Sps
1035151909Sps		if (error == 0)
1036151909Sps			error = freebsd32_copyoutiov(iov, iov->iov_len,
1037151909Sps			    (struct iovec32 *)(uintptr_t)m32.msg_iov, EMSGSIZE);
1038151359Sps	}
1039151359Sps	free(iov, M_IOV);
1040151909Sps
1041151909Sps	if (control != NULL)
1042151909Sps		m_freem(control);
1043151909Sps
1044151359Sps	return (error);
1045151359Sps}
1046151359Sps
1047151909Sps
1048151909Spsstatic int
1049151909Spsfreebsd32_convert_msg_in(struct mbuf **controlp)
1050151909Sps{
1051151909Sps	struct mbuf *control = *controlp;
1052151909Sps	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1053151909Sps	void *data;
1054151909Sps	socklen_t clen = control->m_len, datalen;
1055151909Sps	int error;
1056151909Sps
1057151909Sps	error = 0;
1058151909Sps	*controlp = NULL;
1059151909Sps
1060151909Sps	while (cm != NULL) {
1061151909Sps		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1062151909Sps			error = EINVAL;
1063151909Sps			break;
1064151909Sps		}
1065151909Sps
1066151909Sps		data = FREEBSD32_CMSG_DATA(cm);
1067151909Sps		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1068151909Sps
1069151909Sps		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1070151909Sps		    cm->cmsg_level);
1071151909Sps		controlp = &(*controlp)->m_next;
1072151909Sps
1073151909Sps		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1074151909Sps			clen -= FREEBSD32_CMSG_SPACE(datalen);
1075151909Sps			cm = (struct cmsghdr *)
1076151909Sps				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1077151909Sps		} else {
1078151909Sps			clen = 0;
1079151909Sps			cm = NULL;
1080151909Sps		}
1081151909Sps	}
1082151909Sps
1083151909Sps	m_freem(control);
1084151909Sps	return (error);
1085151909Sps}
1086151909Sps
1087151909Sps
1088151359Spsint
1089151359Spsfreebsd32_sendmsg(struct thread *td,
1090151359Sps		  struct freebsd32_sendmsg_args *uap)
1091151359Sps{
1092151359Sps	struct msghdr msg;
1093151359Sps	struct msghdr32 m32;
1094151359Sps	struct iovec *iov;
1095151909Sps	struct mbuf *control = NULL;
1096151909Sps	struct sockaddr *to = NULL;
1097151359Sps	int error;
1098151359Sps
1099151359Sps	error = copyin(uap->msg, &m32, sizeof(m32));
1100151359Sps	if (error)
1101151359Sps		return (error);
1102151359Sps	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1103151359Sps	if (error)
1104151359Sps		return (error);
1105151359Sps	error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov,
1106151359Sps	    m32.msg_iovlen, &iov, EMSGSIZE);
1107151359Sps	if (error)
1108151359Sps		return (error);
1109151359Sps	msg.msg_iov = iov;
1110151909Sps	if (msg.msg_name != NULL) {
1111151909Sps		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1112151909Sps		if (error) {
1113151909Sps			to = NULL;
1114151909Sps			goto out;
1115151909Sps		}
1116151909Sps		msg.msg_name = to;
1117151909Sps	}
1118151909Sps
1119151909Sps	if (msg.msg_control) {
1120151909Sps		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1121151909Sps			error = EINVAL;
1122151909Sps			goto out;
1123151909Sps		}
1124151909Sps
1125151909Sps		error = sockargs(&control, msg.msg_control,
1126151909Sps		    msg.msg_controllen, MT_CONTROL);
1127151909Sps		if (error)
1128151909Sps			goto out;
1129151909Sps
1130151909Sps		error = freebsd32_convert_msg_in(&control);
1131151909Sps		if (error)
1132151909Sps			goto out;
1133151909Sps	}
1134151909Sps
1135151909Sps	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1136151909Sps	    UIO_USERSPACE);
1137151909Sps
1138151909Spsout:
1139151359Sps	free(iov, M_IOV);
1140151909Sps	if (to)
1141151909Sps		free(to, M_SONAME);
1142151359Sps	return (error);
1143151359Sps}
1144151359Sps
1145151359Spsint
1146151359Spsfreebsd32_recvfrom(struct thread *td,
1147151359Sps		   struct freebsd32_recvfrom_args *uap)
1148151359Sps{
1149151359Sps	struct msghdr msg;
1150151359Sps	struct iovec aiov;
1151151359Sps	int error;
1152151359Sps
1153151359Sps	if (uap->fromlenaddr) {
1154151359Sps		error = copyin((void *)(uintptr_t)uap->fromlenaddr,
1155151359Sps		    &msg.msg_namelen, sizeof(msg.msg_namelen));
1156151359Sps		if (error)
1157151359Sps			return (error);
1158151359Sps	} else {
1159151359Sps		msg.msg_namelen = 0;
1160151359Sps	}
1161151359Sps
1162151359Sps	msg.msg_name = (void *)(uintptr_t)uap->from;
1163151359Sps	msg.msg_iov = &aiov;
1164151359Sps	msg.msg_iovlen = 1;
1165151359Sps	aiov.iov_base = (void *)(uintptr_t)uap->buf;
1166151359Sps	aiov.iov_len = uap->len;
1167151359Sps	msg.msg_control = 0;
1168151359Sps	msg.msg_flags = uap->flags;
1169151909Sps	error = kern_recvit(td, uap->s, &msg,
1170151909Sps	    (void *)(uintptr_t)uap->fromlenaddr, UIO_USERSPACE, NULL);
1171151359Sps	return (error);
1172151359Sps}
1173151359Sps
1174151359Spsint
1175119333Speterfreebsd32_settimeofday(struct thread *td,
1176119333Speter		       struct freebsd32_settimeofday_args *uap)
1177100384Speter{
1178144450Sjhb	struct timeval32 tv32;
1179144450Sjhb	struct timeval tv, *tvp;
1180144450Sjhb	struct timezone tz, *tzp;
1181100384Speter	int error;
1182100384Speter
1183144450Sjhb	if (uap->tv) {
1184144450Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
1185100384Speter		if (error)
1186100384Speter			return (error);
1187144450Sjhb		CP(tv32, tv, tv_sec);
1188144450Sjhb		CP(tv32, tv, tv_usec);
1189144450Sjhb		tvp = &tv;
1190144450Sjhb	} else
1191144450Sjhb		tvp = NULL;
1192144450Sjhb	if (uap->tzp) {
1193144450Sjhb		error = copyin(uap->tzp, &tz, sizeof(tz));
1194100384Speter		if (error)
1195100384Speter			return (error);
1196144450Sjhb		tzp = &tz;
1197144450Sjhb	} else
1198144450Sjhb		tzp = NULL;
1199144450Sjhb	return (kern_settimeofday(td, tvp, tzp));
1200100384Speter}
1201100384Speter
1202100384Speterint
1203119333Speterfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1204100384Speter{
1205142059Sjhb	struct timeval32 s32[2];
1206142059Sjhb	struct timeval s[2], *sp;
1207100384Speter	int error;
1208100384Speter
1209142059Sjhb	if (uap->tptr != NULL) {
1210142059Sjhb		error = copyin(uap->tptr, s32, sizeof(s32));
1211100384Speter		if (error)
1212100384Speter			return (error);
1213100384Speter		CP(s32[0], s[0], tv_sec);
1214100384Speter		CP(s32[0], s[0], tv_usec);
1215100384Speter		CP(s32[1], s[1], tv_sec);
1216100384Speter		CP(s32[1], s[1], tv_usec);
1217142059Sjhb		sp = s;
1218142059Sjhb	} else
1219142059Sjhb		sp = NULL;
1220142059Sjhb	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1221100384Speter}
1222100384Speter
1223100384Speterint
1224119333Speterfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1225100384Speter{
1226144450Sjhb	struct timeval32 tv32;
1227144450Sjhb	struct timeval delta, olddelta, *deltap;
1228100384Speter	int error;
1229100384Speter
1230144450Sjhb	if (uap->delta) {
1231144450Sjhb		error = copyin(uap->delta, &tv32, sizeof(tv32));
1232100384Speter		if (error)
1233100384Speter			return (error);
1234144450Sjhb		CP(tv32, delta, tv_sec);
1235144450Sjhb		CP(tv32, delta, tv_usec);
1236144450Sjhb		deltap = &delta;
1237144450Sjhb	} else
1238144450Sjhb		deltap = NULL;
1239144450Sjhb	error = kern_adjtime(td, deltap, &olddelta);
1240144450Sjhb	if (uap->olddelta && error == 0) {
1241144450Sjhb		CP(olddelta, tv32, tv_sec);
1242144450Sjhb		CP(olddelta, tv32, tv_usec);
1243144450Sjhb		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1244100384Speter	}
1245100384Speter	return (error);
1246100384Speter}
1247100384Speter
1248128597Smarcel#ifdef COMPAT_FREEBSD4
1249100384Speterint
1250128260Speterfreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1251100384Speter{
1252142059Sjhb	struct statfs32 s32;
1253142059Sjhb	struct statfs s;
1254100384Speter	int error;
1255100384Speter
1256142059Sjhb	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1257100384Speter	if (error)
1258100384Speter		return (error);
1259142059Sjhb	copy_statfs(&s, &s32);
1260142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1261100384Speter}
1262128597Smarcel#endif
1263100384Speter
1264128597Smarcel#ifdef COMPAT_FREEBSD4
1265100384Speterint
1266128260Speterfreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1267100384Speter{
1268142059Sjhb	struct statfs32 s32;
1269142059Sjhb	struct statfs s;
1270100384Speter	int error;
1271100384Speter
1272142059Sjhb	error = kern_fstatfs(td, uap->fd, &s);
1273100384Speter	if (error)
1274100384Speter		return (error);
1275142059Sjhb	copy_statfs(&s, &s32);
1276142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1277100384Speter}
1278128597Smarcel#endif
1279100384Speter
1280128597Smarcel#ifdef COMPAT_FREEBSD4
1281100384Speterint
1282128260Speterfreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1283128260Speter{
1284142059Sjhb	struct statfs32 s32;
1285142059Sjhb	struct statfs s;
1286142059Sjhb	fhandle_t fh;
1287128260Speter	int error;
1288128260Speter
1289142059Sjhb	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1290142059Sjhb		return (error);
1291142059Sjhb	error = kern_fhstatfs(td, fh, &s);
1292128260Speter	if (error)
1293128260Speter		return (error);
1294142059Sjhb	copy_statfs(&s, &s32);
1295142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1296128260Speter}
1297128597Smarcel#endif
1298128260Speter
1299128260Speterint
1300119333Speterfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1301100384Speter{
1302100384Speter	/*
1303100384Speter	 * Vector through to semsys if it is loaded.
1304100384Speter	 */
1305150883Sjhb	return sysent[SYS_semsys].sy_call(td, uap);
1306100384Speter}
1307100384Speter
1308100384Speterint
1309119333Speterfreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1310100384Speter{
1311100384Speter	/*
1312100384Speter	 * Vector through to msgsys if it is loaded.
1313100384Speter	 */
1314150883Sjhb	return sysent[SYS_msgsys].sy_call(td, uap);
1315100384Speter}
1316100384Speter
1317100384Speterint
1318119333Speterfreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1319100384Speter{
1320100384Speter	/*
1321100384Speter	 * Vector through to shmsys if it is loaded.
1322100384Speter	 */
1323150883Sjhb	return sysent[SYS_shmsys].sy_call(td, uap);
1324100384Speter}
1325100384Speter
1326100384Speterint
1327119333Speterfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1328100384Speter{
1329100384Speter	struct pread_args ap;
1330100384Speter
1331107849Salfred	ap.fd = uap->fd;
1332107849Salfred	ap.buf = uap->buf;
1333107849Salfred	ap.nbyte = uap->nbyte;
1334119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1335100384Speter	return (pread(td, &ap));
1336100384Speter}
1337100384Speter
1338100384Speterint
1339119333Speterfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1340100384Speter{
1341100384Speter	struct pwrite_args ap;
1342100384Speter
1343107849Salfred	ap.fd = uap->fd;
1344107849Salfred	ap.buf = uap->buf;
1345107849Salfred	ap.nbyte = uap->nbyte;
1346119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1347100384Speter	return (pwrite(td, &ap));
1348100384Speter}
1349100384Speter
1350100384Speterint
1351119333Speterfreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1352100384Speter{
1353100384Speter	int error;
1354100384Speter	struct lseek_args ap;
1355100384Speter	off_t pos;
1356100384Speter
1357107849Salfred	ap.fd = uap->fd;
1358119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1359107849Salfred	ap.whence = uap->whence;
1360100384Speter	error = lseek(td, &ap);
1361100384Speter	/* Expand the quad return into two parts for eax and edx */
1362100384Speter	pos = *(off_t *)(td->td_retval);
1363100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1364100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
1365100384Speter	return error;
1366100384Speter}
1367100384Speter
1368100384Speterint
1369119333Speterfreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1370100384Speter{
1371100384Speter	struct truncate_args ap;
1372100384Speter
1373107849Salfred	ap.path = uap->path;
1374119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1375100384Speter	return (truncate(td, &ap));
1376100384Speter}
1377100384Speter
1378100384Speterint
1379119333Speterfreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1380100384Speter{
1381100384Speter	struct ftruncate_args ap;
1382100384Speter
1383107849Salfred	ap.fd = uap->fd;
1384119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1385100384Speter	return (ftruncate(td, &ap));
1386100384Speter}
1387100384Speter
1388104738Speter#ifdef COMPAT_FREEBSD4
1389100384Speterint
1390119333Speterfreebsd4_freebsd32_sendfile(struct thread *td,
1391119333Speter    struct freebsd4_freebsd32_sendfile_args *uap)
1392104738Speter{
1393104738Speter	struct freebsd4_sendfile_args ap;
1394104738Speter
1395107849Salfred	ap.fd = uap->fd;
1396107849Salfred	ap.s = uap->s;
1397119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1398107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1399107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1400107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1401107849Salfred	ap.flags = uap->flags;
1402104738Speter	return (freebsd4_sendfile(td, &ap));
1403104738Speter}
1404104738Speter#endif
1405104738Speter
1406104738Speterint
1407119333Speterfreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1408100384Speter{
1409100384Speter	struct sendfile_args ap;
1410100384Speter
1411107849Salfred	ap.fd = uap->fd;
1412107849Salfred	ap.s = uap->s;
1413119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1414107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1415107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1416107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1417107849Salfred	ap.flags = uap->flags;
1418100384Speter	return (sendfile(td, &ap));
1419100384Speter}
1420100384Speter
1421100384Speterstruct stat32 {
1422130640Sphk	dev_t	st_dev;
1423100384Speter	ino_t	st_ino;
1424100384Speter	mode_t	st_mode;
1425100384Speter	nlink_t	st_nlink;
1426100384Speter	uid_t	st_uid;
1427100384Speter	gid_t	st_gid;
1428130640Sphk	dev_t	st_rdev;
1429100384Speter	struct timespec32 st_atimespec;
1430100384Speter	struct timespec32 st_mtimespec;
1431100384Speter	struct timespec32 st_ctimespec;
1432100384Speter	off_t	st_size;
1433100384Speter	int64_t	st_blocks;
1434100384Speter	u_int32_t st_blksize;
1435100384Speter	u_int32_t st_flags;
1436100384Speter	u_int32_t st_gen;
1437121719Speter	struct timespec32 st_birthtimespec;
1438121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1439121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1440100384Speter};
1441100384Speter
1442121719Speter
1443121719SpeterCTASSERT(sizeof(struct stat32) == 96);
1444121719Speter
1445100384Speterstatic void
1446100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1447100384Speter{
1448100384Speter	CP(*in, *out, st_dev);
1449100384Speter	CP(*in, *out, st_ino);
1450100384Speter	CP(*in, *out, st_mode);
1451100384Speter	CP(*in, *out, st_nlink);
1452100384Speter	CP(*in, *out, st_uid);
1453100384Speter	CP(*in, *out, st_gid);
1454100384Speter	CP(*in, *out, st_rdev);
1455100384Speter	TS_CP(*in, *out, st_atimespec);
1456100384Speter	TS_CP(*in, *out, st_mtimespec);
1457100384Speter	TS_CP(*in, *out, st_ctimespec);
1458100384Speter	CP(*in, *out, st_size);
1459100384Speter	CP(*in, *out, st_blocks);
1460100384Speter	CP(*in, *out, st_blksize);
1461100384Speter	CP(*in, *out, st_flags);
1462100384Speter	CP(*in, *out, st_gen);
1463100384Speter}
1464100384Speter
1465100384Speterint
1466119333Speterfreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1467100384Speter{
1468123746Speter	struct stat sb;
1469123746Speter	struct stat32 sb32;
1470100384Speter	int error;
1471100384Speter
1472142059Sjhb	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1473100384Speter	if (error)
1474100384Speter		return (error);
1475123746Speter	copy_stat(&sb, &sb32);
1476123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1477100384Speter	return (error);
1478100384Speter}
1479100384Speter
1480100384Speterint
1481119333Speterfreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1482100384Speter{
1483123746Speter	struct stat ub;
1484123746Speter	struct stat32 ub32;
1485100384Speter	int error;
1486100384Speter
1487142059Sjhb	error = kern_fstat(td, uap->fd, &ub);
1488100384Speter	if (error)
1489100384Speter		return (error);
1490123746Speter	copy_stat(&ub, &ub32);
1491123746Speter	error = copyout(&ub32, uap->ub, sizeof(ub32));
1492100384Speter	return (error);
1493100384Speter}
1494100384Speter
1495100384Speterint
1496119333Speterfreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1497100384Speter{
1498123746Speter	struct stat sb;
1499123746Speter	struct stat32 sb32;
1500142059Sjhb	int error;
1501100384Speter
1502142059Sjhb	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1503100384Speter	if (error)
1504100384Speter		return (error);
1505123746Speter	copy_stat(&sb, &sb32);
1506123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1507100384Speter	return (error);
1508100384Speter}
1509100384Speter
1510100384Speter/*
1511100384Speter * MPSAFE
1512100384Speter */
1513100384Speterint
1514119333Speterfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1515100384Speter{
1516100384Speter	int error, name[CTL_MAXNAME];
1517100384Speter	size_t j, oldlen;
1518100384Speter
1519100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1520100384Speter		return (EINVAL);
1521136404Speter 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1522100384Speter 	if (error)
1523100384Speter		return (error);
1524100384Speter	mtx_lock(&Giant);
1525100384Speter	if (uap->oldlenp)
1526100384Speter		oldlen = fuword32(uap->oldlenp);
1527100384Speter	else
1528100384Speter		oldlen = 0;
1529100384Speter	error = userland_sysctl(td, name, uap->namelen,
1530100384Speter		uap->old, &oldlen, 1,
1531136404Speter		uap->new, uap->newlen, &j, SCTL_MASK32);
1532100384Speter	if (error && error != ENOMEM)
1533100384Speter		goto done2;
1534136404Speter	if (uap->oldlenp)
1535100384Speter		suword32(uap->oldlenp, j);
1536100384Speterdone2:
1537100384Speter	mtx_unlock(&Giant);
1538100384Speter	return (error);
1539100384Speter}
1540100384Speter
1541100384Speterstruct sigaction32 {
1542100384Speter	u_int32_t	sa_u;
1543100384Speter	int		sa_flags;
1544100384Speter	sigset_t	sa_mask;
1545100384Speter};
1546100384Speter
1547121719SpeterCTASSERT(sizeof(struct sigaction32) == 24);
1548121719Speter
1549100384Speterint
1550119333Speterfreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1551100384Speter{
1552113859Sjhb	struct sigaction32 s32;
1553113859Sjhb	struct sigaction sa, osa, *sap;
1554100384Speter	int error;
1555100384Speter
1556113859Sjhb	if (uap->act) {
1557113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
1558100384Speter		if (error)
1559100384Speter			return (error);
1560113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
1561113859Sjhb		CP(s32, sa, sa_flags);
1562113859Sjhb		CP(s32, sa, sa_mask);
1563113859Sjhb		sap = &sa;
1564113859Sjhb	} else
1565113859Sjhb		sap = NULL;
1566113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1567146583Sps	if (error == 0 && uap->oact != NULL) {
1568113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
1569113859Sjhb		CP(osa, s32, sa_flags);
1570113859Sjhb		CP(osa, s32, sa_mask);
1571113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
1572100384Speter	}
1573100384Speter	return (error);
1574100384Speter}
1575100384Speter
1576114987Speter#ifdef COMPAT_FREEBSD4
1577114987Speterint
1578119333Speterfreebsd4_freebsd32_sigaction(struct thread *td,
1579119333Speter			     struct freebsd4_freebsd32_sigaction_args *uap)
1580114987Speter{
1581114987Speter	struct sigaction32 s32;
1582114987Speter	struct sigaction sa, osa, *sap;
1583114987Speter	int error;
1584114987Speter
1585114987Speter	if (uap->act) {
1586114987Speter		error = copyin(uap->act, &s32, sizeof(s32));
1587114987Speter		if (error)
1588114987Speter			return (error);
1589114987Speter		sa.sa_handler = PTRIN(s32.sa_u);
1590114987Speter		CP(s32, sa, sa_flags);
1591114987Speter		CP(s32, sa, sa_mask);
1592114987Speter		sap = &sa;
1593114987Speter	} else
1594114987Speter		sap = NULL;
1595114987Speter	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1596146583Sps	if (error == 0 && uap->oact != NULL) {
1597114987Speter		s32.sa_u = PTROUT(osa.sa_handler);
1598114987Speter		CP(osa, s32, sa_flags);
1599114987Speter		CP(osa, s32, sa_mask);
1600114987Speter		error = copyout(&s32, uap->oact, sizeof(s32));
1601114987Speter	}
1602114987Speter	return (error);
1603114987Speter}
1604114987Speter#endif
1605114987Speter
1606151582Sps#ifdef COMPAT_43
1607151720Speterstruct osigaction32 {
1608151582Sps	u_int32_t	sa_u;
1609151582Sps	osigset_t	sa_mask;
1610151582Sps	int		sa_flags;
1611151582Sps};
1612151582Sps
1613151582Sps#define	ONSIG	32
1614151582Sps
1615140481Spsint
1616151720Speterofreebsd32_sigaction(struct thread *td,
1617151720Speter			     struct ofreebsd32_sigaction_args *uap)
1618151582Sps{
1619151720Speter	struct osigaction32 s32;
1620151582Sps	struct sigaction sa, osa, *sap;
1621151582Sps	int error;
1622151582Sps
1623151582Sps	if (uap->signum <= 0 || uap->signum >= ONSIG)
1624151582Sps		return (EINVAL);
1625151582Sps
1626151582Sps	if (uap->nsa) {
1627151582Sps		error = copyin(uap->nsa, &s32, sizeof(s32));
1628151582Sps		if (error)
1629151582Sps			return (error);
1630151582Sps		sa.sa_handler = PTRIN(s32.sa_u);
1631151582Sps		CP(s32, sa, sa_flags);
1632151582Sps		OSIG2SIG(s32.sa_mask, sa.sa_mask);
1633151582Sps		sap = &sa;
1634151582Sps	} else
1635151582Sps		sap = NULL;
1636151582Sps	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1637151582Sps	if (error == 0 && uap->osa != NULL) {
1638151582Sps		s32.sa_u = PTROUT(osa.sa_handler);
1639151582Sps		CP(osa, s32, sa_flags);
1640151582Sps		SIG2OSIG(osa.sa_mask, s32.sa_mask);
1641151582Sps		error = copyout(&s32, uap->osa, sizeof(s32));
1642151582Sps	}
1643151582Sps	return (error);
1644151582Sps}
1645151582Sps
1646151582Spsint
1647151720Speterofreebsd32_sigprocmask(struct thread *td,
1648151720Speter			       struct ofreebsd32_sigprocmask_args *uap)
1649151582Sps{
1650151582Sps	sigset_t set, oset;
1651151582Sps	int error;
1652151582Sps
1653151582Sps	OSIG2SIG(uap->mask, set);
1654151582Sps	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
1655151582Sps	SIG2OSIG(oset, td->td_retval[0]);
1656151582Sps	return (error);
1657151582Sps}
1658151582Sps
1659151582Spsint
1660151720Speterofreebsd32_sigpending(struct thread *td,
1661151720Speter			      struct ofreebsd32_sigpending_args *uap)
1662151582Sps{
1663151582Sps	struct proc *p = td->td_proc;
1664151582Sps	sigset_t siglist;
1665151582Sps
1666151582Sps	PROC_LOCK(p);
1667151582Sps	siglist = p->p_siglist;
1668151582Sps	SIGSETOR(siglist, td->td_siglist);
1669151582Sps	PROC_UNLOCK(p);
1670151582Sps	SIG2OSIG(siglist, td->td_retval[0]);
1671151582Sps	return (0);
1672151582Sps}
1673151582Sps
1674151582Spsstruct sigvec32 {
1675151582Sps	u_int32_t	sv_handler;
1676151582Sps	int		sv_mask;
1677151582Sps	int		sv_flags;
1678151582Sps};
1679151582Sps
1680151582Spsint
1681151720Speterofreebsd32_sigvec(struct thread *td,
1682151720Speter			  struct ofreebsd32_sigvec_args *uap)
1683151582Sps{
1684151582Sps	struct sigvec32 vec;
1685151582Sps	struct sigaction sa, osa, *sap;
1686151582Sps	int error;
1687151582Sps
1688151582Sps	if (uap->signum <= 0 || uap->signum >= ONSIG)
1689151582Sps		return (EINVAL);
1690151582Sps
1691151582Sps	if (uap->nsv) {
1692151582Sps		error = copyin(uap->nsv, &vec, sizeof(vec));
1693151582Sps		if (error)
1694151582Sps			return (error);
1695151582Sps		sa.sa_handler = PTRIN(vec.sv_handler);
1696151582Sps		OSIG2SIG(vec.sv_mask, sa.sa_mask);
1697151582Sps		sa.sa_flags = vec.sv_flags;
1698151582Sps		sa.sa_flags ^= SA_RESTART;
1699151582Sps		sap = &sa;
1700151582Sps	} else
1701151582Sps		sap = NULL;
1702151582Sps	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1703151582Sps	if (error == 0 && uap->osv != NULL) {
1704151582Sps		vec.sv_handler = PTROUT(osa.sa_handler);
1705151582Sps		SIG2OSIG(osa.sa_mask, vec.sv_mask);
1706151582Sps		vec.sv_flags = osa.sa_flags;
1707151582Sps		vec.sv_flags &= ~SA_NOCLDWAIT;
1708151582Sps		vec.sv_flags ^= SA_RESTART;
1709151582Sps		error = copyout(&vec, uap->osv, sizeof(vec));
1710151582Sps	}
1711151582Sps	return (error);
1712151582Sps}
1713151582Sps
1714151582Spsint
1715151720Speterofreebsd32_sigblock(struct thread *td,
1716151720Speter			    struct ofreebsd32_sigblock_args *uap)
1717151582Sps{
1718151582Sps	struct proc *p = td->td_proc;
1719151582Sps	sigset_t set;
1720151582Sps
1721151582Sps	OSIG2SIG(uap->mask, set);
1722151582Sps	SIG_CANTMASK(set);
1723151582Sps	PROC_LOCK(p);
1724151582Sps	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1725151582Sps	SIGSETOR(td->td_sigmask, set);
1726151582Sps	PROC_UNLOCK(p);
1727151582Sps	return (0);
1728151582Sps}
1729151582Sps
1730151582Spsint
1731151720Speterofreebsd32_sigsetmask(struct thread *td,
1732151720Speter			      struct ofreebsd32_sigsetmask_args *uap)
1733151582Sps{
1734151582Sps	struct proc *p = td->td_proc;
1735151582Sps	sigset_t set;
1736151582Sps
1737151582Sps	OSIG2SIG(uap->mask, set);
1738151582Sps	SIG_CANTMASK(set);
1739151582Sps	PROC_LOCK(p);
1740151582Sps	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1741151582Sps	SIGSETLO(td->td_sigmask, set);
1742151582Sps	signotify(td);
1743151582Sps	PROC_UNLOCK(p);
1744151582Sps	return (0);
1745151582Sps}
1746151582Sps
1747151582Spsint
1748151720Speterofreebsd32_sigsuspend(struct thread *td,
1749151720Speter			      struct ofreebsd32_sigsuspend_args *uap)
1750151582Sps{
1751151582Sps	struct proc *p = td->td_proc;
1752151582Sps	sigset_t mask;
1753151582Sps
1754151582Sps	PROC_LOCK(p);
1755151582Sps	td->td_oldsigmask = td->td_sigmask;
1756151582Sps	td->td_pflags |= TDP_OLDMASK;
1757151582Sps	OSIG2SIG(uap->mask, mask);
1758151582Sps	SIG_CANTMASK(mask);
1759151582Sps	SIGSETLO(td->td_sigmask, mask);
1760151582Sps	signotify(td);
1761151582Sps	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
1762151582Sps		/* void */;
1763151582Sps	PROC_UNLOCK(p);
1764151582Sps	/* always return EINTR rather than ERESTART... */
1765151582Sps	return (EINTR);
1766151582Sps}
1767151582Sps
1768151582Spsstruct sigstack32 {
1769151582Sps	u_int32_t	ss_sp;
1770151582Sps	int		ss_onstack;
1771151582Sps};
1772151582Sps
1773151582Spsint
1774151720Speterofreebsd32_sigstack(struct thread *td,
1775151720Speter			    struct ofreebsd32_sigstack_args *uap)
1776151582Sps{
1777151582Sps	struct sigstack32 s32;
1778151582Sps	struct sigstack nss, oss;
1779151582Sps	int error = 0;
1780151582Sps
1781151582Sps	if (uap->nss != NULL) {
1782151582Sps		error = copyin(uap->nss, &s32, sizeof(s32));
1783151582Sps		if (error)
1784151582Sps			return (error);
1785151582Sps		nss.ss_sp = PTRIN(s32.ss_sp);
1786151582Sps		CP(s32, nss, ss_onstack);
1787151582Sps	}
1788151582Sps	oss.ss_sp = td->td_sigstk.ss_sp;
1789151582Sps	oss.ss_onstack = sigonstack(cpu_getstack(td));
1790151582Sps	if (uap->nss != NULL) {
1791151582Sps		td->td_sigstk.ss_sp = nss.ss_sp;
1792151582Sps		td->td_sigstk.ss_size = 0;
1793151582Sps		td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK;
1794151582Sps		td->td_pflags |= TDP_ALTSTACK;
1795151582Sps	}
1796151582Sps	if (uap->oss != NULL) {
1797151582Sps		s32.ss_sp = PTROUT(oss.ss_sp);
1798151582Sps		CP(oss, s32, ss_onstack);
1799151582Sps		error = copyout(&s32, uap->oss, sizeof(s32));
1800151582Sps	}
1801151582Sps	return (error);
1802151582Sps}
1803151582Sps#endif
1804151582Sps
1805151582Spsint
1806140481Spsfreebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1807140481Sps{
1808140481Sps	struct timespec32 rmt32, rqt32;
1809140481Sps	struct timespec rmt, rqt;
1810140481Sps	int error;
1811140481Sps
1812151355Sps	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
1813140481Sps	if (error)
1814140481Sps		return (error);
1815140481Sps
1816140481Sps	CP(rqt32, rqt, tv_sec);
1817140481Sps	CP(rqt32, rqt, tv_nsec);
1818140481Sps
1819140481Sps	if (uap->rmtp &&
1820140481Sps	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1821140481Sps		return (EFAULT);
1822140481Sps	error = kern_nanosleep(td, &rqt, &rmt);
1823140481Sps	if (error && uap->rmtp) {
1824140481Sps		int error2;
1825140481Sps
1826140481Sps		CP(rmt, rmt32, tv_sec);
1827140481Sps		CP(rmt, rmt32, tv_nsec);
1828140481Sps
1829151355Sps		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
1830140481Sps		if (error2)
1831140481Sps			error = error2;
1832140481Sps	}
1833140481Sps	return (error);
1834140481Sps}
1835140481Sps
1836151357Spsint
1837151357Spsfreebsd32_clock_gettime(struct thread *td,
1838151357Sps			struct freebsd32_clock_gettime_args *uap)
1839151357Sps{
1840151357Sps	struct timespec	ats;
1841151357Sps	struct timespec32 ats32;
1842151357Sps	int error;
1843151357Sps
1844151357Sps	error = kern_clock_gettime(td, uap->clock_id, &ats);
1845151357Sps	if (error == 0) {
1846151357Sps		CP(ats, ats32, tv_sec);
1847151357Sps		CP(ats, ats32, tv_nsec);
1848151357Sps		error = copyout(&ats32, uap->tp, sizeof(ats32));
1849151357Sps	}
1850151357Sps	return (error);
1851151357Sps}
1852151357Sps
1853151357Spsint
1854151357Spsfreebsd32_clock_settime(struct thread *td,
1855151357Sps			struct freebsd32_clock_settime_args *uap)
1856151357Sps{
1857151357Sps	struct timespec	ats;
1858151357Sps	struct timespec32 ats32;
1859151357Sps	int error;
1860151357Sps
1861151357Sps	error = copyin(uap->tp, &ats32, sizeof(ats32));
1862151357Sps	if (error)
1863151357Sps		return (error);
1864151357Sps	CP(ats32, ats, tv_sec);
1865151357Sps	CP(ats32, ats, tv_nsec);
1866151357Sps
1867151357Sps	return (kern_clock_settime(td, uap->clock_id, &ats));
1868151357Sps}
1869151357Sps
1870151357Spsint
1871151357Spsfreebsd32_clock_getres(struct thread *td,
1872151357Sps		       struct freebsd32_clock_getres_args *uap)
1873151357Sps{
1874151357Sps	struct timespec	ts;
1875151357Sps	struct timespec32 ts32;
1876151357Sps	int error;
1877151357Sps
1878151357Sps	if (uap->tp == NULL)
1879151357Sps		return (0);
1880151357Sps	error = kern_clock_getres(td, uap->clock_id, &ts);
1881151357Sps	if (error == 0) {
1882151357Sps		CP(ts, ts32, tv_sec);
1883151357Sps		CP(ts, ts32, tv_nsec);
1884151357Sps		error = copyout(&ts32, uap->tp, sizeof(ts32));
1885151357Sps	}
1886151357Sps	return (error);
1887151357Sps}
1888151357Sps
1889100384Speter#if 0
1890100384Speter
1891100384Speterint
1892119333Speterfreebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1893100384Speter{
1894100384Speter	int error;
1895100384Speter	struct yyy32 *p32, s32;
1896100384Speter	struct yyy *p = NULL, s;
1897100384Speter
1898147654Sjhb	if (uap->zzz) {
1899147654Sjhb		error = copyin(uap->zzz, &s32, sizeof(s32));
1900100384Speter		if (error)
1901100384Speter			return (error);
1902100384Speter		/* translate in */
1903147654Sjhb		p = &s;
1904100384Speter	}
1905147654Sjhb	error = kern_xxx(td, p);
1906100384Speter	if (error)
1907100384Speter		return (error);
1908147654Sjhb	if (uap->zzz) {
1909100384Speter		/* translate out */
1910100384Speter		error = copyout(&s32, p32, sizeof(s32));
1911100384Speter	}
1912100384Speter	return (error);
1913100384Speter}
1914100384Speter
1915100384Speter#endif
1916