freebsd32_misc.c revision 153247
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 153247 2005-12-08 22:14:25Z ambrisko $");
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_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1225{
1226	struct timeval32 s32[2];
1227	struct timeval s[2], *sp;
1228	int error;
1229
1230	if (uap->tptr != NULL) {
1231		error = copyin(uap->tptr, s32, sizeof(s32));
1232		if (error)
1233			return (error);
1234		CP(s32[0], s[0], tv_sec);
1235		CP(s32[0], s[0], tv_usec);
1236		CP(s32[1], s[1], tv_sec);
1237		CP(s32[1], s[1], tv_usec);
1238		sp = s;
1239	} else
1240		sp = NULL;
1241	return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1242}
1243
1244
1245int
1246freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1247{
1248	struct timeval32 tv32;
1249	struct timeval delta, olddelta, *deltap;
1250	int error;
1251
1252	if (uap->delta) {
1253		error = copyin(uap->delta, &tv32, sizeof(tv32));
1254		if (error)
1255			return (error);
1256		CP(tv32, delta, tv_sec);
1257		CP(tv32, delta, tv_usec);
1258		deltap = &delta;
1259	} else
1260		deltap = NULL;
1261	error = kern_adjtime(td, deltap, &olddelta);
1262	if (uap->olddelta && error == 0) {
1263		CP(olddelta, tv32, tv_sec);
1264		CP(olddelta, tv32, tv_usec);
1265		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1266	}
1267	return (error);
1268}
1269
1270#ifdef COMPAT_FREEBSD4
1271int
1272freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1273{
1274	struct statfs32 s32;
1275	struct statfs s;
1276	int error;
1277
1278	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1279	if (error)
1280		return (error);
1281	copy_statfs(&s, &s32);
1282	return (copyout(&s32, uap->buf, sizeof(s32)));
1283}
1284#endif
1285
1286#ifdef COMPAT_FREEBSD4
1287int
1288freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1289{
1290	struct statfs32 s32;
1291	struct statfs s;
1292	int error;
1293
1294	error = kern_fstatfs(td, uap->fd, &s);
1295	if (error)
1296		return (error);
1297	copy_statfs(&s, &s32);
1298	return (copyout(&s32, uap->buf, sizeof(s32)));
1299}
1300#endif
1301
1302#ifdef COMPAT_FREEBSD4
1303int
1304freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1305{
1306	struct statfs32 s32;
1307	struct statfs s;
1308	fhandle_t fh;
1309	int error;
1310
1311	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1312		return (error);
1313	error = kern_fhstatfs(td, fh, &s);
1314	if (error)
1315		return (error);
1316	copy_statfs(&s, &s32);
1317	return (copyout(&s32, uap->buf, sizeof(s32)));
1318}
1319#endif
1320
1321int
1322freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1323{
1324	/*
1325	 * Vector through to semsys if it is loaded.
1326	 */
1327	return sysent[SYS_semsys].sy_call(td, uap);
1328}
1329
1330int
1331freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1332{
1333	/*
1334	 * Vector through to msgsys if it is loaded.
1335	 */
1336	return sysent[SYS_msgsys].sy_call(td, uap);
1337}
1338
1339int
1340freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1341{
1342	/*
1343	 * Vector through to shmsys if it is loaded.
1344	 */
1345	return sysent[SYS_shmsys].sy_call(td, uap);
1346}
1347
1348int
1349freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1350{
1351	struct pread_args ap;
1352
1353	ap.fd = uap->fd;
1354	ap.buf = uap->buf;
1355	ap.nbyte = uap->nbyte;
1356	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1357	return (pread(td, &ap));
1358}
1359
1360int
1361freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1362{
1363	struct pwrite_args ap;
1364
1365	ap.fd = uap->fd;
1366	ap.buf = uap->buf;
1367	ap.nbyte = uap->nbyte;
1368	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1369	return (pwrite(td, &ap));
1370}
1371
1372int
1373freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1374{
1375	int error;
1376	struct lseek_args ap;
1377	off_t pos;
1378
1379	ap.fd = uap->fd;
1380	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1381	ap.whence = uap->whence;
1382	error = lseek(td, &ap);
1383	/* Expand the quad return into two parts for eax and edx */
1384	pos = *(off_t *)(td->td_retval);
1385	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1386	td->td_retval[1] = pos >> 32;		/* %edx */
1387	return error;
1388}
1389
1390int
1391freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1392{
1393	struct truncate_args ap;
1394
1395	ap.path = uap->path;
1396	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1397	return (truncate(td, &ap));
1398}
1399
1400int
1401freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1402{
1403	struct ftruncate_args ap;
1404
1405	ap.fd = uap->fd;
1406	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1407	return (ftruncate(td, &ap));
1408}
1409
1410#ifdef COMPAT_FREEBSD4
1411int
1412freebsd4_freebsd32_sendfile(struct thread *td,
1413    struct freebsd4_freebsd32_sendfile_args *uap)
1414{
1415	struct freebsd4_sendfile_args ap;
1416
1417	ap.fd = uap->fd;
1418	ap.s = uap->s;
1419	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1420	ap.nbytes = uap->nbytes;	/* XXX check */
1421	ap.hdtr = uap->hdtr;		/* XXX check */
1422	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1423	ap.flags = uap->flags;
1424	return (freebsd4_sendfile(td, &ap));
1425}
1426#endif
1427
1428int
1429freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1430{
1431	struct sendfile_args ap;
1432
1433	ap.fd = uap->fd;
1434	ap.s = uap->s;
1435	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1436	ap.nbytes = uap->nbytes;	/* XXX check */
1437	ap.hdtr = uap->hdtr;		/* XXX check */
1438	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1439	ap.flags = uap->flags;
1440	return (sendfile(td, &ap));
1441}
1442
1443struct stat32 {
1444	dev_t	st_dev;
1445	ino_t	st_ino;
1446	mode_t	st_mode;
1447	nlink_t	st_nlink;
1448	uid_t	st_uid;
1449	gid_t	st_gid;
1450	dev_t	st_rdev;
1451	struct timespec32 st_atimespec;
1452	struct timespec32 st_mtimespec;
1453	struct timespec32 st_ctimespec;
1454	off_t	st_size;
1455	int64_t	st_blocks;
1456	u_int32_t st_blksize;
1457	u_int32_t st_flags;
1458	u_int32_t st_gen;
1459	struct timespec32 st_birthtimespec;
1460	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1461	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1462};
1463
1464
1465CTASSERT(sizeof(struct stat32) == 96);
1466
1467static void
1468copy_stat( struct stat *in, struct stat32 *out)
1469{
1470	CP(*in, *out, st_dev);
1471	CP(*in, *out, st_ino);
1472	CP(*in, *out, st_mode);
1473	CP(*in, *out, st_nlink);
1474	CP(*in, *out, st_uid);
1475	CP(*in, *out, st_gid);
1476	CP(*in, *out, st_rdev);
1477	TS_CP(*in, *out, st_atimespec);
1478	TS_CP(*in, *out, st_mtimespec);
1479	TS_CP(*in, *out, st_ctimespec);
1480	CP(*in, *out, st_size);
1481	CP(*in, *out, st_blocks);
1482	CP(*in, *out, st_blksize);
1483	CP(*in, *out, st_flags);
1484	CP(*in, *out, st_gen);
1485}
1486
1487int
1488freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1489{
1490	struct stat sb;
1491	struct stat32 sb32;
1492	int error;
1493
1494	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1495	if (error)
1496		return (error);
1497	copy_stat(&sb, &sb32);
1498	error = copyout(&sb32, uap->ub, sizeof (sb32));
1499	return (error);
1500}
1501
1502int
1503freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1504{
1505	struct stat ub;
1506	struct stat32 ub32;
1507	int error;
1508
1509	error = kern_fstat(td, uap->fd, &ub);
1510	if (error)
1511		return (error);
1512	copy_stat(&ub, &ub32);
1513	error = copyout(&ub32, uap->ub, sizeof(ub32));
1514	return (error);
1515}
1516
1517int
1518freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1519{
1520	struct stat sb;
1521	struct stat32 sb32;
1522	int error;
1523
1524	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1525	if (error)
1526		return (error);
1527	copy_stat(&sb, &sb32);
1528	error = copyout(&sb32, uap->ub, sizeof (sb32));
1529	return (error);
1530}
1531
1532/*
1533 * MPSAFE
1534 */
1535int
1536freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1537{
1538	int error, name[CTL_MAXNAME];
1539	size_t j, oldlen;
1540
1541	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1542		return (EINVAL);
1543 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1544 	if (error)
1545		return (error);
1546	mtx_lock(&Giant);
1547	if (uap->oldlenp)
1548		oldlen = fuword32(uap->oldlenp);
1549	else
1550		oldlen = 0;
1551	error = userland_sysctl(td, name, uap->namelen,
1552		uap->old, &oldlen, 1,
1553		uap->new, uap->newlen, &j, SCTL_MASK32);
1554	if (error && error != ENOMEM)
1555		goto done2;
1556	if (uap->oldlenp)
1557		suword32(uap->oldlenp, j);
1558done2:
1559	mtx_unlock(&Giant);
1560	return (error);
1561}
1562
1563struct sigaction32 {
1564	u_int32_t	sa_u;
1565	int		sa_flags;
1566	sigset_t	sa_mask;
1567};
1568
1569CTASSERT(sizeof(struct sigaction32) == 24);
1570
1571int
1572freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1573{
1574	struct sigaction32 s32;
1575	struct sigaction sa, osa, *sap;
1576	int error;
1577
1578	if (uap->act) {
1579		error = copyin(uap->act, &s32, sizeof(s32));
1580		if (error)
1581			return (error);
1582		sa.sa_handler = PTRIN(s32.sa_u);
1583		CP(s32, sa, sa_flags);
1584		CP(s32, sa, sa_mask);
1585		sap = &sa;
1586	} else
1587		sap = NULL;
1588	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1589	if (error == 0 && uap->oact != NULL) {
1590		s32.sa_u = PTROUT(osa.sa_handler);
1591		CP(osa, s32, sa_flags);
1592		CP(osa, s32, sa_mask);
1593		error = copyout(&s32, uap->oact, sizeof(s32));
1594	}
1595	return (error);
1596}
1597
1598#ifdef COMPAT_FREEBSD4
1599int
1600freebsd4_freebsd32_sigaction(struct thread *td,
1601			     struct freebsd4_freebsd32_sigaction_args *uap)
1602{
1603	struct sigaction32 s32;
1604	struct sigaction sa, osa, *sap;
1605	int error;
1606
1607	if (uap->act) {
1608		error = copyin(uap->act, &s32, sizeof(s32));
1609		if (error)
1610			return (error);
1611		sa.sa_handler = PTRIN(s32.sa_u);
1612		CP(s32, sa, sa_flags);
1613		CP(s32, sa, sa_mask);
1614		sap = &sa;
1615	} else
1616		sap = NULL;
1617	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1618	if (error == 0 && uap->oact != NULL) {
1619		s32.sa_u = PTROUT(osa.sa_handler);
1620		CP(osa, s32, sa_flags);
1621		CP(osa, s32, sa_mask);
1622		error = copyout(&s32, uap->oact, sizeof(s32));
1623	}
1624	return (error);
1625}
1626#endif
1627
1628#ifdef COMPAT_43
1629struct osigaction32 {
1630	u_int32_t	sa_u;
1631	osigset_t	sa_mask;
1632	int		sa_flags;
1633};
1634
1635#define	ONSIG	32
1636
1637int
1638ofreebsd32_sigaction(struct thread *td,
1639			     struct ofreebsd32_sigaction_args *uap)
1640{
1641	struct osigaction32 s32;
1642	struct sigaction sa, osa, *sap;
1643	int error;
1644
1645	if (uap->signum <= 0 || uap->signum >= ONSIG)
1646		return (EINVAL);
1647
1648	if (uap->nsa) {
1649		error = copyin(uap->nsa, &s32, sizeof(s32));
1650		if (error)
1651			return (error);
1652		sa.sa_handler = PTRIN(s32.sa_u);
1653		CP(s32, sa, sa_flags);
1654		OSIG2SIG(s32.sa_mask, sa.sa_mask);
1655		sap = &sa;
1656	} else
1657		sap = NULL;
1658	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1659	if (error == 0 && uap->osa != NULL) {
1660		s32.sa_u = PTROUT(osa.sa_handler);
1661		CP(osa, s32, sa_flags);
1662		SIG2OSIG(osa.sa_mask, s32.sa_mask);
1663		error = copyout(&s32, uap->osa, sizeof(s32));
1664	}
1665	return (error);
1666}
1667
1668int
1669ofreebsd32_sigprocmask(struct thread *td,
1670			       struct ofreebsd32_sigprocmask_args *uap)
1671{
1672	sigset_t set, oset;
1673	int error;
1674
1675	OSIG2SIG(uap->mask, set);
1676	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
1677	SIG2OSIG(oset, td->td_retval[0]);
1678	return (error);
1679}
1680
1681int
1682ofreebsd32_sigpending(struct thread *td,
1683			      struct ofreebsd32_sigpending_args *uap)
1684{
1685	struct proc *p = td->td_proc;
1686	sigset_t siglist;
1687
1688	PROC_LOCK(p);
1689	siglist = p->p_siglist;
1690	SIGSETOR(siglist, td->td_siglist);
1691	PROC_UNLOCK(p);
1692	SIG2OSIG(siglist, td->td_retval[0]);
1693	return (0);
1694}
1695
1696struct sigvec32 {
1697	u_int32_t	sv_handler;
1698	int		sv_mask;
1699	int		sv_flags;
1700};
1701
1702int
1703ofreebsd32_sigvec(struct thread *td,
1704			  struct ofreebsd32_sigvec_args *uap)
1705{
1706	struct sigvec32 vec;
1707	struct sigaction sa, osa, *sap;
1708	int error;
1709
1710	if (uap->signum <= 0 || uap->signum >= ONSIG)
1711		return (EINVAL);
1712
1713	if (uap->nsv) {
1714		error = copyin(uap->nsv, &vec, sizeof(vec));
1715		if (error)
1716			return (error);
1717		sa.sa_handler = PTRIN(vec.sv_handler);
1718		OSIG2SIG(vec.sv_mask, sa.sa_mask);
1719		sa.sa_flags = vec.sv_flags;
1720		sa.sa_flags ^= SA_RESTART;
1721		sap = &sa;
1722	} else
1723		sap = NULL;
1724	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1725	if (error == 0 && uap->osv != NULL) {
1726		vec.sv_handler = PTROUT(osa.sa_handler);
1727		SIG2OSIG(osa.sa_mask, vec.sv_mask);
1728		vec.sv_flags = osa.sa_flags;
1729		vec.sv_flags &= ~SA_NOCLDWAIT;
1730		vec.sv_flags ^= SA_RESTART;
1731		error = copyout(&vec, uap->osv, sizeof(vec));
1732	}
1733	return (error);
1734}
1735
1736int
1737ofreebsd32_sigblock(struct thread *td,
1738			    struct ofreebsd32_sigblock_args *uap)
1739{
1740	struct proc *p = td->td_proc;
1741	sigset_t set;
1742
1743	OSIG2SIG(uap->mask, set);
1744	SIG_CANTMASK(set);
1745	PROC_LOCK(p);
1746	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1747	SIGSETOR(td->td_sigmask, set);
1748	PROC_UNLOCK(p);
1749	return (0);
1750}
1751
1752int
1753ofreebsd32_sigsetmask(struct thread *td,
1754			      struct ofreebsd32_sigsetmask_args *uap)
1755{
1756	struct proc *p = td->td_proc;
1757	sigset_t set;
1758
1759	OSIG2SIG(uap->mask, set);
1760	SIG_CANTMASK(set);
1761	PROC_LOCK(p);
1762	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1763	SIGSETLO(td->td_sigmask, set);
1764	signotify(td);
1765	PROC_UNLOCK(p);
1766	return (0);
1767}
1768
1769int
1770ofreebsd32_sigsuspend(struct thread *td,
1771			      struct ofreebsd32_sigsuspend_args *uap)
1772{
1773	struct proc *p = td->td_proc;
1774	sigset_t mask;
1775
1776	PROC_LOCK(p);
1777	td->td_oldsigmask = td->td_sigmask;
1778	td->td_pflags |= TDP_OLDMASK;
1779	OSIG2SIG(uap->mask, mask);
1780	SIG_CANTMASK(mask);
1781	SIGSETLO(td->td_sigmask, mask);
1782	signotify(td);
1783	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
1784		/* void */;
1785	PROC_UNLOCK(p);
1786	/* always return EINTR rather than ERESTART... */
1787	return (EINTR);
1788}
1789
1790struct sigstack32 {
1791	u_int32_t	ss_sp;
1792	int		ss_onstack;
1793};
1794
1795int
1796ofreebsd32_sigstack(struct thread *td,
1797			    struct ofreebsd32_sigstack_args *uap)
1798{
1799	struct sigstack32 s32;
1800	struct sigstack nss, oss;
1801	int error = 0;
1802
1803	if (uap->nss != NULL) {
1804		error = copyin(uap->nss, &s32, sizeof(s32));
1805		if (error)
1806			return (error);
1807		nss.ss_sp = PTRIN(s32.ss_sp);
1808		CP(s32, nss, ss_onstack);
1809	}
1810	oss.ss_sp = td->td_sigstk.ss_sp;
1811	oss.ss_onstack = sigonstack(cpu_getstack(td));
1812	if (uap->nss != NULL) {
1813		td->td_sigstk.ss_sp = nss.ss_sp;
1814		td->td_sigstk.ss_size = 0;
1815		td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK;
1816		td->td_pflags |= TDP_ALTSTACK;
1817	}
1818	if (uap->oss != NULL) {
1819		s32.ss_sp = PTROUT(oss.ss_sp);
1820		CP(oss, s32, ss_onstack);
1821		error = copyout(&s32, uap->oss, sizeof(s32));
1822	}
1823	return (error);
1824}
1825#endif
1826
1827int
1828freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1829{
1830	struct timespec32 rmt32, rqt32;
1831	struct timespec rmt, rqt;
1832	int error;
1833
1834	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
1835	if (error)
1836		return (error);
1837
1838	CP(rqt32, rqt, tv_sec);
1839	CP(rqt32, rqt, tv_nsec);
1840
1841	if (uap->rmtp &&
1842	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1843		return (EFAULT);
1844	error = kern_nanosleep(td, &rqt, &rmt);
1845	if (error && uap->rmtp) {
1846		int error2;
1847
1848		CP(rmt, rmt32, tv_sec);
1849		CP(rmt, rmt32, tv_nsec);
1850
1851		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
1852		if (error2)
1853			error = error2;
1854	}
1855	return (error);
1856}
1857
1858int
1859freebsd32_clock_gettime(struct thread *td,
1860			struct freebsd32_clock_gettime_args *uap)
1861{
1862	struct timespec	ats;
1863	struct timespec32 ats32;
1864	int error;
1865
1866	error = kern_clock_gettime(td, uap->clock_id, &ats);
1867	if (error == 0) {
1868		CP(ats, ats32, tv_sec);
1869		CP(ats, ats32, tv_nsec);
1870		error = copyout(&ats32, uap->tp, sizeof(ats32));
1871	}
1872	return (error);
1873}
1874
1875int
1876freebsd32_clock_settime(struct thread *td,
1877			struct freebsd32_clock_settime_args *uap)
1878{
1879	struct timespec	ats;
1880	struct timespec32 ats32;
1881	int error;
1882
1883	error = copyin(uap->tp, &ats32, sizeof(ats32));
1884	if (error)
1885		return (error);
1886	CP(ats32, ats, tv_sec);
1887	CP(ats32, ats, tv_nsec);
1888
1889	return (kern_clock_settime(td, uap->clock_id, &ats));
1890}
1891
1892int
1893freebsd32_clock_getres(struct thread *td,
1894		       struct freebsd32_clock_getres_args *uap)
1895{
1896	struct timespec	ts;
1897	struct timespec32 ts32;
1898	int error;
1899
1900	if (uap->tp == NULL)
1901		return (0);
1902	error = kern_clock_getres(td, uap->clock_id, &ts);
1903	if (error == 0) {
1904		CP(ts, ts32, tv_sec);
1905		CP(ts, ts32, tv_nsec);
1906		error = copyout(&ts32, uap->tp, sizeof(ts32));
1907	}
1908	return (error);
1909}
1910
1911#if 0
1912
1913int
1914freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1915{
1916	int error;
1917	struct yyy32 *p32, s32;
1918	struct yyy *p = NULL, s;
1919
1920	if (uap->zzz) {
1921		error = copyin(uap->zzz, &s32, sizeof(s32));
1922		if (error)
1923			return (error);
1924		/* translate in */
1925		p = &s;
1926	}
1927	error = kern_xxx(td, p);
1928	if (error)
1929		return (error);
1930	if (uap->zzz) {
1931		/* translate out */
1932		error = copyout(&s32, p32, sizeof(s32));
1933	}
1934	return (error);
1935}
1936
1937#endif
1938