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