freebsd32_misc.c revision 162551
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 162551 2006-09-22 15:04:28Z davidxu $");
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>
41161343Sjkim#include <sys/limits.h>
42100384Speter#include <sys/lock.h>
43100384Speter#include <sys/malloc.h>
44100384Speter#include <sys/file.h>		/* Must come after sys/malloc.h */
45151909Sps#include <sys/mbuf.h>
46100384Speter#include <sys/mman.h>
47100384Speter#include <sys/module.h>
48100384Speter#include <sys/mount.h>
49100384Speter#include <sys/mutex.h>
50100384Speter#include <sys/namei.h>
51100384Speter#include <sys/param.h>
52100384Speter#include <sys/proc.h>
53100384Speter#include <sys/reboot.h>
54100384Speter#include <sys/resource.h>
55100384Speter#include <sys/resourcevar.h>
56100384Speter#include <sys/selinfo.h>
57146950Sps#include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
58100384Speter#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
59100384Speter#include <sys/signal.h>
60100384Speter#include <sys/signalvar.h>
61100384Speter#include <sys/socket.h>
62100384Speter#include <sys/socketvar.h>
63100384Speter#include <sys/stat.h>
64150883Sjhb#include <sys/syscall.h>
65113859Sjhb#include <sys/syscallsubr.h>
66100384Speter#include <sys/sysctl.h>
67100384Speter#include <sys/sysent.h>
68100384Speter#include <sys/sysproto.h>
69100384Speter#include <sys/systm.h>
70162551Sdavidxu#include <sys/thr.h>
71100384Speter#include <sys/unistd.h>
72162551Sdavidxu#include <sys/ucontext.h>
73100384Speter#include <sys/vnode.h>
74127140Sjhb#include <sys/wait.h>
75157285Sps#include <sys/ipc.h>
76157285Sps#include <sys/shm.h>
77100384Speter
78100384Speter#include <vm/vm.h>
79100384Speter#include <vm/vm_kern.h>
80100384Speter#include <vm/vm_param.h>
81100384Speter#include <vm/pmap.h>
82100384Speter#include <vm/vm_map.h>
83100384Speter#include <vm/vm_object.h>
84100384Speter#include <vm/vm_extern.h>
85100384Speter
86151582Sps#include <machine/cpu.h>
87151582Sps
88119333Speter#include <compat/freebsd32/freebsd32_util.h>
89119333Speter#include <compat/freebsd32/freebsd32.h>
90119333Speter#include <compat/freebsd32/freebsd32_proto.h>
91100384Speter
92121719SpeterCTASSERT(sizeof(struct timeval32) == 8);
93121719SpeterCTASSERT(sizeof(struct timespec32) == 8);
94121719SpeterCTASSERT(sizeof(struct statfs32) == 256);
95121719SpeterCTASSERT(sizeof(struct rusage32) == 72);
96121719Speter
97100384Speterint
98119333Speterfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
99100384Speter{
100127140Sjhb	int error, status;
101127140Sjhb	struct rusage32 ru32;
102136152Sjhb	struct rusage ru, *rup;
103100384Speter
104136152Sjhb	if (uap->rusage != NULL)
105136152Sjhb		rup = &ru;
106136152Sjhb	else
107136152Sjhb		rup = NULL;
108136152Sjhb	error = kern_wait(td, uap->pid, &status, uap->options, rup);
109100384Speter	if (error)
110100384Speter		return (error);
111127140Sjhb	if (uap->status != NULL)
112127140Sjhb		error = copyout(&status, uap->status, sizeof(status));
113127140Sjhb	if (uap->rusage != NULL && error == 0) {
114100384Speter		TV_CP(ru, ru32, ru_utime);
115100384Speter		TV_CP(ru, ru32, ru_stime);
116100384Speter		CP(ru, ru32, ru_maxrss);
117100384Speter		CP(ru, ru32, ru_ixrss);
118100384Speter		CP(ru, ru32, ru_idrss);
119100384Speter		CP(ru, ru32, ru_isrss);
120100384Speter		CP(ru, ru32, ru_minflt);
121100384Speter		CP(ru, ru32, ru_majflt);
122100384Speter		CP(ru, ru32, ru_nswap);
123100384Speter		CP(ru, ru32, ru_inblock);
124100384Speter		CP(ru, ru32, ru_oublock);
125100384Speter		CP(ru, ru32, ru_msgsnd);
126100384Speter		CP(ru, ru32, ru_msgrcv);
127100384Speter		CP(ru, ru32, ru_nsignals);
128100384Speter		CP(ru, ru32, ru_nvcsw);
129100384Speter		CP(ru, ru32, ru_nivcsw);
130127140Sjhb		error = copyout(&ru32, uap->rusage, sizeof(ru32));
131100384Speter	}
132100384Speter	return (error);
133100384Speter}
134100384Speter
135128597Smarcel#ifdef COMPAT_FREEBSD4
136100384Speterstatic void
137100384Spetercopy_statfs(struct statfs *in, struct statfs32 *out)
138100384Speter{
139156266Sps
140156266Sps	bzero(out, sizeof(*out));
141100384Speter	CP(*in, *out, f_bsize);
142100384Speter	CP(*in, *out, f_iosize);
143100384Speter	CP(*in, *out, f_blocks);
144100384Speter	CP(*in, *out, f_bfree);
145100384Speter	CP(*in, *out, f_bavail);
146100384Speter	CP(*in, *out, f_files);
147100384Speter	CP(*in, *out, f_ffree);
148100384Speter	CP(*in, *out, f_fsid);
149100384Speter	CP(*in, *out, f_owner);
150100384Speter	CP(*in, *out, f_type);
151100384Speter	CP(*in, *out, f_flags);
152100384Speter	CP(*in, *out, f_flags);
153100384Speter	CP(*in, *out, f_syncwrites);
154100384Speter	CP(*in, *out, f_asyncwrites);
155156266Sps	strlcpy(out->f_fstypename,
156156266Sps	      in->f_fstypename, MFSNAMELEN);
157156266Sps	strlcpy(out->f_mntonname,
158156266Sps	      in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
159100384Speter	CP(*in, *out, f_syncreads);
160100384Speter	CP(*in, *out, f_asyncreads);
161156266Sps	strlcpy(out->f_mntfromname,
162156266Sps	      in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
163100384Speter}
164128597Smarcel#endif
165100384Speter
166128597Smarcel#ifdef COMPAT_FREEBSD4
167100384Speterint
168128260Speterfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
169100384Speter{
170147178Spjd	struct statfs *buf, *sp;
171147178Spjd	struct statfs32 stat32;
172147178Spjd	size_t count, size;
173100384Speter	int error;
174100384Speter
175147178Spjd	count = uap->bufsize / sizeof(struct statfs32);
176147178Spjd	size = count * sizeof(struct statfs);
177147302Spjd	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
178147302Spjd	if (size > 0) {
179100384Speter		count = td->td_retval[0];
180147178Spjd		sp = buf;
181147178Spjd		while (count > 0 && error == 0) {
182147178Spjd			copy_statfs(sp, &stat32);
183147178Spjd			error = copyout(&stat32, uap->buf, sizeof(stat32));
184147178Spjd			sp++;
185147178Spjd			uap->buf++;
186147178Spjd			count--;
187100384Speter		}
188147178Spjd		free(buf, M_TEMP);
189100384Speter	}
190100384Speter	return (error);
191100384Speter}
192128597Smarcel#endif
193100384Speter
194100384Speterstruct sigaltstack32 {
195100384Speter	u_int32_t	ss_sp;
196100384Speter	u_int32_t	ss_size;
197100384Speter	int		ss_flags;
198100384Speter};
199100384Speter
200121719SpeterCTASSERT(sizeof(struct sigaltstack32) == 12);
201121719Speter
202100384Speterint
203119333Speterfreebsd32_sigaltstack(struct thread *td,
204119333Speter		      struct freebsd32_sigaltstack_args *uap)
205100384Speter{
206113859Sjhb	struct sigaltstack32 s32;
207113859Sjhb	struct sigaltstack ss, oss, *ssp;
208100384Speter	int error;
209100384Speter
210113859Sjhb	if (uap->ss != NULL) {
211113859Sjhb		error = copyin(uap->ss, &s32, sizeof(s32));
212100384Speter		if (error)
213100384Speter			return (error);
214113859Sjhb		PTRIN_CP(s32, ss, ss_sp);
215113859Sjhb		CP(s32, ss, ss_size);
216113859Sjhb		CP(s32, ss, ss_flags);
217113859Sjhb		ssp = &ss;
218113859Sjhb	} else
219113859Sjhb		ssp = NULL;
220113859Sjhb	error = kern_sigaltstack(td, ssp, &oss);
221113859Sjhb	if (error == 0 && uap->oss != NULL) {
222113859Sjhb		PTROUT_CP(oss, s32, ss_sp);
223113859Sjhb		CP(oss, s32, ss_size);
224113859Sjhb		CP(oss, s32, ss_flags);
225113859Sjhb		error = copyout(&s32, uap->oss, sizeof(s32));
226100384Speter	}
227100384Speter	return (error);
228100384Speter}
229100384Speter
230142059Sjhb/*
231142059Sjhb * Custom version of exec_copyin_args() so that we can translate
232142059Sjhb * the pointers.
233142059Sjhb */
234142059Sjhbstatic int
235142059Sjhbfreebsd32_exec_copyin_args(struct image_args *args, char *fname,
236142059Sjhb    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
237100384Speter{
238142059Sjhb	char *argp, *envp;
239142059Sjhb	u_int32_t *p32, arg;
240142059Sjhb	size_t length;
241100384Speter	int error;
242100384Speter
243142059Sjhb	bzero(args, sizeof(*args));
244142059Sjhb	if (argv == NULL)
245142059Sjhb		return (EFAULT);
246100384Speter
247142059Sjhb	/*
248142059Sjhb	 * Allocate temporary demand zeroed space for argument and
249142059Sjhb	 *	environment strings
250142059Sjhb	 */
251147588Sjhb	args->buf = (char *) kmem_alloc_wait(exec_map,
252147588Sjhb	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
253142059Sjhb	if (args->buf == NULL)
254142059Sjhb		return (ENOMEM);
255142059Sjhb	args->begin_argv = args->buf;
256142059Sjhb	args->endp = args->begin_argv;
257142059Sjhb	args->stringspace = ARG_MAX;
258142059Sjhb
259142059Sjhb	args->fname = args->buf + ARG_MAX;
260142059Sjhb
261142059Sjhb	/*
262142059Sjhb	 * Copy the file name.
263142059Sjhb	 */
264142059Sjhb	error = (segflg == UIO_SYSSPACE) ?
265142059Sjhb	    copystr(fname, args->fname, PATH_MAX, &length) :
266142059Sjhb	    copyinstr(fname, args->fname, PATH_MAX, &length);
267142059Sjhb	if (error != 0)
268156440Sups		goto err_exit;
269142059Sjhb
270142059Sjhb	/*
271142059Sjhb	 * extract arguments first
272142059Sjhb	 */
273142059Sjhb	p32 = argv;
274142059Sjhb	for (;;) {
275142059Sjhb		error = copyin(p32++, &arg, sizeof(arg));
276142059Sjhb		if (error)
277156440Sups			goto err_exit;
278142059Sjhb		if (arg == 0)
279142059Sjhb			break;
280142059Sjhb		argp = PTRIN(arg);
281142059Sjhb		error = copyinstr(argp, args->endp, args->stringspace, &length);
282142059Sjhb		if (error) {
283142059Sjhb			if (error == ENAMETOOLONG)
284156440Sups				error = E2BIG;
285156440Sups			goto err_exit;
286142059Sjhb		}
287142059Sjhb		args->stringspace -= length;
288142059Sjhb		args->endp += length;
289142059Sjhb		args->argc++;
290100384Speter	}
291142059Sjhb
292142059Sjhb	args->begin_envv = args->endp;
293142059Sjhb
294142059Sjhb	/*
295142059Sjhb	 * extract environment strings
296142059Sjhb	 */
297142059Sjhb	if (envv) {
298142059Sjhb		p32 = envv;
299142059Sjhb		for (;;) {
300100384Speter			error = copyin(p32++, &arg, sizeof(arg));
301100384Speter			if (error)
302156440Sups				goto err_exit;
303142059Sjhb			if (arg == 0)
304142059Sjhb				break;
305142059Sjhb			envp = PTRIN(arg);
306142059Sjhb			error = copyinstr(envp, args->endp, args->stringspace,
307142059Sjhb			    &length);
308142059Sjhb			if (error) {
309142059Sjhb				if (error == ENAMETOOLONG)
310156440Sups					error = E2BIG;
311156440Sups				goto err_exit;
312142059Sjhb			}
313142059Sjhb			args->stringspace -= length;
314142059Sjhb			args->endp += length;
315142059Sjhb			args->envc++;
316142059Sjhb		}
317100384Speter	}
318100384Speter
319142059Sjhb	return (0);
320156440Sups
321156440Supserr_exit:
322156440Sups	kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
323156440Sups	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
324156440Sups	args->buf = NULL;
325156440Sups	return (error);
326100384Speter}
327100384Speter
328142059Sjhbint
329142059Sjhbfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
330142059Sjhb{
331142059Sjhb	struct image_args eargs;
332142059Sjhb	int error;
333142059Sjhb
334142059Sjhb	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
335142059Sjhb	    uap->argv, uap->envv);
336142059Sjhb	if (error == 0)
337142059Sjhb		error = kern_execve(td, &eargs, NULL);
338142059Sjhb	return (error);
339142059Sjhb}
340142059Sjhb
341114987Speter#ifdef __ia64__
342100384Speterstatic int
343119333Speterfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
344119333Speter		       int prot, int fd, off_t pos)
345100384Speter{
346100384Speter	vm_map_t map;
347100384Speter	vm_map_entry_t entry;
348100384Speter	int rv;
349100384Speter
350100384Speter	map = &td->td_proc->p_vmspace->vm_map;
351100384Speter	if (fd != -1)
352100384Speter		prot |= VM_PROT_WRITE;
353100384Speter
354100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
355100384Speter		if ((entry->protection & prot) != prot) {
356100384Speter			rv = vm_map_protect(map,
357100384Speter					    trunc_page(start),
358100384Speter					    round_page(end),
359100384Speter					    entry->protection | prot,
360100384Speter					    FALSE);
361100384Speter			if (rv != KERN_SUCCESS)
362100384Speter				return (EINVAL);
363100384Speter		}
364100384Speter	} else {
365100384Speter		vm_offset_t addr = trunc_page(start);
366100384Speter		rv = vm_map_find(map, 0, 0,
367100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
368100384Speter				 VM_PROT_ALL, 0);
369100384Speter		if (rv != KERN_SUCCESS)
370100384Speter			return (EINVAL);
371100384Speter	}
372100384Speter
373100384Speter	if (fd != -1) {
374100384Speter		struct pread_args r;
375107849Salfred		r.fd = fd;
376107849Salfred		r.buf = (void *) start;
377107849Salfred		r.nbyte = end - start;
378107849Salfred		r.offset = pos;
379100384Speter		return (pread(td, &r));
380100384Speter	} else {
381100384Speter		while (start < end) {
382100384Speter			subyte((void *) start, 0);
383100384Speter			start++;
384100384Speter		}
385100384Speter		return (0);
386100384Speter	}
387100384Speter}
388114987Speter#endif
389100384Speter
390100384Speterint
391119333Speterfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
392100384Speter{
393100384Speter	struct mmap_args ap;
394107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
395107849Salfred	vm_size_t len	 = uap->len;
396107849Salfred	int prot	 = uap->prot;
397107849Salfred	int flags	 = uap->flags;
398107849Salfred	int fd		 = uap->fd;
399107849Salfred	off_t pos	 = (uap->poslo
400107849Salfred			    | ((off_t)uap->poshi << 32));
401114987Speter#ifdef __ia64__
402100384Speter	vm_size_t pageoff;
403100384Speter	int error;
404100384Speter
405100384Speter	/*
406100384Speter	 * Attempt to handle page size hassles.
407100384Speter	 */
408100384Speter	pageoff = (pos & PAGE_MASK);
409100384Speter	if (flags & MAP_FIXED) {
410100384Speter		vm_offset_t start, end;
411100384Speter		start = addr;
412100384Speter		end = addr + len;
413100384Speter
414147964Sjhb		mtx_lock(&Giant);
415100384Speter		if (start != trunc_page(start)) {
416119333Speter			error = freebsd32_mmap_partial(td, start,
417119333Speter						       round_page(start), prot,
418119333Speter						       fd, pos);
419100384Speter			if (fd != -1)
420100384Speter				pos += round_page(start) - start;
421100384Speter			start = round_page(start);
422100384Speter		}
423100384Speter		if (end != round_page(end)) {
424100384Speter			vm_offset_t t = trunc_page(end);
425119333Speter			error = freebsd32_mmap_partial(td, t, end,
426100384Speter						  prot, fd,
427100384Speter						  pos + t - start);
428100384Speter			end = trunc_page(end);
429100384Speter		}
430100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
431100384Speter			/*
432100384Speter			 * We can't map this region at all. The specified
433100384Speter			 * address doesn't have the same alignment as the file
434100384Speter			 * position. Fake the mapping by simply reading the
435100384Speter			 * entire region into memory. First we need to make
436100384Speter			 * sure the region exists.
437100384Speter			 */
438100384Speter			vm_map_t map;
439100384Speter			struct pread_args r;
440100384Speter			int rv;
441100384Speter
442100384Speter			prot |= VM_PROT_WRITE;
443100384Speter			map = &td->td_proc->p_vmspace->vm_map;
444100384Speter			rv = vm_map_remove(map, start, end);
445147964Sjhb			if (rv != KERN_SUCCESS) {
446147964Sjhb				mtx_unlock(&Giant);
447100384Speter				return (EINVAL);
448147964Sjhb			}
449100384Speter			rv = vm_map_find(map, 0, 0,
450100384Speter					 &start, end - start, FALSE,
451100384Speter					 prot, VM_PROT_ALL, 0);
452147964Sjhb			mtx_unlock(&Giant);
453100384Speter			if (rv != KERN_SUCCESS)
454100384Speter				return (EINVAL);
455107849Salfred			r.fd = fd;
456107849Salfred			r.buf = (void *) start;
457107849Salfred			r.nbyte = end - start;
458107849Salfred			r.offset = pos;
459100384Speter			error = pread(td, &r);
460100384Speter			if (error)
461100384Speter				return (error);
462100384Speter
463100384Speter			td->td_retval[0] = addr;
464100384Speter			return (0);
465100384Speter		}
466147964Sjhb		mtx_unlock(&Giant);
467100384Speter		if (end == start) {
468100384Speter			/*
469100384Speter			 * After dealing with the ragged ends, there
470100384Speter			 * might be none left.
471100384Speter			 */
472100384Speter			td->td_retval[0] = addr;
473100384Speter			return (0);
474100384Speter		}
475100384Speter		addr = start;
476100384Speter		len = end - start;
477100384Speter	}
478114987Speter#endif
479100384Speter
480107849Salfred	ap.addr = (void *) addr;
481107849Salfred	ap.len = len;
482107849Salfred	ap.prot = prot;
483107849Salfred	ap.flags = flags;
484107849Salfred	ap.fd = fd;
485107849Salfred	ap.pos = pos;
486100384Speter
487100384Speter	return (mmap(td, &ap));
488100384Speter}
489100384Speter
490100384Speterstruct itimerval32 {
491100384Speter	struct timeval32 it_interval;
492100384Speter	struct timeval32 it_value;
493100384Speter};
494100384Speter
495121719SpeterCTASSERT(sizeof(struct itimerval32) == 16);
496121719Speter
497100384Speterint
498119333Speterfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
499100384Speter{
500142059Sjhb	struct itimerval itv, oitv, *itvp;
501142059Sjhb	struct itimerval32 i32;
502100384Speter	int error;
503100384Speter
504142059Sjhb	if (uap->itv != NULL) {
505142059Sjhb		error = copyin(uap->itv, &i32, sizeof(i32));
506100384Speter		if (error)
507100384Speter			return (error);
508142059Sjhb		TV_CP(i32, itv, it_interval);
509142059Sjhb		TV_CP(i32, itv, it_value);
510142059Sjhb		itvp = &itv;
511142059Sjhb	} else
512142059Sjhb		itvp = NULL;
513142059Sjhb	error = kern_setitimer(td, uap->which, itvp, &oitv);
514142059Sjhb	if (error || uap->oitv == NULL)
515100384Speter		return (error);
516142059Sjhb	TV_CP(oitv, i32, it_interval);
517142059Sjhb	TV_CP(oitv, i32, it_value);
518142059Sjhb	return (copyout(&i32, uap->oitv, sizeof(i32)));
519100384Speter}
520100384Speter
521100384Speterint
522125171Speterfreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
523125171Speter{
524142059Sjhb	struct itimerval itv;
525142059Sjhb	struct itimerval32 i32;
526125171Speter	int error;
527125171Speter
528142059Sjhb	error = kern_getitimer(td, uap->which, &itv);
529142059Sjhb	if (error || uap->itv == NULL)
530125171Speter		return (error);
531142059Sjhb	TV_CP(itv, i32, it_interval);
532142059Sjhb	TV_CP(itv, i32, it_value);
533142059Sjhb	return (copyout(&i32, uap->itv, sizeof(i32)));
534125171Speter}
535125171Speter
536125171Speterint
537119333Speterfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
538100384Speter{
539142059Sjhb	struct timeval32 tv32;
540142059Sjhb	struct timeval tv, *tvp;
541100384Speter	int error;
542100384Speter
543142059Sjhb	if (uap->tv != NULL) {
544142059Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
545100384Speter		if (error)
546100384Speter			return (error);
547142059Sjhb		CP(tv32, tv, tv_sec);
548142059Sjhb		CP(tv32, tv, tv_usec);
549142059Sjhb		tvp = &tv;
550142059Sjhb	} else
551142059Sjhb		tvp = NULL;
552100384Speter	/*
553100384Speter	 * XXX big-endian needs to convert the fd_sets too.
554142059Sjhb	 * XXX Do pointers need PTRIN()?
555100384Speter	 */
556142059Sjhb	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
557100384Speter}
558100384Speter
559114987Speterstruct kevent32 {
560114987Speter	u_int32_t	ident;		/* identifier for this event */
561114987Speter	short		filter;		/* filter for event */
562114987Speter	u_short		flags;
563114987Speter	u_int		fflags;
564114987Speter	int32_t		data;
565114987Speter	u_int32_t	udata;		/* opaque user data identifier */
566114987Speter};
567114987Speter
568121719SpeterCTASSERT(sizeof(struct kevent32) == 20);
569146950Spsstatic int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
570146950Spsstatic int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
571121719Speter
572146950Sps/*
573146950Sps * Copy 'count' items into the destination list pointed to by uap->eventlist.
574146950Sps */
575146950Spsstatic int
576146950Spsfreebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
577146950Sps{
578146950Sps	struct freebsd32_kevent_args *uap;
579146950Sps	struct kevent32	ks32[KQ_NEVENTS];
580146950Sps	int i, error = 0;
581146950Sps
582146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
583146950Sps	uap = (struct freebsd32_kevent_args *)arg;
584146950Sps
585146950Sps	for (i = 0; i < count; i++) {
586146950Sps		CP(kevp[i], ks32[i], ident);
587146950Sps		CP(kevp[i], ks32[i], filter);
588146950Sps		CP(kevp[i], ks32[i], flags);
589146950Sps		CP(kevp[i], ks32[i], fflags);
590146950Sps		CP(kevp[i], ks32[i], data);
591146950Sps		PTROUT_CP(kevp[i], ks32[i], udata);
592146950Sps	}
593146950Sps	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
594146950Sps	if (error == 0)
595146950Sps		uap->eventlist += count;
596146950Sps	return (error);
597146950Sps}
598146950Sps
599146950Sps/*
600146950Sps * Copy 'count' items from the list pointed to by uap->changelist.
601146950Sps */
602146950Spsstatic int
603146950Spsfreebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
604146950Sps{
605146950Sps	struct freebsd32_kevent_args *uap;
606146950Sps	struct kevent32	ks32[KQ_NEVENTS];
607146950Sps	int i, error = 0;
608146950Sps
609146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
610146950Sps	uap = (struct freebsd32_kevent_args *)arg;
611146950Sps
612146950Sps	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
613146950Sps	if (error)
614146950Sps		goto done;
615146950Sps	uap->changelist += count;
616146950Sps
617146950Sps	for (i = 0; i < count; i++) {
618146950Sps		CP(ks32[i], kevp[i], ident);
619146950Sps		CP(ks32[i], kevp[i], filter);
620146950Sps		CP(ks32[i], kevp[i], flags);
621146950Sps		CP(ks32[i], kevp[i], fflags);
622146950Sps		CP(ks32[i], kevp[i], data);
623146950Sps		PTRIN_CP(ks32[i], kevp[i], udata);
624146950Sps	}
625146950Spsdone:
626146950Sps	return (error);
627146950Sps}
628146950Sps
629100384Speterint
630119333Speterfreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
631114987Speter{
632114987Speter	struct timespec32 ts32;
633142934Sps	struct timespec ts, *tsp;
634146950Sps	struct kevent_copyops k_ops = { uap,
635146950Sps					freebsd32_kevent_copyout,
636146950Sps					freebsd32_kevent_copyin};
637146950Sps	int error;
638114987Speter
639114987Speter
640114987Speter	if (uap->timeout) {
641114987Speter		error = copyin(uap->timeout, &ts32, sizeof(ts32));
642114987Speter		if (error)
643114987Speter			return (error);
644114987Speter		CP(ts32, ts, tv_sec);
645114987Speter		CP(ts32, ts, tv_nsec);
646142934Sps		tsp = &ts;
647142934Sps	} else
648142934Sps		tsp = NULL;
649146950Sps	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
650146950Sps	    &k_ops, tsp);
651142934Sps	return (error);
652114987Speter}
653114987Speter
654114987Speterint
655119333Speterfreebsd32_gettimeofday(struct thread *td,
656119333Speter		       struct freebsd32_gettimeofday_args *uap)
657100384Speter{
658123425Speter	struct timeval atv;
659123425Speter	struct timeval32 atv32;
660123425Speter	struct timezone rtz;
661123425Speter	int error = 0;
662100384Speter
663123425Speter	if (uap->tp) {
664123425Speter		microtime(&atv);
665123425Speter		CP(atv, atv32, tv_sec);
666123425Speter		CP(atv, atv32, tv_usec);
667123425Speter		error = copyout(&atv32, uap->tp, sizeof (atv32));
668100384Speter	}
669123425Speter	if (error == 0 && uap->tzp != NULL) {
670123425Speter		rtz.tz_minuteswest = tz_minuteswest;
671123425Speter		rtz.tz_dsttime = tz_dsttime;
672123425Speter		error = copyout(&rtz, uap->tzp, sizeof (rtz));
673100384Speter	}
674100384Speter	return (error);
675100384Speter}
676100384Speter
677100384Speterint
678119333Speterfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
679100384Speter{
680136152Sjhb	struct rusage32 s32;
681136152Sjhb	struct rusage s;
682100384Speter	int error;
683100384Speter
684136152Sjhb	error = kern_getrusage(td, uap->who, &s);
685100384Speter	if (error)
686100384Speter		return (error);
687136152Sjhb	if (uap->rusage != NULL) {
688100384Speter		TV_CP(s, s32, ru_utime);
689100384Speter		TV_CP(s, s32, ru_stime);
690100384Speter		CP(s, s32, ru_maxrss);
691100384Speter		CP(s, s32, ru_ixrss);
692100384Speter		CP(s, s32, ru_idrss);
693100384Speter		CP(s, s32, ru_isrss);
694100384Speter		CP(s, s32, ru_minflt);
695100384Speter		CP(s, s32, ru_majflt);
696100384Speter		CP(s, s32, ru_nswap);
697100384Speter		CP(s, s32, ru_inblock);
698100384Speter		CP(s, s32, ru_oublock);
699100384Speter		CP(s, s32, ru_msgsnd);
700100384Speter		CP(s, s32, ru_msgrcv);
701100384Speter		CP(s, s32, ru_nsignals);
702100384Speter		CP(s, s32, ru_nvcsw);
703100384Speter		CP(s, s32, ru_nivcsw);
704136152Sjhb		error = copyout(&s32, uap->rusage, sizeof(s32));
705100384Speter	}
706100384Speter	return (error);
707100384Speter}
708100384Speter
709100384Speterstruct iovec32 {
710100384Speter	u_int32_t iov_base;
711100384Speter	int	iov_len;
712100384Speter};
713100384Speter
714121719SpeterCTASSERT(sizeof(struct iovec32) == 8);
715121719Speter
716144450Sjhbstatic int
717144450Sjhbfreebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
718100384Speter{
719144450Sjhb	struct iovec32 iov32;
720144450Sjhb	struct iovec *iov;
721144450Sjhb	struct uio *uio;
722144450Sjhb	u_int iovlen;
723144450Sjhb	int error, i;
724100384Speter
725144450Sjhb	*uiop = NULL;
726144450Sjhb	if (iovcnt > UIO_MAXIOV)
727100384Speter		return (EINVAL);
728144450Sjhb	iovlen = iovcnt * sizeof(struct iovec);
729144450Sjhb	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
730144450Sjhb	iov = (struct iovec *)(uio + 1);
731144450Sjhb	for (i = 0; i < iovcnt; i++) {
732144450Sjhb		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
733144450Sjhb		if (error) {
734144450Sjhb			free(uio, M_IOV);
735144450Sjhb			return (error);
736144450Sjhb		}
737144450Sjhb		iov[i].iov_base = PTRIN(iov32.iov_base);
738144450Sjhb		iov[i].iov_len = iov32.iov_len;
739100384Speter	}
740144450Sjhb	uio->uio_iov = iov;
741144450Sjhb	uio->uio_iovcnt = iovcnt;
742144450Sjhb	uio->uio_segflg = UIO_USERSPACE;
743144450Sjhb	uio->uio_offset = -1;
744144450Sjhb	uio->uio_resid = 0;
745144450Sjhb	for (i = 0; i < iovcnt; i++) {
746144450Sjhb		if (iov->iov_len > INT_MAX - uio->uio_resid) {
747144450Sjhb			free(uio, M_IOV);
748144450Sjhb			return (EINVAL);
749144450Sjhb		}
750144450Sjhb		uio->uio_resid += iov->iov_len;
751144450Sjhb		iov++;
752144450Sjhb	}
753144450Sjhb	*uiop = uio;
754144450Sjhb	return (0);
755144450Sjhb}
756100384Speter
757144450Sjhbint
758144450Sjhbfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
759144450Sjhb{
760144450Sjhb	struct uio *auio;
761144450Sjhb	int error;
762100384Speter
763144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
764144450Sjhb	if (error)
765144450Sjhb		return (error);
766144450Sjhb	error = kern_readv(td, uap->fd, auio);
767144450Sjhb	free(auio, M_IOV);
768100384Speter	return (error);
769100384Speter}
770100384Speter
771100384Speterint
772119333Speterfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
773100384Speter{
774144450Sjhb	struct uio *auio;
775144450Sjhb	int error;
776100384Speter
777144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
778144450Sjhb	if (error)
779144450Sjhb		return (error);
780144450Sjhb	error = kern_writev(td, uap->fd, auio);
781144450Sjhb	free(auio, M_IOV);
782100384Speter	return (error);
783100384Speter}
784100384Speter
785100384Speterint
786147813Sjhbfreebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
787147813Sjhb{
788147813Sjhb	struct uio *auio;
789147813Sjhb	int error;
790147813Sjhb
791147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
792147813Sjhb	if (error)
793147813Sjhb		return (error);
794147813Sjhb	error = kern_preadv(td, uap->fd, auio, uap->offset);
795147813Sjhb	free(auio, M_IOV);
796147813Sjhb	return (error);
797147813Sjhb}
798147813Sjhb
799147813Sjhbint
800147813Sjhbfreebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
801147813Sjhb{
802147813Sjhb	struct uio *auio;
803147813Sjhb	int error;
804147813Sjhb
805147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
806147813Sjhb	if (error)
807147813Sjhb		return (error);
808147813Sjhb	error = kern_pwritev(td, uap->fd, auio, uap->offset);
809147813Sjhb	free(auio, M_IOV);
810147813Sjhb	return (error);
811147813Sjhb}
812147813Sjhb
813151359Spsstatic int
814151909Spsfreebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
815151359Sps    int error)
816151359Sps{
817151359Sps	struct iovec32 iov32;
818151909Sps	struct iovec *iov;
819151909Sps	u_int iovlen;
820151359Sps	int i;
821151359Sps
822151909Sps	*iovp = NULL;
823151359Sps	if (iovcnt > UIO_MAXIOV)
824151359Sps		return (error);
825151359Sps	iovlen = iovcnt * sizeof(struct iovec);
826151909Sps	iov = malloc(iovlen, M_IOV, M_WAITOK);
827151359Sps	for (i = 0; i < iovcnt; i++) {
828151909Sps		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
829151359Sps		if (error) {
830151909Sps			free(iov, M_IOV);
831151359Sps			return (error);
832151359Sps		}
833151909Sps		iov[i].iov_base = PTRIN(iov32.iov_base);
834151909Sps		iov[i].iov_len = iov32.iov_len;
835151359Sps	}
836151909Sps	*iovp = iov;
837151359Sps	return (0);
838151359Sps}
839151359Sps
840151359Spsstruct msghdr32 {
841151359Sps	u_int32_t	 msg_name;
842151359Sps	socklen_t	 msg_namelen;
843151359Sps	u_int32_t	 msg_iov;
844151359Sps	int		 msg_iovlen;
845151359Sps	u_int32_t	 msg_control;
846151359Sps	socklen_t	 msg_controllen;
847151359Sps	int		 msg_flags;
848151359Sps};
849151359SpsCTASSERT(sizeof(struct msghdr32) == 28);
850151359Sps
851151359Spsstatic int
852151359Spsfreebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
853151359Sps{
854151359Sps	struct msghdr32 m32;
855151359Sps	int error;
856151359Sps
857151359Sps	error = copyin(msg32, &m32, sizeof(m32));
858151359Sps	if (error)
859151359Sps		return (error);
860151359Sps	msg->msg_name = PTRIN(m32.msg_name);
861151359Sps	msg->msg_namelen = m32.msg_namelen;
862151359Sps	msg->msg_iov = PTRIN(m32.msg_iov);
863151359Sps	msg->msg_iovlen = m32.msg_iovlen;
864151359Sps	msg->msg_control = PTRIN(m32.msg_control);
865151359Sps	msg->msg_controllen = m32.msg_controllen;
866151359Sps	msg->msg_flags = m32.msg_flags;
867151909Sps	return (0);
868151359Sps}
869151359Sps
870151359Spsstatic int
871151359Spsfreebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
872151359Sps{
873151359Sps	struct msghdr32 m32;
874151359Sps	int error;
875151359Sps
876151359Sps	m32.msg_name = PTROUT(msg->msg_name);
877151359Sps	m32.msg_namelen = msg->msg_namelen;
878151359Sps	m32.msg_iov = PTROUT(msg->msg_iov);
879151359Sps	m32.msg_iovlen = msg->msg_iovlen;
880151359Sps	m32.msg_control = PTROUT(msg->msg_control);
881151359Sps	m32.msg_controllen = msg->msg_controllen;
882151359Sps	m32.msg_flags = msg->msg_flags;
883151359Sps	error = copyout(&m32, msg32, sizeof(m32));
884151359Sps	return (error);
885151359Sps}
886151359Sps
887151909Sps#define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
888151909Sps#define FREEBSD32_ALIGN(p)	\
889151909Sps	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
890151909Sps#define	FREEBSD32_CMSG_SPACE(l)	\
891151909Sps	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
892151909Sps
893151909Sps#define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
894151909Sps				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
895151909Spsstatic int
896151909Spsfreebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
897151909Sps{
898151909Sps	struct cmsghdr *cm;
899151909Sps	void *data;
900151909Sps	socklen_t clen, datalen;
901151909Sps	int error;
902151909Sps	caddr_t ctlbuf;
903151909Sps	int len, maxlen, copylen;
904151909Sps	struct mbuf *m;
905151909Sps	error = 0;
906151909Sps
907151909Sps	len    = msg->msg_controllen;
908151909Sps	maxlen = msg->msg_controllen;
909151909Sps	msg->msg_controllen = 0;
910151909Sps
911151909Sps	m = control;
912151909Sps	ctlbuf = msg->msg_control;
913151909Sps
914151909Sps	while (m && len > 0) {
915151909Sps		cm = mtod(m, struct cmsghdr *);
916151909Sps		clen = m->m_len;
917151909Sps
918151909Sps		while (cm != NULL) {
919151909Sps
920151909Sps			if (sizeof(struct cmsghdr) > clen ||
921151909Sps			    cm->cmsg_len > clen) {
922151909Sps				error = EINVAL;
923151909Sps				break;
924151909Sps			}
925151909Sps
926151909Sps			data   = CMSG_DATA(cm);
927151909Sps			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
928151909Sps
929151909Sps			/* Adjust message length */
930151909Sps			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
931151909Sps			    datalen;
932151909Sps
933151909Sps
934151909Sps			/* Copy cmsghdr */
935151909Sps			copylen = sizeof(struct cmsghdr);
936151909Sps			if (len < copylen) {
937151909Sps				msg->msg_flags |= MSG_CTRUNC;
938151909Sps				copylen = len;
939151909Sps			}
940151909Sps
941151909Sps			error = copyout(cm,ctlbuf,copylen);
942151909Sps			if (error)
943151909Sps				goto exit;
944151909Sps
945151909Sps			ctlbuf += FREEBSD32_ALIGN(copylen);
946151909Sps			len    -= FREEBSD32_ALIGN(copylen);
947151909Sps
948151909Sps			if (len <= 0)
949151909Sps				break;
950151909Sps
951151909Sps			/* Copy data */
952151909Sps			copylen = datalen;
953151909Sps			if (len < copylen) {
954151909Sps				msg->msg_flags |= MSG_CTRUNC;
955151909Sps				copylen = len;
956151909Sps			}
957151909Sps
958151909Sps			error = copyout(data,ctlbuf,copylen);
959151909Sps			if (error)
960151909Sps				goto exit;
961151909Sps
962151909Sps			ctlbuf += FREEBSD32_ALIGN(copylen);
963151909Sps			len    -= FREEBSD32_ALIGN(copylen);
964151909Sps
965151909Sps			if (CMSG_SPACE(datalen) < clen) {
966151909Sps				clen -= CMSG_SPACE(datalen);
967151909Sps				cm = (struct cmsghdr *)
968151909Sps					((caddr_t)cm + CMSG_SPACE(datalen));
969151909Sps			} else {
970151909Sps				clen = 0;
971151909Sps				cm = NULL;
972151909Sps			}
973151909Sps		}
974151909Sps		m = m->m_next;
975151909Sps	}
976151909Sps
977151909Sps	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
978151909Sps
979151909Spsexit:
980151909Sps	return (error);
981151909Sps
982151909Sps}
983151909Sps
984147813Sjhbint
985151359Spsfreebsd32_recvmsg(td, uap)
986151359Sps	struct thread *td;
987151359Sps	struct freebsd32_recvmsg_args /* {
988151359Sps		int	s;
989151359Sps		struct	msghdr32 *msg;
990151359Sps		int	flags;
991151359Sps	} */ *uap;
992151359Sps{
993151359Sps	struct msghdr msg;
994151359Sps	struct msghdr32 m32;
995151359Sps	struct iovec *uiov, *iov;
996151909Sps	struct mbuf *control = NULL;
997151909Sps	struct mbuf **controlp;
998151909Sps
999151359Sps	int error;
1000151359Sps	error = copyin(uap->msg, &m32, sizeof(m32));
1001151359Sps	if (error)
1002151359Sps		return (error);
1003151359Sps	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1004151359Sps	if (error)
1005151359Sps		return (error);
1006160246Sjhb	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1007160246Sjhb	    EMSGSIZE);
1008151359Sps	if (error)
1009151359Sps		return (error);
1010151359Sps	msg.msg_flags = uap->flags;
1011151359Sps	uiov = msg.msg_iov;
1012151359Sps	msg.msg_iov = iov;
1013151909Sps
1014151909Sps	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1015160249Sjhb	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
1016151359Sps	if (error == 0) {
1017151359Sps		msg.msg_iov = uiov;
1018151909Sps
1019151909Sps		if (control != NULL)
1020151909Sps			error = freebsd32_copy_msg_out(&msg, control);
1021151909Sps
1022151909Sps		if (error == 0)
1023151909Sps			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1024151359Sps	}
1025151359Sps	free(iov, M_IOV);
1026151909Sps
1027151909Sps	if (control != NULL)
1028151909Sps		m_freem(control);
1029151909Sps
1030151359Sps	return (error);
1031151359Sps}
1032151359Sps
1033151909Sps
1034151909Spsstatic int
1035151909Spsfreebsd32_convert_msg_in(struct mbuf **controlp)
1036151909Sps{
1037151909Sps	struct mbuf *control = *controlp;
1038151909Sps	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1039151909Sps	void *data;
1040151909Sps	socklen_t clen = control->m_len, datalen;
1041151909Sps	int error;
1042151909Sps
1043151909Sps	error = 0;
1044151909Sps	*controlp = NULL;
1045151909Sps
1046151909Sps	while (cm != NULL) {
1047151909Sps		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1048151909Sps			error = EINVAL;
1049151909Sps			break;
1050151909Sps		}
1051151909Sps
1052151909Sps		data = FREEBSD32_CMSG_DATA(cm);
1053151909Sps		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1054151909Sps
1055151909Sps		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1056151909Sps		    cm->cmsg_level);
1057151909Sps		controlp = &(*controlp)->m_next;
1058151909Sps
1059151909Sps		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1060151909Sps			clen -= FREEBSD32_CMSG_SPACE(datalen);
1061151909Sps			cm = (struct cmsghdr *)
1062151909Sps				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1063151909Sps		} else {
1064151909Sps			clen = 0;
1065151909Sps			cm = NULL;
1066151909Sps		}
1067151909Sps	}
1068151909Sps
1069151909Sps	m_freem(control);
1070151909Sps	return (error);
1071151909Sps}
1072151909Sps
1073151909Sps
1074151359Spsint
1075151359Spsfreebsd32_sendmsg(struct thread *td,
1076151359Sps		  struct freebsd32_sendmsg_args *uap)
1077151359Sps{
1078151359Sps	struct msghdr msg;
1079151359Sps	struct msghdr32 m32;
1080151359Sps	struct iovec *iov;
1081151909Sps	struct mbuf *control = NULL;
1082151909Sps	struct sockaddr *to = NULL;
1083151359Sps	int error;
1084151359Sps
1085151359Sps	error = copyin(uap->msg, &m32, sizeof(m32));
1086151359Sps	if (error)
1087151359Sps		return (error);
1088151359Sps	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1089151359Sps	if (error)
1090151359Sps		return (error);
1091160246Sjhb	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1092160246Sjhb	    EMSGSIZE);
1093151359Sps	if (error)
1094151359Sps		return (error);
1095151359Sps	msg.msg_iov = iov;
1096151909Sps	if (msg.msg_name != NULL) {
1097151909Sps		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1098151909Sps		if (error) {
1099151909Sps			to = NULL;
1100151909Sps			goto out;
1101151909Sps		}
1102151909Sps		msg.msg_name = to;
1103151909Sps	}
1104151909Sps
1105151909Sps	if (msg.msg_control) {
1106151909Sps		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1107151909Sps			error = EINVAL;
1108151909Sps			goto out;
1109151909Sps		}
1110151909Sps
1111151909Sps		error = sockargs(&control, msg.msg_control,
1112151909Sps		    msg.msg_controllen, MT_CONTROL);
1113151909Sps		if (error)
1114151909Sps			goto out;
1115151909Sps
1116151909Sps		error = freebsd32_convert_msg_in(&control);
1117151909Sps		if (error)
1118151909Sps			goto out;
1119151909Sps	}
1120151909Sps
1121151909Sps	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1122151909Sps	    UIO_USERSPACE);
1123151909Sps
1124151909Spsout:
1125151359Sps	free(iov, M_IOV);
1126151909Sps	if (to)
1127151909Sps		free(to, M_SONAME);
1128151359Sps	return (error);
1129151359Sps}
1130151359Sps
1131151359Spsint
1132151359Spsfreebsd32_recvfrom(struct thread *td,
1133151359Sps		   struct freebsd32_recvfrom_args *uap)
1134151359Sps{
1135151359Sps	struct msghdr msg;
1136151359Sps	struct iovec aiov;
1137151359Sps	int error;
1138151359Sps
1139151359Sps	if (uap->fromlenaddr) {
1140160246Sjhb		error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
1141160246Sjhb		    sizeof(msg.msg_namelen));
1142151359Sps		if (error)
1143151359Sps			return (error);
1144151359Sps	} else {
1145151359Sps		msg.msg_namelen = 0;
1146151359Sps	}
1147151359Sps
1148160246Sjhb	msg.msg_name = PTRIN(uap->from);
1149151359Sps	msg.msg_iov = &aiov;
1150151359Sps	msg.msg_iovlen = 1;
1151160246Sjhb	aiov.iov_base = PTRIN(uap->buf);
1152151359Sps	aiov.iov_len = uap->len;
1153160246Sjhb	msg.msg_control = NULL;
1154151359Sps	msg.msg_flags = uap->flags;
1155160249Sjhb	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
1156160249Sjhb	if (error == 0 && uap->fromlenaddr)
1157160249Sjhb		error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
1158160249Sjhb		    sizeof (msg.msg_namelen));
1159151359Sps	return (error);
1160151359Sps}
1161151359Sps
1162151359Spsint
1163119333Speterfreebsd32_settimeofday(struct thread *td,
1164119333Speter		       struct freebsd32_settimeofday_args *uap)
1165100384Speter{
1166144450Sjhb	struct timeval32 tv32;
1167144450Sjhb	struct timeval tv, *tvp;
1168144450Sjhb	struct timezone tz, *tzp;
1169100384Speter	int error;
1170100384Speter
1171144450Sjhb	if (uap->tv) {
1172144450Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
1173100384Speter		if (error)
1174100384Speter			return (error);
1175144450Sjhb		CP(tv32, tv, tv_sec);
1176144450Sjhb		CP(tv32, tv, tv_usec);
1177144450Sjhb		tvp = &tv;
1178144450Sjhb	} else
1179144450Sjhb		tvp = NULL;
1180144450Sjhb	if (uap->tzp) {
1181144450Sjhb		error = copyin(uap->tzp, &tz, sizeof(tz));
1182100384Speter		if (error)
1183100384Speter			return (error);
1184144450Sjhb		tzp = &tz;
1185144450Sjhb	} else
1186144450Sjhb		tzp = NULL;
1187144450Sjhb	return (kern_settimeofday(td, tvp, tzp));
1188100384Speter}
1189100384Speter
1190100384Speterint
1191119333Speterfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1192100384Speter{
1193142059Sjhb	struct timeval32 s32[2];
1194142059Sjhb	struct timeval s[2], *sp;
1195100384Speter	int error;
1196100384Speter
1197142059Sjhb	if (uap->tptr != NULL) {
1198142059Sjhb		error = copyin(uap->tptr, s32, sizeof(s32));
1199100384Speter		if (error)
1200100384Speter			return (error);
1201100384Speter		CP(s32[0], s[0], tv_sec);
1202100384Speter		CP(s32[0], s[0], tv_usec);
1203100384Speter		CP(s32[1], s[1], tv_sec);
1204100384Speter		CP(s32[1], s[1], tv_usec);
1205142059Sjhb		sp = s;
1206142059Sjhb	} else
1207142059Sjhb		sp = NULL;
1208142059Sjhb	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1209100384Speter}
1210100384Speter
1211100384Speterint
1212154586Sambriskofreebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
1213154586Sambrisko{
1214154586Sambrisko	struct timeval32 s32[2];
1215154586Sambrisko	struct timeval s[2], *sp;
1216154586Sambrisko	int error;
1217154586Sambrisko
1218154586Sambrisko	if (uap->tptr != NULL) {
1219154586Sambrisko		error = copyin(uap->tptr, s32, sizeof(s32));
1220154586Sambrisko		if (error)
1221154586Sambrisko			return (error);
1222154586Sambrisko		CP(s32[0], s[0], tv_sec);
1223154586Sambrisko		CP(s32[0], s[0], tv_usec);
1224154586Sambrisko		CP(s32[1], s[1], tv_sec);
1225154586Sambrisko		CP(s32[1], s[1], tv_usec);
1226154586Sambrisko		sp = s;
1227154586Sambrisko	} else
1228154586Sambrisko		sp = NULL;
1229154586Sambrisko	return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1230154586Sambrisko}
1231154586Sambrisko
1232154586Sambriskoint
1233153247Sambriskofreebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1234153247Sambrisko{
1235153247Sambrisko	struct timeval32 s32[2];
1236153247Sambrisko	struct timeval s[2], *sp;
1237153247Sambrisko	int error;
1238153247Sambrisko
1239153247Sambrisko	if (uap->tptr != NULL) {
1240153247Sambrisko		error = copyin(uap->tptr, s32, sizeof(s32));
1241153247Sambrisko		if (error)
1242153247Sambrisko			return (error);
1243153247Sambrisko		CP(s32[0], s[0], tv_sec);
1244153247Sambrisko		CP(s32[0], s[0], tv_usec);
1245153247Sambrisko		CP(s32[1], s[1], tv_sec);
1246153247Sambrisko		CP(s32[1], s[1], tv_usec);
1247153247Sambrisko		sp = s;
1248153247Sambrisko	} else
1249153247Sambrisko		sp = NULL;
1250153247Sambrisko	return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1251153247Sambrisko}
1252153247Sambrisko
1253153247Sambrisko
1254153247Sambriskoint
1255119333Speterfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1256100384Speter{
1257144450Sjhb	struct timeval32 tv32;
1258144450Sjhb	struct timeval delta, olddelta, *deltap;
1259100384Speter	int error;
1260100384Speter
1261144450Sjhb	if (uap->delta) {
1262144450Sjhb		error = copyin(uap->delta, &tv32, sizeof(tv32));
1263100384Speter		if (error)
1264100384Speter			return (error);
1265144450Sjhb		CP(tv32, delta, tv_sec);
1266144450Sjhb		CP(tv32, delta, tv_usec);
1267144450Sjhb		deltap = &delta;
1268144450Sjhb	} else
1269144450Sjhb		deltap = NULL;
1270144450Sjhb	error = kern_adjtime(td, deltap, &olddelta);
1271144450Sjhb	if (uap->olddelta && error == 0) {
1272144450Sjhb		CP(olddelta, tv32, tv_sec);
1273144450Sjhb		CP(olddelta, tv32, tv_usec);
1274144450Sjhb		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1275100384Speter	}
1276100384Speter	return (error);
1277100384Speter}
1278100384Speter
1279128597Smarcel#ifdef COMPAT_FREEBSD4
1280100384Speterint
1281128260Speterfreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1282100384Speter{
1283142059Sjhb	struct statfs32 s32;
1284142059Sjhb	struct statfs s;
1285100384Speter	int error;
1286100384Speter
1287142059Sjhb	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1288100384Speter	if (error)
1289100384Speter		return (error);
1290142059Sjhb	copy_statfs(&s, &s32);
1291142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1292100384Speter}
1293128597Smarcel#endif
1294100384Speter
1295128597Smarcel#ifdef COMPAT_FREEBSD4
1296100384Speterint
1297128260Speterfreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1298100384Speter{
1299142059Sjhb	struct statfs32 s32;
1300142059Sjhb	struct statfs s;
1301100384Speter	int error;
1302100384Speter
1303142059Sjhb	error = kern_fstatfs(td, uap->fd, &s);
1304100384Speter	if (error)
1305100384Speter		return (error);
1306142059Sjhb	copy_statfs(&s, &s32);
1307142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1308100384Speter}
1309128597Smarcel#endif
1310100384Speter
1311128597Smarcel#ifdef COMPAT_FREEBSD4
1312100384Speterint
1313128260Speterfreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1314128260Speter{
1315142059Sjhb	struct statfs32 s32;
1316142059Sjhb	struct statfs s;
1317142059Sjhb	fhandle_t fh;
1318128260Speter	int error;
1319128260Speter
1320142059Sjhb	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1321142059Sjhb		return (error);
1322142059Sjhb	error = kern_fhstatfs(td, fh, &s);
1323128260Speter	if (error)
1324128260Speter		return (error);
1325142059Sjhb	copy_statfs(&s, &s32);
1326142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1327128260Speter}
1328128597Smarcel#endif
1329128260Speter
1330128260Speterint
1331119333Speterfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1332100384Speter{
1333100384Speter	/*
1334100384Speter	 * Vector through to semsys if it is loaded.
1335100384Speter	 */
1336150883Sjhb	return sysent[SYS_semsys].sy_call(td, uap);
1337100384Speter}
1338100384Speter
1339100384Speterint
1340119333Speterfreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1341100384Speter{
1342100384Speter	/*
1343100384Speter	 * Vector through to msgsys if it is loaded.
1344100384Speter	 */
1345150883Sjhb	return sysent[SYS_msgsys].sy_call(td, uap);
1346100384Speter}
1347100384Speter
1348100384Speterint
1349119333Speterfreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1350100384Speter{
1351157285Sps
1352157285Sps	switch (uap->which) {
1353157285Sps	case 0:	{	/* shmat */
1354157285Sps		struct shmat_args ap;
1355157285Sps
1356157285Sps		ap.shmid = uap->a2;
1357157285Sps		ap.shmaddr = PTRIN(uap->a3);
1358157285Sps		ap.shmflg = uap->a4;
1359157285Sps		return (sysent[SYS_shmat].sy_call(td, &ap));
1360157285Sps	}
1361157285Sps	case 2: {	/* shmdt */
1362157285Sps		struct shmdt_args ap;
1363157285Sps
1364157285Sps		ap.shmaddr = PTRIN(uap->a2);
1365157285Sps		return (sysent[SYS_shmdt].sy_call(td, &ap));
1366157285Sps	}
1367157285Sps	case 3: {	/* shmget */
1368157285Sps		struct shmget_args ap;
1369157285Sps
1370157285Sps		ap.key = uap->a2;
1371157285Sps		ap.size = uap->a3;
1372157285Sps		ap.shmflg = uap->a4;
1373157285Sps		return (sysent[SYS_shmget].sy_call(td, &ap));
1374157285Sps	}
1375157285Sps	case 4: {	/* shmctl */
1376157285Sps		struct freebsd32_shmctl_args ap;
1377157285Sps
1378157285Sps		ap.shmid = uap->a2;
1379157285Sps		ap.cmd = uap->a3;
1380157285Sps		ap.buf = PTRIN(uap->a4);
1381157285Sps		return (freebsd32_shmctl(td, &ap));
1382157285Sps	}
1383157285Sps	case 1:		/* oshmctl */
1384157285Sps	default:
1385157285Sps		return (EINVAL);
1386157285Sps	}
1387100384Speter}
1388100384Speter
1389157285Spsstruct ipc_perm32 {
1390157285Sps	uint16_t	cuid;
1391157285Sps	uint16_t	cgid;
1392157285Sps	uint16_t	uid;
1393157285Sps	uint16_t	gid;
1394157285Sps	uint16_t	mode;
1395157285Sps	uint16_t	seq;
1396157285Sps	uint32_t	key;
1397157285Sps};
1398157285Spsstruct shmid_ds32 {
1399157285Sps	struct ipc_perm32 shm_perm;
1400157285Sps	int32_t		shm_segsz;
1401157285Sps	int32_t		shm_lpid;
1402157285Sps	int32_t		shm_cpid;
1403157285Sps	int16_t		shm_nattch;
1404157285Sps	int32_t		shm_atime;
1405157285Sps	int32_t		shm_dtime;
1406157285Sps	int32_t		shm_ctime;
1407157285Sps	uint32_t	shm_internal;
1408157285Sps};
1409157285Spsstruct shm_info32 {
1410157285Sps	int32_t		used_ids;
1411157285Sps	uint32_t	shm_tot;
1412157285Sps	uint32_t	shm_rss;
1413157285Sps	uint32_t	shm_swp;
1414157285Sps	uint32_t	swap_attempts;
1415157285Sps	uint32_t	swap_successes;
1416157285Sps};
1417157285Spsstruct shminfo32 {
1418157285Sps	uint32_t	shmmax;
1419157285Sps	uint32_t	shmmin;
1420157285Sps	uint32_t	shmmni;
1421157285Sps	uint32_t	shmseg;
1422157285Sps	uint32_t	shmall;
1423157285Sps};
1424157285Sps
1425100384Speterint
1426157285Spsfreebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
1427157285Sps{
1428157285Sps	int error = 0;
1429157285Sps	union {
1430157285Sps		struct shmid_ds shmid_ds;
1431157285Sps		struct shm_info shm_info;
1432157285Sps		struct shminfo shminfo;
1433157285Sps	} u;
1434157285Sps	union {
1435157285Sps		struct shmid_ds32 shmid_ds32;
1436157285Sps		struct shm_info32 shm_info32;
1437157285Sps		struct shminfo32 shminfo32;
1438157285Sps	} u32;
1439157285Sps	size_t sz;
1440157285Sps
1441157285Sps	if (uap->cmd == IPC_SET) {
1442157285Sps		if ((error = copyin(uap->buf, &u32.shmid_ds32,
1443157285Sps		    sizeof(u32.shmid_ds32))))
1444157285Sps			goto done;
1445157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cuid);
1446157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cgid);
1447157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.uid);
1448157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.gid);
1449157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.mode);
1450157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.seq);
1451157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.key);
1452157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1453157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1454157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1455157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1456157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1457157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1458157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1459157285Sps		PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal);
1460157285Sps	}
1461157285Sps
1462157285Sps	error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1463157285Sps	if (error)
1464157285Sps		goto done;
1465157285Sps
1466157285Sps	/* Cases in which we need to copyout */
1467157285Sps	switch (uap->cmd) {
1468157285Sps	case IPC_INFO:
1469157285Sps		CP(u.shminfo, u32.shminfo32, shmmax);
1470157285Sps		CP(u.shminfo, u32.shminfo32, shmmin);
1471157285Sps		CP(u.shminfo, u32.shminfo32, shmmni);
1472157285Sps		CP(u.shminfo, u32.shminfo32, shmseg);
1473157285Sps		CP(u.shminfo, u32.shminfo32, shmall);
1474157285Sps		error = copyout(&u32.shminfo32, uap->buf,
1475157285Sps		    sizeof(u32.shminfo32));
1476157285Sps		break;
1477157285Sps	case SHM_INFO:
1478157285Sps		CP(u.shm_info, u32.shm_info32, used_ids);
1479157285Sps		CP(u.shm_info, u32.shm_info32, shm_rss);
1480157285Sps		CP(u.shm_info, u32.shm_info32, shm_tot);
1481157285Sps		CP(u.shm_info, u32.shm_info32, shm_swp);
1482157285Sps		CP(u.shm_info, u32.shm_info32, swap_attempts);
1483157285Sps		CP(u.shm_info, u32.shm_info32, swap_successes);
1484157285Sps		error = copyout(&u32.shm_info32, uap->buf,
1485157285Sps		    sizeof(u32.shm_info32));
1486157285Sps		break;
1487157285Sps	case SHM_STAT:
1488157285Sps	case IPC_STAT:
1489157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cuid);
1490157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cgid);
1491157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.uid);
1492157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.gid);
1493157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.mode);
1494157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.seq);
1495157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.key);
1496157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1497157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1498157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1499157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1500157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1501157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1502157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1503157285Sps		PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal);
1504157285Sps		error = copyout(&u32.shmid_ds32, uap->buf,
1505157285Sps		    sizeof(u32.shmid_ds32));
1506157285Sps		break;
1507157285Sps	}
1508157285Sps
1509157285Spsdone:
1510157285Sps	if (error) {
1511157285Sps		/* Invalidate the return value */
1512157285Sps		td->td_retval[0] = -1;
1513157285Sps	}
1514157285Sps	return (error);
1515157285Sps}
1516157285Sps
1517157285Spsint
1518119333Speterfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1519100384Speter{
1520100384Speter	struct pread_args ap;
1521100384Speter
1522107849Salfred	ap.fd = uap->fd;
1523107849Salfred	ap.buf = uap->buf;
1524107849Salfred	ap.nbyte = uap->nbyte;
1525119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1526100384Speter	return (pread(td, &ap));
1527100384Speter}
1528100384Speter
1529100384Speterint
1530119333Speterfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1531100384Speter{
1532100384Speter	struct pwrite_args ap;
1533100384Speter
1534107849Salfred	ap.fd = uap->fd;
1535107849Salfred	ap.buf = uap->buf;
1536107849Salfred	ap.nbyte = uap->nbyte;
1537119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1538100384Speter	return (pwrite(td, &ap));
1539100384Speter}
1540100384Speter
1541100384Speterint
1542119333Speterfreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1543100384Speter{
1544100384Speter	int error;
1545100384Speter	struct lseek_args ap;
1546100384Speter	off_t pos;
1547100384Speter
1548107849Salfred	ap.fd = uap->fd;
1549119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1550107849Salfred	ap.whence = uap->whence;
1551100384Speter	error = lseek(td, &ap);
1552100384Speter	/* Expand the quad return into two parts for eax and edx */
1553100384Speter	pos = *(off_t *)(td->td_retval);
1554100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1555100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
1556100384Speter	return error;
1557100384Speter}
1558100384Speter
1559100384Speterint
1560119333Speterfreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1561100384Speter{
1562100384Speter	struct truncate_args ap;
1563100384Speter
1564107849Salfred	ap.path = uap->path;
1565119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1566100384Speter	return (truncate(td, &ap));
1567100384Speter}
1568100384Speter
1569100384Speterint
1570119333Speterfreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1571100384Speter{
1572100384Speter	struct ftruncate_args ap;
1573100384Speter
1574107849Salfred	ap.fd = uap->fd;
1575119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1576100384Speter	return (ftruncate(td, &ap));
1577100384Speter}
1578100384Speter
1579156114Spsstruct sf_hdtr32 {
1580156114Sps	uint32_t headers;
1581156114Sps	int hdr_cnt;
1582156114Sps	uint32_t trailers;
1583156114Sps	int trl_cnt;
1584156114Sps};
1585156114Sps
1586156114Spsstatic int
1587156114Spsfreebsd32_do_sendfile(struct thread *td,
1588156114Sps    struct freebsd32_sendfile_args *uap, int compat)
1589104738Speter{
1590156114Sps	struct sendfile_args ap;
1591156114Sps	struct sf_hdtr32 hdtr32;
1592156114Sps	struct sf_hdtr hdtr;
1593156114Sps	struct uio *hdr_uio, *trl_uio;
1594156114Sps	struct iovec32 *iov32;
1595156114Sps	int error;
1596104738Speter
1597156114Sps	hdr_uio = trl_uio = NULL;
1598156114Sps
1599107849Salfred	ap.fd = uap->fd;
1600107849Salfred	ap.s = uap->s;
1601119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1602156114Sps	ap.nbytes = uap->nbytes;
1603156114Sps	ap.hdtr = (struct sf_hdtr *)uap->hdtr;		/* XXX not used */
1604156114Sps	ap.sbytes = uap->sbytes;
1605107849Salfred	ap.flags = uap->flags;
1606156114Sps
1607156114Sps	if (uap->hdtr != NULL) {
1608156114Sps		error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
1609156114Sps		if (error)
1610156114Sps			goto out;
1611156114Sps		PTRIN_CP(hdtr32, hdtr, headers);
1612156114Sps		CP(hdtr32, hdtr, hdr_cnt);
1613156114Sps		PTRIN_CP(hdtr32, hdtr, trailers);
1614156114Sps		CP(hdtr32, hdtr, trl_cnt);
1615156114Sps
1616156114Sps		if (hdtr.headers != NULL) {
1617160246Sjhb			iov32 = PTRIN(hdtr32.headers);
1618156114Sps			error = freebsd32_copyinuio(iov32,
1619156114Sps			    hdtr32.hdr_cnt, &hdr_uio);
1620156114Sps			if (error)
1621156114Sps				goto out;
1622156114Sps		}
1623156114Sps		if (hdtr.trailers != NULL) {
1624160246Sjhb			iov32 = PTRIN(hdtr32.trailers);
1625156114Sps			error = freebsd32_copyinuio(iov32,
1626156114Sps			    hdtr32.trl_cnt, &trl_uio);
1627156114Sps			if (error)
1628156114Sps				goto out;
1629156114Sps		}
1630156114Sps	}
1631156114Sps
1632156114Sps	error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
1633156114Spsout:
1634156114Sps	if (hdr_uio)
1635156114Sps		free(hdr_uio, M_IOV);
1636156114Sps	if (trl_uio)
1637156114Sps		free(trl_uio, M_IOV);
1638156114Sps	return (error);
1639104738Speter}
1640156114Sps
1641156114Sps#ifdef COMPAT_FREEBSD4
1642156114Spsint
1643156114Spsfreebsd4_freebsd32_sendfile(struct thread *td,
1644156114Sps    struct freebsd4_freebsd32_sendfile_args *uap)
1645156114Sps{
1646156114Sps	return (freebsd32_do_sendfile(td,
1647156114Sps	    (struct freebsd32_sendfile_args *)uap, 1));
1648156114Sps}
1649104738Speter#endif
1650104738Speter
1651104738Speterint
1652119333Speterfreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1653100384Speter{
1654100384Speter
1655156114Sps	return (freebsd32_do_sendfile(td, uap, 0));
1656100384Speter}
1657100384Speter
1658100384Speterstruct stat32 {
1659130640Sphk	dev_t	st_dev;
1660100384Speter	ino_t	st_ino;
1661100384Speter	mode_t	st_mode;
1662100384Speter	nlink_t	st_nlink;
1663100384Speter	uid_t	st_uid;
1664100384Speter	gid_t	st_gid;
1665130640Sphk	dev_t	st_rdev;
1666100384Speter	struct timespec32 st_atimespec;
1667100384Speter	struct timespec32 st_mtimespec;
1668100384Speter	struct timespec32 st_ctimespec;
1669100384Speter	off_t	st_size;
1670100384Speter	int64_t	st_blocks;
1671100384Speter	u_int32_t st_blksize;
1672100384Speter	u_int32_t st_flags;
1673100384Speter	u_int32_t st_gen;
1674121719Speter	struct timespec32 st_birthtimespec;
1675121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1676121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1677100384Speter};
1678100384Speter
1679121719Speter
1680121719SpeterCTASSERT(sizeof(struct stat32) == 96);
1681121719Speter
1682100384Speterstatic void
1683100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1684100384Speter{
1685100384Speter	CP(*in, *out, st_dev);
1686100384Speter	CP(*in, *out, st_ino);
1687100384Speter	CP(*in, *out, st_mode);
1688100384Speter	CP(*in, *out, st_nlink);
1689100384Speter	CP(*in, *out, st_uid);
1690100384Speter	CP(*in, *out, st_gid);
1691100384Speter	CP(*in, *out, st_rdev);
1692100384Speter	TS_CP(*in, *out, st_atimespec);
1693100384Speter	TS_CP(*in, *out, st_mtimespec);
1694100384Speter	TS_CP(*in, *out, st_ctimespec);
1695100384Speter	CP(*in, *out, st_size);
1696100384Speter	CP(*in, *out, st_blocks);
1697100384Speter	CP(*in, *out, st_blksize);
1698100384Speter	CP(*in, *out, st_flags);
1699100384Speter	CP(*in, *out, st_gen);
1700100384Speter}
1701100384Speter
1702100384Speterint
1703119333Speterfreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1704100384Speter{
1705123746Speter	struct stat sb;
1706123746Speter	struct stat32 sb32;
1707100384Speter	int error;
1708100384Speter
1709142059Sjhb	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1710100384Speter	if (error)
1711100384Speter		return (error);
1712123746Speter	copy_stat(&sb, &sb32);
1713123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1714100384Speter	return (error);
1715100384Speter}
1716100384Speter
1717100384Speterint
1718119333Speterfreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1719100384Speter{
1720123746Speter	struct stat ub;
1721123746Speter	struct stat32 ub32;
1722100384Speter	int error;
1723100384Speter
1724142059Sjhb	error = kern_fstat(td, uap->fd, &ub);
1725100384Speter	if (error)
1726100384Speter		return (error);
1727123746Speter	copy_stat(&ub, &ub32);
1728123746Speter	error = copyout(&ub32, uap->ub, sizeof(ub32));
1729100384Speter	return (error);
1730100384Speter}
1731100384Speter
1732100384Speterint
1733119333Speterfreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1734100384Speter{
1735123746Speter	struct stat sb;
1736123746Speter	struct stat32 sb32;
1737142059Sjhb	int error;
1738100384Speter
1739142059Sjhb	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1740100384Speter	if (error)
1741100384Speter		return (error);
1742123746Speter	copy_stat(&sb, &sb32);
1743123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1744100384Speter	return (error);
1745100384Speter}
1746100384Speter
1747100384Speter/*
1748100384Speter * MPSAFE
1749100384Speter */
1750100384Speterint
1751119333Speterfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1752100384Speter{
1753100384Speter	int error, name[CTL_MAXNAME];
1754100384Speter	size_t j, oldlen;
1755100384Speter
1756100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1757100384Speter		return (EINVAL);
1758136404Speter 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1759100384Speter 	if (error)
1760100384Speter		return (error);
1761100384Speter	mtx_lock(&Giant);
1762100384Speter	if (uap->oldlenp)
1763100384Speter		oldlen = fuword32(uap->oldlenp);
1764100384Speter	else
1765100384Speter		oldlen = 0;
1766100384Speter	error = userland_sysctl(td, name, uap->namelen,
1767100384Speter		uap->old, &oldlen, 1,
1768136404Speter		uap->new, uap->newlen, &j, SCTL_MASK32);
1769100384Speter	if (error && error != ENOMEM)
1770100384Speter		goto done2;
1771136404Speter	if (uap->oldlenp)
1772100384Speter		suword32(uap->oldlenp, j);
1773100384Speterdone2:
1774100384Speter	mtx_unlock(&Giant);
1775100384Speter	return (error);
1776100384Speter}
1777100384Speter
1778100384Speterstruct sigaction32 {
1779100384Speter	u_int32_t	sa_u;
1780100384Speter	int		sa_flags;
1781100384Speter	sigset_t	sa_mask;
1782100384Speter};
1783100384Speter
1784121719SpeterCTASSERT(sizeof(struct sigaction32) == 24);
1785121719Speter
1786100384Speterint
1787119333Speterfreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1788100384Speter{
1789113859Sjhb	struct sigaction32 s32;
1790113859Sjhb	struct sigaction sa, osa, *sap;
1791100384Speter	int error;
1792100384Speter
1793113859Sjhb	if (uap->act) {
1794113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
1795100384Speter		if (error)
1796100384Speter			return (error);
1797113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
1798113859Sjhb		CP(s32, sa, sa_flags);
1799113859Sjhb		CP(s32, sa, sa_mask);
1800113859Sjhb		sap = &sa;
1801113859Sjhb	} else
1802113859Sjhb		sap = NULL;
1803113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1804146583Sps	if (error == 0 && uap->oact != NULL) {
1805113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
1806113859Sjhb		CP(osa, s32, sa_flags);
1807113859Sjhb		CP(osa, s32, sa_mask);
1808113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
1809100384Speter	}
1810100384Speter	return (error);
1811100384Speter}
1812100384Speter
1813114987Speter#ifdef COMPAT_FREEBSD4
1814114987Speterint
1815119333Speterfreebsd4_freebsd32_sigaction(struct thread *td,
1816119333Speter			     struct freebsd4_freebsd32_sigaction_args *uap)
1817114987Speter{
1818114987Speter	struct sigaction32 s32;
1819114987Speter	struct sigaction sa, osa, *sap;
1820114987Speter	int error;
1821114987Speter
1822114987Speter	if (uap->act) {
1823114987Speter		error = copyin(uap->act, &s32, sizeof(s32));
1824114987Speter		if (error)
1825114987Speter			return (error);
1826114987Speter		sa.sa_handler = PTRIN(s32.sa_u);
1827114987Speter		CP(s32, sa, sa_flags);
1828114987Speter		CP(s32, sa, sa_mask);
1829114987Speter		sap = &sa;
1830114987Speter	} else
1831114987Speter		sap = NULL;
1832114987Speter	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1833146583Sps	if (error == 0 && uap->oact != NULL) {
1834114987Speter		s32.sa_u = PTROUT(osa.sa_handler);
1835114987Speter		CP(osa, s32, sa_flags);
1836114987Speter		CP(osa, s32, sa_mask);
1837114987Speter		error = copyout(&s32, uap->oact, sizeof(s32));
1838114987Speter	}
1839114987Speter	return (error);
1840114987Speter}
1841114987Speter#endif
1842114987Speter
1843151582Sps#ifdef COMPAT_43
1844151720Speterstruct osigaction32 {
1845151582Sps	u_int32_t	sa_u;
1846151582Sps	osigset_t	sa_mask;
1847151582Sps	int		sa_flags;
1848151582Sps};
1849151582Sps
1850151582Sps#define	ONSIG	32
1851151582Sps
1852140481Spsint
1853151720Speterofreebsd32_sigaction(struct thread *td,
1854151720Speter			     struct ofreebsd32_sigaction_args *uap)
1855151582Sps{
1856151720Speter	struct osigaction32 s32;
1857151582Sps	struct sigaction sa, osa, *sap;
1858151582Sps	int error;
1859151582Sps
1860151582Sps	if (uap->signum <= 0 || uap->signum >= ONSIG)
1861151582Sps		return (EINVAL);
1862151582Sps
1863151582Sps	if (uap->nsa) {
1864151582Sps		error = copyin(uap->nsa, &s32, sizeof(s32));
1865151582Sps		if (error)
1866151582Sps			return (error);
1867151582Sps		sa.sa_handler = PTRIN(s32.sa_u);
1868151582Sps		CP(s32, sa, sa_flags);
1869151582Sps		OSIG2SIG(s32.sa_mask, sa.sa_mask);
1870151582Sps		sap = &sa;
1871151582Sps	} else
1872151582Sps		sap = NULL;
1873151582Sps	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1874151582Sps	if (error == 0 && uap->osa != NULL) {
1875151582Sps		s32.sa_u = PTROUT(osa.sa_handler);
1876151582Sps		CP(osa, s32, sa_flags);
1877151582Sps		SIG2OSIG(osa.sa_mask, s32.sa_mask);
1878151582Sps		error = copyout(&s32, uap->osa, sizeof(s32));
1879151582Sps	}
1880151582Sps	return (error);
1881151582Sps}
1882151582Sps
1883151582Spsint
1884151720Speterofreebsd32_sigprocmask(struct thread *td,
1885151720Speter			       struct ofreebsd32_sigprocmask_args *uap)
1886151582Sps{
1887151582Sps	sigset_t set, oset;
1888151582Sps	int error;
1889151582Sps
1890151582Sps	OSIG2SIG(uap->mask, set);
1891151582Sps	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
1892151582Sps	SIG2OSIG(oset, td->td_retval[0]);
1893151582Sps	return (error);
1894151582Sps}
1895151582Sps
1896151582Spsint
1897151720Speterofreebsd32_sigpending(struct thread *td,
1898151720Speter			      struct ofreebsd32_sigpending_args *uap)
1899151582Sps{
1900151582Sps	struct proc *p = td->td_proc;
1901151582Sps	sigset_t siglist;
1902151582Sps
1903151582Sps	PROC_LOCK(p);
1904151582Sps	siglist = p->p_siglist;
1905151582Sps	SIGSETOR(siglist, td->td_siglist);
1906151582Sps	PROC_UNLOCK(p);
1907151582Sps	SIG2OSIG(siglist, td->td_retval[0]);
1908151582Sps	return (0);
1909151582Sps}
1910151582Sps
1911151582Spsstruct sigvec32 {
1912151582Sps	u_int32_t	sv_handler;
1913151582Sps	int		sv_mask;
1914151582Sps	int		sv_flags;
1915151582Sps};
1916151582Sps
1917151582Spsint
1918151720Speterofreebsd32_sigvec(struct thread *td,
1919151720Speter			  struct ofreebsd32_sigvec_args *uap)
1920151582Sps{
1921151582Sps	struct sigvec32 vec;
1922151582Sps	struct sigaction sa, osa, *sap;
1923151582Sps	int error;
1924151582Sps
1925151582Sps	if (uap->signum <= 0 || uap->signum >= ONSIG)
1926151582Sps		return (EINVAL);
1927151582Sps
1928151582Sps	if (uap->nsv) {
1929151582Sps		error = copyin(uap->nsv, &vec, sizeof(vec));
1930151582Sps		if (error)
1931151582Sps			return (error);
1932151582Sps		sa.sa_handler = PTRIN(vec.sv_handler);
1933151582Sps		OSIG2SIG(vec.sv_mask, sa.sa_mask);
1934151582Sps		sa.sa_flags = vec.sv_flags;
1935151582Sps		sa.sa_flags ^= SA_RESTART;
1936151582Sps		sap = &sa;
1937151582Sps	} else
1938151582Sps		sap = NULL;
1939151582Sps	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1940151582Sps	if (error == 0 && uap->osv != NULL) {
1941151582Sps		vec.sv_handler = PTROUT(osa.sa_handler);
1942151582Sps		SIG2OSIG(osa.sa_mask, vec.sv_mask);
1943151582Sps		vec.sv_flags = osa.sa_flags;
1944151582Sps		vec.sv_flags &= ~SA_NOCLDWAIT;
1945151582Sps		vec.sv_flags ^= SA_RESTART;
1946151582Sps		error = copyout(&vec, uap->osv, sizeof(vec));
1947151582Sps	}
1948151582Sps	return (error);
1949151582Sps}
1950151582Sps
1951151582Spsint
1952151720Speterofreebsd32_sigblock(struct thread *td,
1953151720Speter			    struct ofreebsd32_sigblock_args *uap)
1954151582Sps{
1955151582Sps	struct proc *p = td->td_proc;
1956151582Sps	sigset_t set;
1957151582Sps
1958151582Sps	OSIG2SIG(uap->mask, set);
1959151582Sps	SIG_CANTMASK(set);
1960151582Sps	PROC_LOCK(p);
1961151582Sps	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1962151582Sps	SIGSETOR(td->td_sigmask, set);
1963151582Sps	PROC_UNLOCK(p);
1964151582Sps	return (0);
1965151582Sps}
1966151582Sps
1967151582Spsint
1968151720Speterofreebsd32_sigsetmask(struct thread *td,
1969151720Speter			      struct ofreebsd32_sigsetmask_args *uap)
1970151582Sps{
1971151582Sps	struct proc *p = td->td_proc;
1972151582Sps	sigset_t set;
1973151582Sps
1974151582Sps	OSIG2SIG(uap->mask, set);
1975151582Sps	SIG_CANTMASK(set);
1976151582Sps	PROC_LOCK(p);
1977151582Sps	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1978151582Sps	SIGSETLO(td->td_sigmask, set);
1979151582Sps	signotify(td);
1980151582Sps	PROC_UNLOCK(p);
1981151582Sps	return (0);
1982151582Sps}
1983151582Sps
1984151582Spsint
1985151720Speterofreebsd32_sigsuspend(struct thread *td,
1986151720Speter			      struct ofreebsd32_sigsuspend_args *uap)
1987151582Sps{
1988151582Sps	struct proc *p = td->td_proc;
1989151582Sps	sigset_t mask;
1990151582Sps
1991151582Sps	PROC_LOCK(p);
1992151582Sps	td->td_oldsigmask = td->td_sigmask;
1993151582Sps	td->td_pflags |= TDP_OLDMASK;
1994151582Sps	OSIG2SIG(uap->mask, mask);
1995151582Sps	SIG_CANTMASK(mask);
1996151582Sps	SIGSETLO(td->td_sigmask, mask);
1997151582Sps	signotify(td);
1998151582Sps	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
1999151582Sps		/* void */;
2000151582Sps	PROC_UNLOCK(p);
2001151582Sps	/* always return EINTR rather than ERESTART... */
2002151582Sps	return (EINTR);
2003151582Sps}
2004151582Sps
2005151582Spsstruct sigstack32 {
2006151582Sps	u_int32_t	ss_sp;
2007151582Sps	int		ss_onstack;
2008151582Sps};
2009151582Sps
2010151582Spsint
2011151720Speterofreebsd32_sigstack(struct thread *td,
2012151720Speter			    struct ofreebsd32_sigstack_args *uap)
2013151582Sps{
2014151582Sps	struct sigstack32 s32;
2015151582Sps	struct sigstack nss, oss;
2016151582Sps	int error = 0;
2017151582Sps
2018151582Sps	if (uap->nss != NULL) {
2019151582Sps		error = copyin(uap->nss, &s32, sizeof(s32));
2020151582Sps		if (error)
2021151582Sps			return (error);
2022151582Sps		nss.ss_sp = PTRIN(s32.ss_sp);
2023151582Sps		CP(s32, nss, ss_onstack);
2024151582Sps	}
2025151582Sps	oss.ss_sp = td->td_sigstk.ss_sp;
2026151582Sps	oss.ss_onstack = sigonstack(cpu_getstack(td));
2027151582Sps	if (uap->nss != NULL) {
2028151582Sps		td->td_sigstk.ss_sp = nss.ss_sp;
2029151582Sps		td->td_sigstk.ss_size = 0;
2030151582Sps		td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK;
2031151582Sps		td->td_pflags |= TDP_ALTSTACK;
2032151582Sps	}
2033151582Sps	if (uap->oss != NULL) {
2034151582Sps		s32.ss_sp = PTROUT(oss.ss_sp);
2035151582Sps		CP(oss, s32, ss_onstack);
2036151582Sps		error = copyout(&s32, uap->oss, sizeof(s32));
2037151582Sps	}
2038151582Sps	return (error);
2039151582Sps}
2040151582Sps#endif
2041151582Sps
2042151582Spsint
2043140481Spsfreebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
2044140481Sps{
2045140481Sps	struct timespec32 rmt32, rqt32;
2046140481Sps	struct timespec rmt, rqt;
2047140481Sps	int error;
2048140481Sps
2049151355Sps	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
2050140481Sps	if (error)
2051140481Sps		return (error);
2052140481Sps
2053140481Sps	CP(rqt32, rqt, tv_sec);
2054140481Sps	CP(rqt32, rqt, tv_nsec);
2055140481Sps
2056140481Sps	if (uap->rmtp &&
2057140481Sps	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
2058140481Sps		return (EFAULT);
2059140481Sps	error = kern_nanosleep(td, &rqt, &rmt);
2060140481Sps	if (error && uap->rmtp) {
2061140481Sps		int error2;
2062140481Sps
2063140481Sps		CP(rmt, rmt32, tv_sec);
2064140481Sps		CP(rmt, rmt32, tv_nsec);
2065140481Sps
2066151355Sps		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
2067140481Sps		if (error2)
2068140481Sps			error = error2;
2069140481Sps	}
2070140481Sps	return (error);
2071140481Sps}
2072140481Sps
2073151357Spsint
2074151357Spsfreebsd32_clock_gettime(struct thread *td,
2075151357Sps			struct freebsd32_clock_gettime_args *uap)
2076151357Sps{
2077151357Sps	struct timespec	ats;
2078151357Sps	struct timespec32 ats32;
2079151357Sps	int error;
2080151357Sps
2081151357Sps	error = kern_clock_gettime(td, uap->clock_id, &ats);
2082151357Sps	if (error == 0) {
2083151357Sps		CP(ats, ats32, tv_sec);
2084151357Sps		CP(ats, ats32, tv_nsec);
2085151357Sps		error = copyout(&ats32, uap->tp, sizeof(ats32));
2086151357Sps	}
2087151357Sps	return (error);
2088151357Sps}
2089151357Sps
2090151357Spsint
2091151357Spsfreebsd32_clock_settime(struct thread *td,
2092151357Sps			struct freebsd32_clock_settime_args *uap)
2093151357Sps{
2094151357Sps	struct timespec	ats;
2095151357Sps	struct timespec32 ats32;
2096151357Sps	int error;
2097151357Sps
2098151357Sps	error = copyin(uap->tp, &ats32, sizeof(ats32));
2099151357Sps	if (error)
2100151357Sps		return (error);
2101151357Sps	CP(ats32, ats, tv_sec);
2102151357Sps	CP(ats32, ats, tv_nsec);
2103151357Sps
2104151357Sps	return (kern_clock_settime(td, uap->clock_id, &ats));
2105151357Sps}
2106151357Sps
2107151357Spsint
2108151357Spsfreebsd32_clock_getres(struct thread *td,
2109151357Sps		       struct freebsd32_clock_getres_args *uap)
2110151357Sps{
2111151357Sps	struct timespec	ts;
2112151357Sps	struct timespec32 ts32;
2113151357Sps	int error;
2114151357Sps
2115151357Sps	if (uap->tp == NULL)
2116151357Sps		return (0);
2117151357Sps	error = kern_clock_getres(td, uap->clock_id, &ts);
2118151357Sps	if (error == 0) {
2119151357Sps		CP(ts, ts32, tv_sec);
2120151357Sps		CP(ts, ts32, tv_nsec);
2121151357Sps		error = copyout(&ts32, uap->tp, sizeof(ts32));
2122151357Sps	}
2123151357Sps	return (error);
2124151357Sps}
2125151357Sps
2126162551Sdavidxuint
2127162551Sdavidxufreebsd32_thr_new(struct thread *td,
2128162551Sdavidxu		  struct freebsd32_thr_new_args *uap)
2129162551Sdavidxu{
2130162551Sdavidxu	struct thr_param32 param32;
2131162551Sdavidxu	struct thr_param param;
2132162551Sdavidxu	int error;
2133162551Sdavidxu
2134162551Sdavidxu	if (uap->param_size < 0 ||
2135162551Sdavidxu	    uap->param_size > sizeof(struct thr_param32))
2136162551Sdavidxu		return (EINVAL);
2137162551Sdavidxu	bzero(&param, sizeof(struct thr_param));
2138162551Sdavidxu	bzero(&param32, sizeof(struct thr_param32));
2139162551Sdavidxu	error = copyin(uap->param, &param32, uap->param_size);
2140162551Sdavidxu	if (error != 0)
2141162551Sdavidxu		return (error);
2142162551Sdavidxu	param.start_func = PTRIN(param32.start_func);
2143162551Sdavidxu	param.arg = PTRIN(param32.arg);
2144162551Sdavidxu	param.stack_base = PTRIN(param32.stack_base);
2145162551Sdavidxu	param.stack_size = param32.stack_size;
2146162551Sdavidxu	param.tls_base = PTRIN(param32.tls_base);
2147162551Sdavidxu	param.tls_size = param32.tls_size;
2148162551Sdavidxu	param.child_tid = PTRIN(param32.child_tid);
2149162551Sdavidxu	param.parent_tid = PTRIN(param32.parent_tid);
2150162551Sdavidxu	param.flags = param32.flags;
2151162551Sdavidxu	param.rtp = PTRIN(param32.rtp);
2152162551Sdavidxu	param.spare[0] = PTRIN(param32.spare[0]);
2153162551Sdavidxu	param.spare[1] = PTRIN(param32.spare[1]);
2154162551Sdavidxu	param.spare[2] = PTRIN(param32.spare[2]);
2155162551Sdavidxu
2156162551Sdavidxu	return (kern_thr_new(td, &param));
2157162551Sdavidxu}
2158162551Sdavidxu
2159162551Sdavidxuint
2160162551Sdavidxufreebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
2161162551Sdavidxu{
2162162551Sdavidxu	struct timespec32 ts32;
2163162551Sdavidxu	struct timespec ts, *tsp;
2164162551Sdavidxu	int error;
2165162551Sdavidxu
2166162551Sdavidxu	error = 0;
2167162551Sdavidxu	tsp = NULL;
2168162551Sdavidxu	if (uap->timeout != NULL) {
2169162551Sdavidxu		error = copyin((const void *)uap->timeout, (void *)&ts32,
2170162551Sdavidxu		    sizeof(struct timespec32));
2171162551Sdavidxu		if (error != 0)
2172162551Sdavidxu			return (error);
2173162551Sdavidxu		ts.tv_sec = ts32.tv_sec;
2174162551Sdavidxu		ts.tv_nsec = ts32.tv_nsec;
2175162551Sdavidxu		tsp = &ts;
2176162551Sdavidxu	}
2177162551Sdavidxu	return (kern_thr_suspend(td, tsp));
2178162551Sdavidxu}
2179162551Sdavidxu
2180100384Speter#if 0
2181100384Speter
2182100384Speterint
2183119333Speterfreebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
2184100384Speter{
2185100384Speter	int error;
2186100384Speter	struct yyy32 *p32, s32;
2187100384Speter	struct yyy *p = NULL, s;
2188100384Speter
2189147654Sjhb	if (uap->zzz) {
2190147654Sjhb		error = copyin(uap->zzz, &s32, sizeof(s32));
2191100384Speter		if (error)
2192100384Speter			return (error);
2193100384Speter		/* translate in */
2194147654Sjhb		p = &s;
2195100384Speter	}
2196147654Sjhb	error = kern_xxx(td, p);
2197100384Speter	if (error)
2198100384Speter		return (error);
2199147654Sjhb	if (uap->zzz) {
2200100384Speter		/* translate out */
2201100384Speter		error = copyout(&s32, p32, sizeof(s32));
2202100384Speter	}
2203100384Speter	return (error);
2204100384Speter}
2205100384Speter
2206100384Speter#endif
2207