freebsd32_misc.c revision 152134
1/*-
2 * Copyright (c) 2002 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 152134 2005-11-06 18:12:43Z ps $");
29
30#include "opt_compat.h"
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/exec.h>
36#include <sys/fcntl.h>
37#include <sys/filedesc.h>
38#include <sys/namei.h>
39#include <sys/imgact.h>
40#include <sys/kernel.h>
41#include <sys/lock.h>
42#include <sys/malloc.h>
43#include <sys/file.h>		/* Must come after sys/malloc.h */
44#include <sys/mbuf.h>
45#include <sys/mman.h>
46#include <sys/module.h>
47#include <sys/mount.h>
48#include <sys/mutex.h>
49#include <sys/namei.h>
50#include <sys/param.h>
51#include <sys/proc.h>
52#include <sys/reboot.h>
53#include <sys/resource.h>
54#include <sys/resourcevar.h>
55#include <sys/selinfo.h>
56#include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
57#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
58#include <sys/signal.h>
59#include <sys/signalvar.h>
60#include <sys/socket.h>
61#include <sys/socketvar.h>
62#include <sys/stat.h>
63#include <sys/syscall.h>
64#include <sys/syscallsubr.h>
65#include <sys/sysctl.h>
66#include <sys/sysent.h>
67#include <sys/sysproto.h>
68#include <sys/systm.h>
69#include <sys/unistd.h>
70#include <sys/vnode.h>
71#include <sys/wait.h>
72
73#include <vm/vm.h>
74#include <vm/vm_kern.h>
75#include <vm/vm_param.h>
76#include <vm/pmap.h>
77#include <vm/vm_map.h>
78#include <vm/vm_object.h>
79#include <vm/vm_extern.h>
80
81#include <machine/cpu.h>
82
83#include <compat/freebsd32/freebsd32_util.h>
84#include <compat/freebsd32/freebsd32.h>
85#include <compat/freebsd32/freebsd32_proto.h>
86
87CTASSERT(sizeof(struct timeval32) == 8);
88CTASSERT(sizeof(struct timespec32) == 8);
89CTASSERT(sizeof(struct statfs32) == 256);
90CTASSERT(sizeof(struct rusage32) == 72);
91
92int
93freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
94{
95	int error, status;
96	struct rusage32 ru32;
97	struct rusage ru, *rup;
98
99	if (uap->rusage != NULL)
100		rup = &ru;
101	else
102		rup = NULL;
103	error = kern_wait(td, uap->pid, &status, uap->options, rup);
104	if (error)
105		return (error);
106	if (uap->status != NULL)
107		error = copyout(&status, uap->status, sizeof(status));
108	if (uap->rusage != NULL && error == 0) {
109		TV_CP(ru, ru32, ru_utime);
110		TV_CP(ru, ru32, ru_stime);
111		CP(ru, ru32, ru_maxrss);
112		CP(ru, ru32, ru_ixrss);
113		CP(ru, ru32, ru_idrss);
114		CP(ru, ru32, ru_isrss);
115		CP(ru, ru32, ru_minflt);
116		CP(ru, ru32, ru_majflt);
117		CP(ru, ru32, ru_nswap);
118		CP(ru, ru32, ru_inblock);
119		CP(ru, ru32, ru_oublock);
120		CP(ru, ru32, ru_msgsnd);
121		CP(ru, ru32, ru_msgrcv);
122		CP(ru, ru32, ru_nsignals);
123		CP(ru, ru32, ru_nvcsw);
124		CP(ru, ru32, ru_nivcsw);
125		error = copyout(&ru32, uap->rusage, sizeof(ru32));
126	}
127	return (error);
128}
129
130#ifdef COMPAT_FREEBSD4
131static void
132copy_statfs(struct statfs *in, struct statfs32 *out)
133{
134	CP(*in, *out, f_bsize);
135	CP(*in, *out, f_iosize);
136	CP(*in, *out, f_blocks);
137	CP(*in, *out, f_bfree);
138	CP(*in, *out, f_bavail);
139	CP(*in, *out, f_files);
140	CP(*in, *out, f_ffree);
141	CP(*in, *out, f_fsid);
142	CP(*in, *out, f_owner);
143	CP(*in, *out, f_type);
144	CP(*in, *out, f_flags);
145	CP(*in, *out, f_flags);
146	CP(*in, *out, f_syncwrites);
147	CP(*in, *out, f_asyncwrites);
148	bcopy(in->f_fstypename,
149	      out->f_fstypename, MFSNAMELEN);
150	bcopy(in->f_mntonname,
151	      out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
152	CP(*in, *out, f_syncreads);
153	CP(*in, *out, f_asyncreads);
154	bcopy(in->f_mntfromname,
155	      out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
156}
157#endif
158
159#ifdef COMPAT_FREEBSD4
160int
161freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
162{
163	struct statfs *buf, *sp;
164	struct statfs32 stat32;
165	size_t count, size;
166	int error;
167
168	count = uap->bufsize / sizeof(struct statfs32);
169	size = count * sizeof(struct statfs);
170	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
171	if (size > 0) {
172		count = td->td_retval[0];
173		sp = buf;
174		while (count > 0 && error == 0) {
175			copy_statfs(sp, &stat32);
176			error = copyout(&stat32, uap->buf, sizeof(stat32));
177			sp++;
178			uap->buf++;
179			count--;
180		}
181		free(buf, M_TEMP);
182	}
183	return (error);
184}
185#endif
186
187struct sigaltstack32 {
188	u_int32_t	ss_sp;
189	u_int32_t	ss_size;
190	int		ss_flags;
191};
192
193CTASSERT(sizeof(struct sigaltstack32) == 12);
194
195int
196freebsd32_sigaltstack(struct thread *td,
197		      struct freebsd32_sigaltstack_args *uap)
198{
199	struct sigaltstack32 s32;
200	struct sigaltstack ss, oss, *ssp;
201	int error;
202
203	if (uap->ss != NULL) {
204		error = copyin(uap->ss, &s32, sizeof(s32));
205		if (error)
206			return (error);
207		PTRIN_CP(s32, ss, ss_sp);
208		CP(s32, ss, ss_size);
209		CP(s32, ss, ss_flags);
210		ssp = &ss;
211	} else
212		ssp = NULL;
213	error = kern_sigaltstack(td, ssp, &oss);
214	if (error == 0 && uap->oss != NULL) {
215		PTROUT_CP(oss, s32, ss_sp);
216		CP(oss, s32, ss_size);
217		CP(oss, s32, ss_flags);
218		error = copyout(&s32, uap->oss, sizeof(s32));
219	}
220	return (error);
221}
222
223/*
224 * Custom version of exec_copyin_args() so that we can translate
225 * the pointers.
226 */
227static int
228freebsd32_exec_copyin_args(struct image_args *args, char *fname,
229    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
230{
231	char *argp, *envp;
232	u_int32_t *p32, arg;
233	size_t length;
234	int error;
235
236	bzero(args, sizeof(*args));
237	if (argv == NULL)
238		return (EFAULT);
239
240	/*
241	 * Allocate temporary demand zeroed space for argument and
242	 *	environment strings
243	 */
244	args->buf = (char *) kmem_alloc_wait(exec_map,
245	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
246	if (args->buf == NULL)
247		return (ENOMEM);
248	args->begin_argv = args->buf;
249	args->endp = args->begin_argv;
250	args->stringspace = ARG_MAX;
251
252	args->fname = args->buf + ARG_MAX;
253
254	/*
255	 * Copy the file name.
256	 */
257	error = (segflg == UIO_SYSSPACE) ?
258	    copystr(fname, args->fname, PATH_MAX, &length) :
259	    copyinstr(fname, args->fname, PATH_MAX, &length);
260	if (error != 0)
261		return (error);
262
263	/*
264	 * extract arguments first
265	 */
266	p32 = argv;
267	for (;;) {
268		error = copyin(p32++, &arg, sizeof(arg));
269		if (error)
270			return (error);
271		if (arg == 0)
272			break;
273		argp = PTRIN(arg);
274		error = copyinstr(argp, args->endp, args->stringspace, &length);
275		if (error) {
276			if (error == ENAMETOOLONG)
277				return (E2BIG);
278			else
279				return (error);
280		}
281		args->stringspace -= length;
282		args->endp += length;
283		args->argc++;
284	}
285
286	args->begin_envv = args->endp;
287
288	/*
289	 * extract environment strings
290	 */
291	if (envv) {
292		p32 = envv;
293		for (;;) {
294			error = copyin(p32++, &arg, sizeof(arg));
295			if (error)
296				return (error);
297			if (arg == 0)
298				break;
299			envp = PTRIN(arg);
300			error = copyinstr(envp, args->endp, args->stringspace,
301			    &length);
302			if (error) {
303				if (error == ENAMETOOLONG)
304					return (E2BIG);
305				else
306					return (error);
307			}
308			args->stringspace -= length;
309			args->endp += length;
310			args->envc++;
311		}
312	}
313
314	return (0);
315}
316
317int
318freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
319{
320	struct image_args eargs;
321	int error;
322
323	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
324	    uap->argv, uap->envv);
325	if (error == 0)
326		error = kern_execve(td, &eargs, NULL);
327	exec_free_args(&eargs);
328	return (error);
329}
330
331#ifdef __ia64__
332static int
333freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
334		       int prot, int fd, off_t pos)
335{
336	vm_map_t map;
337	vm_map_entry_t entry;
338	int rv;
339
340	map = &td->td_proc->p_vmspace->vm_map;
341	if (fd != -1)
342		prot |= VM_PROT_WRITE;
343
344	if (vm_map_lookup_entry(map, start, &entry)) {
345		if ((entry->protection & prot) != prot) {
346			rv = vm_map_protect(map,
347					    trunc_page(start),
348					    round_page(end),
349					    entry->protection | prot,
350					    FALSE);
351			if (rv != KERN_SUCCESS)
352				return (EINVAL);
353		}
354	} else {
355		vm_offset_t addr = trunc_page(start);
356		rv = vm_map_find(map, 0, 0,
357				 &addr, PAGE_SIZE, FALSE, prot,
358				 VM_PROT_ALL, 0);
359		if (rv != KERN_SUCCESS)
360			return (EINVAL);
361	}
362
363	if (fd != -1) {
364		struct pread_args r;
365		r.fd = fd;
366		r.buf = (void *) start;
367		r.nbyte = end - start;
368		r.offset = pos;
369		return (pread(td, &r));
370	} else {
371		while (start < end) {
372			subyte((void *) start, 0);
373			start++;
374		}
375		return (0);
376	}
377}
378#endif
379
380int
381freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
382{
383	struct mmap_args ap;
384	vm_offset_t addr = (vm_offset_t) uap->addr;
385	vm_size_t len	 = uap->len;
386	int prot	 = uap->prot;
387	int flags	 = uap->flags;
388	int fd		 = uap->fd;
389	off_t pos	 = (uap->poslo
390			    | ((off_t)uap->poshi << 32));
391#ifdef __ia64__
392	vm_size_t pageoff;
393	int error;
394
395	/*
396	 * Attempt to handle page size hassles.
397	 */
398	pageoff = (pos & PAGE_MASK);
399	if (flags & MAP_FIXED) {
400		vm_offset_t start, end;
401		start = addr;
402		end = addr + len;
403
404		mtx_lock(&Giant);
405		if (start != trunc_page(start)) {
406			error = freebsd32_mmap_partial(td, start,
407						       round_page(start), prot,
408						       fd, pos);
409			if (fd != -1)
410				pos += round_page(start) - start;
411			start = round_page(start);
412		}
413		if (end != round_page(end)) {
414			vm_offset_t t = trunc_page(end);
415			error = freebsd32_mmap_partial(td, t, end,
416						  prot, fd,
417						  pos + t - start);
418			end = trunc_page(end);
419		}
420		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
421			/*
422			 * We can't map this region at all. The specified
423			 * address doesn't have the same alignment as the file
424			 * position. Fake the mapping by simply reading the
425			 * entire region into memory. First we need to make
426			 * sure the region exists.
427			 */
428			vm_map_t map;
429			struct pread_args r;
430			int rv;
431
432			prot |= VM_PROT_WRITE;
433			map = &td->td_proc->p_vmspace->vm_map;
434			rv = vm_map_remove(map, start, end);
435			if (rv != KERN_SUCCESS) {
436				mtx_unlock(&Giant);
437				return (EINVAL);
438			}
439			rv = vm_map_find(map, 0, 0,
440					 &start, end - start, FALSE,
441					 prot, VM_PROT_ALL, 0);
442			mtx_unlock(&Giant);
443			if (rv != KERN_SUCCESS)
444				return (EINVAL);
445			r.fd = fd;
446			r.buf = (void *) start;
447			r.nbyte = end - start;
448			r.offset = pos;
449			error = pread(td, &r);
450			if (error)
451				return (error);
452
453			td->td_retval[0] = addr;
454			return (0);
455		}
456		mtx_unlock(&Giant);
457		if (end == start) {
458			/*
459			 * After dealing with the ragged ends, there
460			 * might be none left.
461			 */
462			td->td_retval[0] = addr;
463			return (0);
464		}
465		addr = start;
466		len = end - start;
467	}
468#endif
469
470	ap.addr = (void *) addr;
471	ap.len = len;
472	ap.prot = prot;
473	ap.flags = flags;
474	ap.fd = fd;
475	ap.pos = pos;
476
477	return (mmap(td, &ap));
478}
479
480struct itimerval32 {
481	struct timeval32 it_interval;
482	struct timeval32 it_value;
483};
484
485CTASSERT(sizeof(struct itimerval32) == 16);
486
487int
488freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
489{
490	struct itimerval itv, oitv, *itvp;
491	struct itimerval32 i32;
492	int error;
493
494	if (uap->itv != NULL) {
495		error = copyin(uap->itv, &i32, sizeof(i32));
496		if (error)
497			return (error);
498		TV_CP(i32, itv, it_interval);
499		TV_CP(i32, itv, it_value);
500		itvp = &itv;
501	} else
502		itvp = NULL;
503	error = kern_setitimer(td, uap->which, itvp, &oitv);
504	if (error || uap->oitv == NULL)
505		return (error);
506	TV_CP(oitv, i32, it_interval);
507	TV_CP(oitv, i32, it_value);
508	return (copyout(&i32, uap->oitv, sizeof(i32)));
509}
510
511int
512freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
513{
514	struct itimerval itv;
515	struct itimerval32 i32;
516	int error;
517
518	error = kern_getitimer(td, uap->which, &itv);
519	if (error || uap->itv == NULL)
520		return (error);
521	TV_CP(itv, i32, it_interval);
522	TV_CP(itv, i32, it_value);
523	return (copyout(&i32, uap->itv, sizeof(i32)));
524}
525
526int
527freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
528{
529	struct timeval32 tv32;
530	struct timeval tv, *tvp;
531	int error;
532
533	if (uap->tv != NULL) {
534		error = copyin(uap->tv, &tv32, sizeof(tv32));
535		if (error)
536			return (error);
537		CP(tv32, tv, tv_sec);
538		CP(tv32, tv, tv_usec);
539		tvp = &tv;
540	} else
541		tvp = NULL;
542	/*
543	 * XXX big-endian needs to convert the fd_sets too.
544	 * XXX Do pointers need PTRIN()?
545	 */
546	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
547}
548
549struct kevent32 {
550	u_int32_t	ident;		/* identifier for this event */
551	short		filter;		/* filter for event */
552	u_short		flags;
553	u_int		fflags;
554	int32_t		data;
555	u_int32_t	udata;		/* opaque user data identifier */
556};
557
558CTASSERT(sizeof(struct kevent32) == 20);
559static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
560static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
561
562/*
563 * Copy 'count' items into the destination list pointed to by uap->eventlist.
564 */
565static int
566freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
567{
568	struct freebsd32_kevent_args *uap;
569	struct kevent32	ks32[KQ_NEVENTS];
570	int i, error = 0;
571
572	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
573	uap = (struct freebsd32_kevent_args *)arg;
574
575	for (i = 0; i < count; i++) {
576		CP(kevp[i], ks32[i], ident);
577		CP(kevp[i], ks32[i], filter);
578		CP(kevp[i], ks32[i], flags);
579		CP(kevp[i], ks32[i], fflags);
580		CP(kevp[i], ks32[i], data);
581		PTROUT_CP(kevp[i], ks32[i], udata);
582	}
583	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
584	if (error == 0)
585		uap->eventlist += count;
586	return (error);
587}
588
589/*
590 * Copy 'count' items from the list pointed to by uap->changelist.
591 */
592static int
593freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
594{
595	struct freebsd32_kevent_args *uap;
596	struct kevent32	ks32[KQ_NEVENTS];
597	int i, error = 0;
598
599	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
600	uap = (struct freebsd32_kevent_args *)arg;
601
602	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
603	if (error)
604		goto done;
605	uap->changelist += count;
606
607	for (i = 0; i < count; i++) {
608		CP(ks32[i], kevp[i], ident);
609		CP(ks32[i], kevp[i], filter);
610		CP(ks32[i], kevp[i], flags);
611		CP(ks32[i], kevp[i], fflags);
612		CP(ks32[i], kevp[i], data);
613		PTRIN_CP(ks32[i], kevp[i], udata);
614	}
615done:
616	return (error);
617}
618
619int
620freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
621{
622	struct timespec32 ts32;
623	struct timespec ts, *tsp;
624	struct kevent_copyops k_ops = { uap,
625					freebsd32_kevent_copyout,
626					freebsd32_kevent_copyin};
627	int error;
628
629
630	if (uap->timeout) {
631		error = copyin(uap->timeout, &ts32, sizeof(ts32));
632		if (error)
633			return (error);
634		CP(ts32, ts, tv_sec);
635		CP(ts32, ts, tv_nsec);
636		tsp = &ts;
637	} else
638		tsp = NULL;
639	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
640	    &k_ops, tsp);
641	return (error);
642}
643
644int
645freebsd32_gettimeofday(struct thread *td,
646		       struct freebsd32_gettimeofday_args *uap)
647{
648	struct timeval atv;
649	struct timeval32 atv32;
650	struct timezone rtz;
651	int error = 0;
652
653	if (uap->tp) {
654		microtime(&atv);
655		CP(atv, atv32, tv_sec);
656		CP(atv, atv32, tv_usec);
657		error = copyout(&atv32, uap->tp, sizeof (atv32));
658	}
659	if (error == 0 && uap->tzp != NULL) {
660		rtz.tz_minuteswest = tz_minuteswest;
661		rtz.tz_dsttime = tz_dsttime;
662		error = copyout(&rtz, uap->tzp, sizeof (rtz));
663	}
664	return (error);
665}
666
667int
668freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
669{
670	struct rusage32 s32;
671	struct rusage s;
672	int error;
673
674	error = kern_getrusage(td, uap->who, &s);
675	if (error)
676		return (error);
677	if (uap->rusage != NULL) {
678		TV_CP(s, s32, ru_utime);
679		TV_CP(s, s32, ru_stime);
680		CP(s, s32, ru_maxrss);
681		CP(s, s32, ru_ixrss);
682		CP(s, s32, ru_idrss);
683		CP(s, s32, ru_isrss);
684		CP(s, s32, ru_minflt);
685		CP(s, s32, ru_majflt);
686		CP(s, s32, ru_nswap);
687		CP(s, s32, ru_inblock);
688		CP(s, s32, ru_oublock);
689		CP(s, s32, ru_msgsnd);
690		CP(s, s32, ru_msgrcv);
691		CP(s, s32, ru_nsignals);
692		CP(s, s32, ru_nvcsw);
693		CP(s, s32, ru_nivcsw);
694		error = copyout(&s32, uap->rusage, sizeof(s32));
695	}
696	return (error);
697}
698
699struct iovec32 {
700	u_int32_t iov_base;
701	int	iov_len;
702};
703
704CTASSERT(sizeof(struct iovec32) == 8);
705
706static int
707freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
708{
709	struct iovec32 iov32;
710	struct iovec *iov;
711	struct uio *uio;
712	u_int iovlen;
713	int error, i;
714
715	*uiop = NULL;
716	if (iovcnt > UIO_MAXIOV)
717		return (EINVAL);
718	iovlen = iovcnt * sizeof(struct iovec);
719	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
720	iov = (struct iovec *)(uio + 1);
721	for (i = 0; i < iovcnt; i++) {
722		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
723		if (error) {
724			free(uio, M_IOV);
725			return (error);
726		}
727		iov[i].iov_base = PTRIN(iov32.iov_base);
728		iov[i].iov_len = iov32.iov_len;
729	}
730	uio->uio_iov = iov;
731	uio->uio_iovcnt = iovcnt;
732	uio->uio_segflg = UIO_USERSPACE;
733	uio->uio_offset = -1;
734	uio->uio_resid = 0;
735	for (i = 0; i < iovcnt; i++) {
736		if (iov->iov_len > INT_MAX - uio->uio_resid) {
737			free(uio, M_IOV);
738			return (EINVAL);
739		}
740		uio->uio_resid += iov->iov_len;
741		iov++;
742	}
743	*uiop = uio;
744	return (0);
745}
746
747int
748freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
749{
750	struct uio *auio;
751	int error;
752
753	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
754	if (error)
755		return (error);
756	error = kern_readv(td, uap->fd, auio);
757	free(auio, M_IOV);
758	return (error);
759}
760
761int
762freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
763{
764	struct uio *auio;
765	int error;
766
767	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
768	if (error)
769		return (error);
770	error = kern_writev(td, uap->fd, auio);
771	free(auio, M_IOV);
772	return (error);
773}
774
775int
776freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
777{
778	struct uio *auio;
779	int error;
780
781	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
782	if (error)
783		return (error);
784	error = kern_preadv(td, uap->fd, auio, uap->offset);
785	free(auio, M_IOV);
786	return (error);
787}
788
789int
790freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
791{
792	struct uio *auio;
793	int error;
794
795	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
796	if (error)
797		return (error);
798	error = kern_pwritev(td, uap->fd, auio, uap->offset);
799	free(auio, M_IOV);
800	return (error);
801}
802
803static int
804freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
805    int error)
806{
807	struct iovec32 iov32;
808	struct iovec *iov;
809	u_int iovlen;
810	int i;
811
812	*iovp = NULL;
813	if (iovcnt > UIO_MAXIOV)
814		return (error);
815	iovlen = iovcnt * sizeof(struct iovec);
816	iov = malloc(iovlen, M_IOV, M_WAITOK);
817	for (i = 0; i < iovcnt; i++) {
818		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
819		if (error) {
820			free(iov, M_IOV);
821			return (error);
822		}
823		iov[i].iov_base = PTRIN(iov32.iov_base);
824		iov[i].iov_len = iov32.iov_len;
825	}
826	*iovp = iov;
827	return (0);
828}
829
830static int
831freebsd32_copyoutiov(struct iovec *iov, u_int iovcnt, struct iovec32 *iovp,
832    int error)
833{
834	struct iovec32 iov32;
835	int i;
836
837	if (iovcnt > UIO_MAXIOV)
838		return (error);
839	for (i = 0; i < iovcnt; i++) {
840		iov32.iov_base = PTROUT(iov[i].iov_base);
841		iov32.iov_len = iov[i].iov_len;
842		error = copyout(&iov32, &iovp[i], sizeof(iov32));
843		if (error)
844			return (error);
845	}
846	return (0);
847}
848
849
850struct msghdr32 {
851	u_int32_t	 msg_name;
852	socklen_t	 msg_namelen;
853	u_int32_t	 msg_iov;
854	int		 msg_iovlen;
855	u_int32_t	 msg_control;
856	socklen_t	 msg_controllen;
857	int		 msg_flags;
858};
859CTASSERT(sizeof(struct msghdr32) == 28);
860
861static int
862freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
863{
864	struct msghdr32 m32;
865	int error;
866
867	error = copyin(msg32, &m32, sizeof(m32));
868	if (error)
869		return (error);
870	msg->msg_name = PTRIN(m32.msg_name);
871	msg->msg_namelen = m32.msg_namelen;
872	msg->msg_iov = PTRIN(m32.msg_iov);
873	msg->msg_iovlen = m32.msg_iovlen;
874	msg->msg_control = PTRIN(m32.msg_control);
875	msg->msg_controllen = m32.msg_controllen;
876	msg->msg_flags = m32.msg_flags;
877	return (0);
878}
879
880static int
881freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
882{
883	struct msghdr32 m32;
884	int error;
885
886	m32.msg_name = PTROUT(msg->msg_name);
887	m32.msg_namelen = msg->msg_namelen;
888	m32.msg_iov = PTROUT(msg->msg_iov);
889	m32.msg_iovlen = msg->msg_iovlen;
890	m32.msg_control = PTROUT(msg->msg_control);
891	m32.msg_controllen = msg->msg_controllen;
892	m32.msg_flags = msg->msg_flags;
893	error = copyout(&m32, msg32, sizeof(m32));
894	return (error);
895}
896
897#define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
898#define FREEBSD32_ALIGN(p)	\
899	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
900#define	FREEBSD32_CMSG_SPACE(l)	\
901	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
902
903#define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
904				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
905static int
906freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
907{
908	struct cmsghdr *cm;
909	void *data;
910	socklen_t clen, datalen;
911	int error;
912	caddr_t ctlbuf;
913	int len, maxlen, copylen;
914	struct mbuf *m;
915	error = 0;
916
917	len    = msg->msg_controllen;
918	maxlen = msg->msg_controllen;
919	msg->msg_controllen = 0;
920
921	m = control;
922	ctlbuf = msg->msg_control;
923
924	while (m && len > 0) {
925		cm = mtod(m, struct cmsghdr *);
926		clen = m->m_len;
927
928		while (cm != NULL) {
929
930			if (sizeof(struct cmsghdr) > clen ||
931			    cm->cmsg_len > clen) {
932				error = EINVAL;
933				break;
934			}
935
936			data   = CMSG_DATA(cm);
937			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
938
939			/* Adjust message length */
940			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
941			    datalen;
942
943
944			/* Copy cmsghdr */
945			copylen = sizeof(struct cmsghdr);
946			if (len < copylen) {
947				msg->msg_flags |= MSG_CTRUNC;
948				copylen = len;
949			}
950
951			error = copyout(cm,ctlbuf,copylen);
952			if (error)
953				goto exit;
954
955			ctlbuf += FREEBSD32_ALIGN(copylen);
956			len    -= FREEBSD32_ALIGN(copylen);
957
958			if (len <= 0)
959				break;
960
961			/* Copy data */
962			copylen = datalen;
963			if (len < copylen) {
964				msg->msg_flags |= MSG_CTRUNC;
965				copylen = len;
966			}
967
968			error = copyout(data,ctlbuf,copylen);
969			if (error)
970				goto exit;
971
972			ctlbuf += FREEBSD32_ALIGN(copylen);
973			len    -= FREEBSD32_ALIGN(copylen);
974
975			if (CMSG_SPACE(datalen) < clen) {
976				clen -= CMSG_SPACE(datalen);
977				cm = (struct cmsghdr *)
978					((caddr_t)cm + CMSG_SPACE(datalen));
979			} else {
980				clen = 0;
981				cm = NULL;
982			}
983		}
984		m = m->m_next;
985	}
986
987	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
988
989exit:
990	return (error);
991
992}
993
994int
995freebsd32_recvmsg(td, uap)
996	struct thread *td;
997	struct freebsd32_recvmsg_args /* {
998		int	s;
999		struct	msghdr32 *msg;
1000		int	flags;
1001	} */ *uap;
1002{
1003	struct msghdr msg;
1004	struct msghdr32 m32;
1005	struct iovec *uiov, *iov;
1006	struct mbuf *control = NULL;
1007	struct mbuf **controlp;
1008
1009	int error;
1010	error = copyin(uap->msg, &m32, sizeof(m32));
1011	if (error)
1012		return (error);
1013	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1014	if (error)
1015		return (error);
1016	error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov,
1017	    m32.msg_iovlen, &iov, EMSGSIZE);
1018	if (error)
1019		return (error);
1020	msg.msg_flags = uap->flags;
1021	uiov = msg.msg_iov;
1022	msg.msg_iov = iov;
1023
1024	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1025	error = kern_recvit(td, uap->s, &msg, NULL, UIO_USERSPACE, controlp);
1026	if (error == 0) {
1027		msg.msg_iov = uiov;
1028
1029		if (control != NULL)
1030			error = freebsd32_copy_msg_out(&msg, control);
1031
1032		if (error == 0)
1033			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1034
1035		if (error == 0)
1036			error = freebsd32_copyoutiov(iov, m32.msg_iovlen,
1037			    (struct iovec32 *)(uintptr_t)m32.msg_iov, EMSGSIZE);
1038	}
1039	free(iov, M_IOV);
1040
1041	if (control != NULL)
1042		m_freem(control);
1043
1044	return (error);
1045}
1046
1047
1048static int
1049freebsd32_convert_msg_in(struct mbuf **controlp)
1050{
1051	struct mbuf *control = *controlp;
1052	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1053	void *data;
1054	socklen_t clen = control->m_len, datalen;
1055	int error;
1056
1057	error = 0;
1058	*controlp = NULL;
1059
1060	while (cm != NULL) {
1061		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1062			error = EINVAL;
1063			break;
1064		}
1065
1066		data = FREEBSD32_CMSG_DATA(cm);
1067		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1068
1069		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1070		    cm->cmsg_level);
1071		controlp = &(*controlp)->m_next;
1072
1073		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1074			clen -= FREEBSD32_CMSG_SPACE(datalen);
1075			cm = (struct cmsghdr *)
1076				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1077		} else {
1078			clen = 0;
1079			cm = NULL;
1080		}
1081	}
1082
1083	m_freem(control);
1084	return (error);
1085}
1086
1087
1088int
1089freebsd32_sendmsg(struct thread *td,
1090		  struct freebsd32_sendmsg_args *uap)
1091{
1092	struct msghdr msg;
1093	struct msghdr32 m32;
1094	struct iovec *iov;
1095	struct mbuf *control = NULL;
1096	struct sockaddr *to = NULL;
1097	int error;
1098
1099	error = copyin(uap->msg, &m32, sizeof(m32));
1100	if (error)
1101		return (error);
1102	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1103	if (error)
1104		return (error);
1105	error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov,
1106	    m32.msg_iovlen, &iov, EMSGSIZE);
1107	if (error)
1108		return (error);
1109	msg.msg_iov = iov;
1110	if (msg.msg_name != NULL) {
1111		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1112		if (error) {
1113			to = NULL;
1114			goto out;
1115		}
1116		msg.msg_name = to;
1117	}
1118
1119	if (msg.msg_control) {
1120		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1121			error = EINVAL;
1122			goto out;
1123		}
1124
1125		error = sockargs(&control, msg.msg_control,
1126		    msg.msg_controllen, MT_CONTROL);
1127		if (error)
1128			goto out;
1129
1130		error = freebsd32_convert_msg_in(&control);
1131		if (error)
1132			goto out;
1133	}
1134
1135	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1136	    UIO_USERSPACE);
1137
1138out:
1139	free(iov, M_IOV);
1140	if (to)
1141		free(to, M_SONAME);
1142	return (error);
1143}
1144
1145int
1146freebsd32_recvfrom(struct thread *td,
1147		   struct freebsd32_recvfrom_args *uap)
1148{
1149	struct msghdr msg;
1150	struct iovec aiov;
1151	int error;
1152
1153	if (uap->fromlenaddr) {
1154		error = copyin((void *)(uintptr_t)uap->fromlenaddr,
1155		    &msg.msg_namelen, sizeof(msg.msg_namelen));
1156		if (error)
1157			return (error);
1158	} else {
1159		msg.msg_namelen = 0;
1160	}
1161
1162	msg.msg_name = (void *)(uintptr_t)uap->from;
1163	msg.msg_iov = &aiov;
1164	msg.msg_iovlen = 1;
1165	aiov.iov_base = (void *)(uintptr_t)uap->buf;
1166	aiov.iov_len = uap->len;
1167	msg.msg_control = 0;
1168	msg.msg_flags = uap->flags;
1169	error = kern_recvit(td, uap->s, &msg,
1170	    (void *)(uintptr_t)uap->fromlenaddr, UIO_USERSPACE, NULL);
1171	return (error);
1172}
1173
1174int
1175freebsd32_settimeofday(struct thread *td,
1176		       struct freebsd32_settimeofday_args *uap)
1177{
1178	struct timeval32 tv32;
1179	struct timeval tv, *tvp;
1180	struct timezone tz, *tzp;
1181	int error;
1182
1183	if (uap->tv) {
1184		error = copyin(uap->tv, &tv32, sizeof(tv32));
1185		if (error)
1186			return (error);
1187		CP(tv32, tv, tv_sec);
1188		CP(tv32, tv, tv_usec);
1189		tvp = &tv;
1190	} else
1191		tvp = NULL;
1192	if (uap->tzp) {
1193		error = copyin(uap->tzp, &tz, sizeof(tz));
1194		if (error)
1195			return (error);
1196		tzp = &tz;
1197	} else
1198		tzp = NULL;
1199	return (kern_settimeofday(td, tvp, tzp));
1200}
1201
1202int
1203freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1204{
1205	struct timeval32 s32[2];
1206	struct timeval s[2], *sp;
1207	int error;
1208
1209	if (uap->tptr != NULL) {
1210		error = copyin(uap->tptr, s32, sizeof(s32));
1211		if (error)
1212			return (error);
1213		CP(s32[0], s[0], tv_sec);
1214		CP(s32[0], s[0], tv_usec);
1215		CP(s32[1], s[1], tv_sec);
1216		CP(s32[1], s[1], tv_usec);
1217		sp = s;
1218	} else
1219		sp = NULL;
1220	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1221}
1222
1223int
1224freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1225{
1226	struct timeval32 tv32;
1227	struct timeval delta, olddelta, *deltap;
1228	int error;
1229
1230	if (uap->delta) {
1231		error = copyin(uap->delta, &tv32, sizeof(tv32));
1232		if (error)
1233			return (error);
1234		CP(tv32, delta, tv_sec);
1235		CP(tv32, delta, tv_usec);
1236		deltap = &delta;
1237	} else
1238		deltap = NULL;
1239	error = kern_adjtime(td, deltap, &olddelta);
1240	if (uap->olddelta && error == 0) {
1241		CP(olddelta, tv32, tv_sec);
1242		CP(olddelta, tv32, tv_usec);
1243		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1244	}
1245	return (error);
1246}
1247
1248#ifdef COMPAT_FREEBSD4
1249int
1250freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1251{
1252	struct statfs32 s32;
1253	struct statfs s;
1254	int error;
1255
1256	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1257	if (error)
1258		return (error);
1259	copy_statfs(&s, &s32);
1260	return (copyout(&s32, uap->buf, sizeof(s32)));
1261}
1262#endif
1263
1264#ifdef COMPAT_FREEBSD4
1265int
1266freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1267{
1268	struct statfs32 s32;
1269	struct statfs s;
1270	int error;
1271
1272	error = kern_fstatfs(td, uap->fd, &s);
1273	if (error)
1274		return (error);
1275	copy_statfs(&s, &s32);
1276	return (copyout(&s32, uap->buf, sizeof(s32)));
1277}
1278#endif
1279
1280#ifdef COMPAT_FREEBSD4
1281int
1282freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1283{
1284	struct statfs32 s32;
1285	struct statfs s;
1286	fhandle_t fh;
1287	int error;
1288
1289	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1290		return (error);
1291	error = kern_fhstatfs(td, fh, &s);
1292	if (error)
1293		return (error);
1294	copy_statfs(&s, &s32);
1295	return (copyout(&s32, uap->buf, sizeof(s32)));
1296}
1297#endif
1298
1299int
1300freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1301{
1302	/*
1303	 * Vector through to semsys if it is loaded.
1304	 */
1305	return sysent[SYS_semsys].sy_call(td, uap);
1306}
1307
1308int
1309freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1310{
1311	/*
1312	 * Vector through to msgsys if it is loaded.
1313	 */
1314	return sysent[SYS_msgsys].sy_call(td, uap);
1315}
1316
1317int
1318freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1319{
1320	/*
1321	 * Vector through to shmsys if it is loaded.
1322	 */
1323	return sysent[SYS_shmsys].sy_call(td, uap);
1324}
1325
1326int
1327freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1328{
1329	struct pread_args ap;
1330
1331	ap.fd = uap->fd;
1332	ap.buf = uap->buf;
1333	ap.nbyte = uap->nbyte;
1334	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1335	return (pread(td, &ap));
1336}
1337
1338int
1339freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1340{
1341	struct pwrite_args ap;
1342
1343	ap.fd = uap->fd;
1344	ap.buf = uap->buf;
1345	ap.nbyte = uap->nbyte;
1346	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1347	return (pwrite(td, &ap));
1348}
1349
1350int
1351freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1352{
1353	int error;
1354	struct lseek_args ap;
1355	off_t pos;
1356
1357	ap.fd = uap->fd;
1358	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1359	ap.whence = uap->whence;
1360	error = lseek(td, &ap);
1361	/* Expand the quad return into two parts for eax and edx */
1362	pos = *(off_t *)(td->td_retval);
1363	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1364	td->td_retval[1] = pos >> 32;		/* %edx */
1365	return error;
1366}
1367
1368int
1369freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1370{
1371	struct truncate_args ap;
1372
1373	ap.path = uap->path;
1374	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1375	return (truncate(td, &ap));
1376}
1377
1378int
1379freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1380{
1381	struct ftruncate_args ap;
1382
1383	ap.fd = uap->fd;
1384	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1385	return (ftruncate(td, &ap));
1386}
1387
1388#ifdef COMPAT_FREEBSD4
1389int
1390freebsd4_freebsd32_sendfile(struct thread *td,
1391    struct freebsd4_freebsd32_sendfile_args *uap)
1392{
1393	struct freebsd4_sendfile_args ap;
1394
1395	ap.fd = uap->fd;
1396	ap.s = uap->s;
1397	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1398	ap.nbytes = uap->nbytes;	/* XXX check */
1399	ap.hdtr = uap->hdtr;		/* XXX check */
1400	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1401	ap.flags = uap->flags;
1402	return (freebsd4_sendfile(td, &ap));
1403}
1404#endif
1405
1406int
1407freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1408{
1409	struct sendfile_args ap;
1410
1411	ap.fd = uap->fd;
1412	ap.s = uap->s;
1413	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1414	ap.nbytes = uap->nbytes;	/* XXX check */
1415	ap.hdtr = uap->hdtr;		/* XXX check */
1416	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1417	ap.flags = uap->flags;
1418	return (sendfile(td, &ap));
1419}
1420
1421struct stat32 {
1422	dev_t	st_dev;
1423	ino_t	st_ino;
1424	mode_t	st_mode;
1425	nlink_t	st_nlink;
1426	uid_t	st_uid;
1427	gid_t	st_gid;
1428	dev_t	st_rdev;
1429	struct timespec32 st_atimespec;
1430	struct timespec32 st_mtimespec;
1431	struct timespec32 st_ctimespec;
1432	off_t	st_size;
1433	int64_t	st_blocks;
1434	u_int32_t st_blksize;
1435	u_int32_t st_flags;
1436	u_int32_t st_gen;
1437	struct timespec32 st_birthtimespec;
1438	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1439	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1440};
1441
1442
1443CTASSERT(sizeof(struct stat32) == 96);
1444
1445static void
1446copy_stat( struct stat *in, struct stat32 *out)
1447{
1448	CP(*in, *out, st_dev);
1449	CP(*in, *out, st_ino);
1450	CP(*in, *out, st_mode);
1451	CP(*in, *out, st_nlink);
1452	CP(*in, *out, st_uid);
1453	CP(*in, *out, st_gid);
1454	CP(*in, *out, st_rdev);
1455	TS_CP(*in, *out, st_atimespec);
1456	TS_CP(*in, *out, st_mtimespec);
1457	TS_CP(*in, *out, st_ctimespec);
1458	CP(*in, *out, st_size);
1459	CP(*in, *out, st_blocks);
1460	CP(*in, *out, st_blksize);
1461	CP(*in, *out, st_flags);
1462	CP(*in, *out, st_gen);
1463}
1464
1465int
1466freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1467{
1468	struct stat sb;
1469	struct stat32 sb32;
1470	int error;
1471
1472	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1473	if (error)
1474		return (error);
1475	copy_stat(&sb, &sb32);
1476	error = copyout(&sb32, uap->ub, sizeof (sb32));
1477	return (error);
1478}
1479
1480int
1481freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1482{
1483	struct stat ub;
1484	struct stat32 ub32;
1485	int error;
1486
1487	error = kern_fstat(td, uap->fd, &ub);
1488	if (error)
1489		return (error);
1490	copy_stat(&ub, &ub32);
1491	error = copyout(&ub32, uap->ub, sizeof(ub32));
1492	return (error);
1493}
1494
1495int
1496freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1497{
1498	struct stat sb;
1499	struct stat32 sb32;
1500	int error;
1501
1502	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1503	if (error)
1504		return (error);
1505	copy_stat(&sb, &sb32);
1506	error = copyout(&sb32, uap->ub, sizeof (sb32));
1507	return (error);
1508}
1509
1510/*
1511 * MPSAFE
1512 */
1513int
1514freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1515{
1516	int error, name[CTL_MAXNAME];
1517	size_t j, oldlen;
1518
1519	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1520		return (EINVAL);
1521 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1522 	if (error)
1523		return (error);
1524	mtx_lock(&Giant);
1525	if (uap->oldlenp)
1526		oldlen = fuword32(uap->oldlenp);
1527	else
1528		oldlen = 0;
1529	error = userland_sysctl(td, name, uap->namelen,
1530		uap->old, &oldlen, 1,
1531		uap->new, uap->newlen, &j, SCTL_MASK32);
1532	if (error && error != ENOMEM)
1533		goto done2;
1534	if (uap->oldlenp)
1535		suword32(uap->oldlenp, j);
1536done2:
1537	mtx_unlock(&Giant);
1538	return (error);
1539}
1540
1541struct sigaction32 {
1542	u_int32_t	sa_u;
1543	int		sa_flags;
1544	sigset_t	sa_mask;
1545};
1546
1547CTASSERT(sizeof(struct sigaction32) == 24);
1548
1549int
1550freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1551{
1552	struct sigaction32 s32;
1553	struct sigaction sa, osa, *sap;
1554	int error;
1555
1556	if (uap->act) {
1557		error = copyin(uap->act, &s32, sizeof(s32));
1558		if (error)
1559			return (error);
1560		sa.sa_handler = PTRIN(s32.sa_u);
1561		CP(s32, sa, sa_flags);
1562		CP(s32, sa, sa_mask);
1563		sap = &sa;
1564	} else
1565		sap = NULL;
1566	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1567	if (error == 0 && uap->oact != NULL) {
1568		s32.sa_u = PTROUT(osa.sa_handler);
1569		CP(osa, s32, sa_flags);
1570		CP(osa, s32, sa_mask);
1571		error = copyout(&s32, uap->oact, sizeof(s32));
1572	}
1573	return (error);
1574}
1575
1576#ifdef COMPAT_FREEBSD4
1577int
1578freebsd4_freebsd32_sigaction(struct thread *td,
1579			     struct freebsd4_freebsd32_sigaction_args *uap)
1580{
1581	struct sigaction32 s32;
1582	struct sigaction sa, osa, *sap;
1583	int error;
1584
1585	if (uap->act) {
1586		error = copyin(uap->act, &s32, sizeof(s32));
1587		if (error)
1588			return (error);
1589		sa.sa_handler = PTRIN(s32.sa_u);
1590		CP(s32, sa, sa_flags);
1591		CP(s32, sa, sa_mask);
1592		sap = &sa;
1593	} else
1594		sap = NULL;
1595	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1596	if (error == 0 && uap->oact != NULL) {
1597		s32.sa_u = PTROUT(osa.sa_handler);
1598		CP(osa, s32, sa_flags);
1599		CP(osa, s32, sa_mask);
1600		error = copyout(&s32, uap->oact, sizeof(s32));
1601	}
1602	return (error);
1603}
1604#endif
1605
1606#ifdef COMPAT_43
1607struct osigaction32 {
1608	u_int32_t	sa_u;
1609	osigset_t	sa_mask;
1610	int		sa_flags;
1611};
1612
1613#define	ONSIG	32
1614
1615int
1616ofreebsd32_sigaction(struct thread *td,
1617			     struct ofreebsd32_sigaction_args *uap)
1618{
1619	struct osigaction32 s32;
1620	struct sigaction sa, osa, *sap;
1621	int error;
1622
1623	if (uap->signum <= 0 || uap->signum >= ONSIG)
1624		return (EINVAL);
1625
1626	if (uap->nsa) {
1627		error = copyin(uap->nsa, &s32, sizeof(s32));
1628		if (error)
1629			return (error);
1630		sa.sa_handler = PTRIN(s32.sa_u);
1631		CP(s32, sa, sa_flags);
1632		OSIG2SIG(s32.sa_mask, sa.sa_mask);
1633		sap = &sa;
1634	} else
1635		sap = NULL;
1636	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1637	if (error == 0 && uap->osa != NULL) {
1638		s32.sa_u = PTROUT(osa.sa_handler);
1639		CP(osa, s32, sa_flags);
1640		SIG2OSIG(osa.sa_mask, s32.sa_mask);
1641		error = copyout(&s32, uap->osa, sizeof(s32));
1642	}
1643	return (error);
1644}
1645
1646int
1647ofreebsd32_sigprocmask(struct thread *td,
1648			       struct ofreebsd32_sigprocmask_args *uap)
1649{
1650	sigset_t set, oset;
1651	int error;
1652
1653	OSIG2SIG(uap->mask, set);
1654	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
1655	SIG2OSIG(oset, td->td_retval[0]);
1656	return (error);
1657}
1658
1659int
1660ofreebsd32_sigpending(struct thread *td,
1661			      struct ofreebsd32_sigpending_args *uap)
1662{
1663	struct proc *p = td->td_proc;
1664	sigset_t siglist;
1665
1666	PROC_LOCK(p);
1667	siglist = p->p_siglist;
1668	SIGSETOR(siglist, td->td_siglist);
1669	PROC_UNLOCK(p);
1670	SIG2OSIG(siglist, td->td_retval[0]);
1671	return (0);
1672}
1673
1674struct sigvec32 {
1675	u_int32_t	sv_handler;
1676	int		sv_mask;
1677	int		sv_flags;
1678};
1679
1680int
1681ofreebsd32_sigvec(struct thread *td,
1682			  struct ofreebsd32_sigvec_args *uap)
1683{
1684	struct sigvec32 vec;
1685	struct sigaction sa, osa, *sap;
1686	int error;
1687
1688	if (uap->signum <= 0 || uap->signum >= ONSIG)
1689		return (EINVAL);
1690
1691	if (uap->nsv) {
1692		error = copyin(uap->nsv, &vec, sizeof(vec));
1693		if (error)
1694			return (error);
1695		sa.sa_handler = PTRIN(vec.sv_handler);
1696		OSIG2SIG(vec.sv_mask, sa.sa_mask);
1697		sa.sa_flags = vec.sv_flags;
1698		sa.sa_flags ^= SA_RESTART;
1699		sap = &sa;
1700	} else
1701		sap = NULL;
1702	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1703	if (error == 0 && uap->osv != NULL) {
1704		vec.sv_handler = PTROUT(osa.sa_handler);
1705		SIG2OSIG(osa.sa_mask, vec.sv_mask);
1706		vec.sv_flags = osa.sa_flags;
1707		vec.sv_flags &= ~SA_NOCLDWAIT;
1708		vec.sv_flags ^= SA_RESTART;
1709		error = copyout(&vec, uap->osv, sizeof(vec));
1710	}
1711	return (error);
1712}
1713
1714int
1715ofreebsd32_sigblock(struct thread *td,
1716			    struct ofreebsd32_sigblock_args *uap)
1717{
1718	struct proc *p = td->td_proc;
1719	sigset_t set;
1720
1721	OSIG2SIG(uap->mask, set);
1722	SIG_CANTMASK(set);
1723	PROC_LOCK(p);
1724	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1725	SIGSETOR(td->td_sigmask, set);
1726	PROC_UNLOCK(p);
1727	return (0);
1728}
1729
1730int
1731ofreebsd32_sigsetmask(struct thread *td,
1732			      struct ofreebsd32_sigsetmask_args *uap)
1733{
1734	struct proc *p = td->td_proc;
1735	sigset_t set;
1736
1737	OSIG2SIG(uap->mask, set);
1738	SIG_CANTMASK(set);
1739	PROC_LOCK(p);
1740	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1741	SIGSETLO(td->td_sigmask, set);
1742	signotify(td);
1743	PROC_UNLOCK(p);
1744	return (0);
1745}
1746
1747int
1748ofreebsd32_sigsuspend(struct thread *td,
1749			      struct ofreebsd32_sigsuspend_args *uap)
1750{
1751	struct proc *p = td->td_proc;
1752	sigset_t mask;
1753
1754	PROC_LOCK(p);
1755	td->td_oldsigmask = td->td_sigmask;
1756	td->td_pflags |= TDP_OLDMASK;
1757	OSIG2SIG(uap->mask, mask);
1758	SIG_CANTMASK(mask);
1759	SIGSETLO(td->td_sigmask, mask);
1760	signotify(td);
1761	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
1762		/* void */;
1763	PROC_UNLOCK(p);
1764	/* always return EINTR rather than ERESTART... */
1765	return (EINTR);
1766}
1767
1768struct sigstack32 {
1769	u_int32_t	ss_sp;
1770	int		ss_onstack;
1771};
1772
1773int
1774ofreebsd32_sigstack(struct thread *td,
1775			    struct ofreebsd32_sigstack_args *uap)
1776{
1777	struct sigstack32 s32;
1778	struct sigstack nss, oss;
1779	int error = 0;
1780
1781	if (uap->nss != NULL) {
1782		error = copyin(uap->nss, &s32, sizeof(s32));
1783		if (error)
1784			return (error);
1785		nss.ss_sp = PTRIN(s32.ss_sp);
1786		CP(s32, nss, ss_onstack);
1787	}
1788	oss.ss_sp = td->td_sigstk.ss_sp;
1789	oss.ss_onstack = sigonstack(cpu_getstack(td));
1790	if (uap->nss != NULL) {
1791		td->td_sigstk.ss_sp = nss.ss_sp;
1792		td->td_sigstk.ss_size = 0;
1793		td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK;
1794		td->td_pflags |= TDP_ALTSTACK;
1795	}
1796	if (uap->oss != NULL) {
1797		s32.ss_sp = PTROUT(oss.ss_sp);
1798		CP(oss, s32, ss_onstack);
1799		error = copyout(&s32, uap->oss, sizeof(s32));
1800	}
1801	return (error);
1802}
1803#endif
1804
1805int
1806freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1807{
1808	struct timespec32 rmt32, rqt32;
1809	struct timespec rmt, rqt;
1810	int error;
1811
1812	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
1813	if (error)
1814		return (error);
1815
1816	CP(rqt32, rqt, tv_sec);
1817	CP(rqt32, rqt, tv_nsec);
1818
1819	if (uap->rmtp &&
1820	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1821		return (EFAULT);
1822	error = kern_nanosleep(td, &rqt, &rmt);
1823	if (error && uap->rmtp) {
1824		int error2;
1825
1826		CP(rmt, rmt32, tv_sec);
1827		CP(rmt, rmt32, tv_nsec);
1828
1829		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
1830		if (error2)
1831			error = error2;
1832	}
1833	return (error);
1834}
1835
1836int
1837freebsd32_clock_gettime(struct thread *td,
1838			struct freebsd32_clock_gettime_args *uap)
1839{
1840	struct timespec	ats;
1841	struct timespec32 ats32;
1842	int error;
1843
1844	error = kern_clock_gettime(td, uap->clock_id, &ats);
1845	if (error == 0) {
1846		CP(ats, ats32, tv_sec);
1847		CP(ats, ats32, tv_nsec);
1848		error = copyout(&ats32, uap->tp, sizeof(ats32));
1849	}
1850	return (error);
1851}
1852
1853int
1854freebsd32_clock_settime(struct thread *td,
1855			struct freebsd32_clock_settime_args *uap)
1856{
1857	struct timespec	ats;
1858	struct timespec32 ats32;
1859	int error;
1860
1861	error = copyin(uap->tp, &ats32, sizeof(ats32));
1862	if (error)
1863		return (error);
1864	CP(ats32, ats, tv_sec);
1865	CP(ats32, ats, tv_nsec);
1866
1867	return (kern_clock_settime(td, uap->clock_id, &ats));
1868}
1869
1870int
1871freebsd32_clock_getres(struct thread *td,
1872		       struct freebsd32_clock_getres_args *uap)
1873{
1874	struct timespec	ts;
1875	struct timespec32 ts32;
1876	int error;
1877
1878	if (uap->tp == NULL)
1879		return (0);
1880	error = kern_clock_getres(td, uap->clock_id, &ts);
1881	if (error == 0) {
1882		CP(ts, ts32, tv_sec);
1883		CP(ts, ts32, tv_nsec);
1884		error = copyout(&ts32, uap->tp, sizeof(ts32));
1885	}
1886	return (error);
1887}
1888
1889#if 0
1890
1891int
1892freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1893{
1894	int error;
1895	struct yyy32 *p32, s32;
1896	struct yyy *p = NULL, s;
1897
1898	if (uap->zzz) {
1899		error = copyin(uap->zzz, &s32, sizeof(s32));
1900		if (error)
1901			return (error);
1902		/* translate in */
1903		p = &s;
1904	}
1905	error = kern_xxx(td, p);
1906	if (error)
1907		return (error);
1908	if (uap->zzz) {
1909		/* translate out */
1910		error = copyout(&s32, p32, sizeof(s32));
1911	}
1912	return (error);
1913}
1914
1915#endif
1916