freebsd32_misc.c revision 123744
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 123744 2003-12-23 02:48:11Z peter $");
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/imgact.h>
39#include <sys/kernel.h>
40#include <sys/lock.h>
41#include <sys/malloc.h>
42#include <sys/file.h>		/* Must come after sys/malloc.h */
43#include <sys/mman.h>
44#include <sys/module.h>
45#include <sys/mount.h>
46#include <sys/mutex.h>
47#include <sys/namei.h>
48#include <sys/param.h>
49#include <sys/proc.h>
50#include <sys/reboot.h>
51#include <sys/resource.h>
52#include <sys/resourcevar.h>
53#include <sys/selinfo.h>
54#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
55#include <sys/signal.h>
56#include <sys/signalvar.h>
57#include <sys/socket.h>
58#include <sys/socketvar.h>
59#include <sys/stat.h>
60#include <sys/syscallsubr.h>
61#include <sys/sysctl.h>
62#include <sys/sysent.h>
63#include <sys/sysproto.h>
64#include <sys/systm.h>
65#include <sys/unistd.h>
66#include <sys/user.h>
67#include <sys/utsname.h>
68#include <sys/vnode.h>
69
70#include <vm/vm.h>
71#include <vm/vm_kern.h>
72#include <vm/vm_param.h>
73#include <vm/pmap.h>
74#include <vm/vm_map.h>
75#include <vm/vm_object.h>
76#include <vm/vm_extern.h>
77
78#include <compat/freebsd32/freebsd32_util.h>
79#include <compat/freebsd32/freebsd32.h>
80#include <compat/freebsd32/freebsd32_proto.h>
81
82CTASSERT(sizeof(struct timeval32) == 8);
83CTASSERT(sizeof(struct timespec32) == 8);
84CTASSERT(sizeof(struct statfs32) == 256);
85CTASSERT(sizeof(struct rusage32) == 72);
86
87int
88freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
89{
90	int error;
91	caddr_t sg;
92	struct rusage32 *rusage32, ru32;
93	struct rusage *rusage = NULL, ru;
94
95	rusage32 = uap->rusage;
96	if (rusage32) {
97		sg = stackgap_init();
98		rusage = stackgap_alloc(&sg, sizeof(struct rusage));
99		uap->rusage = (struct rusage32 *)rusage;
100	}
101	error = wait4(td, (struct wait_args *)uap);
102	if (error)
103		return (error);
104	if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
105		TV_CP(ru, ru32, ru_utime);
106		TV_CP(ru, ru32, ru_stime);
107		CP(ru, ru32, ru_maxrss);
108		CP(ru, ru32, ru_ixrss);
109		CP(ru, ru32, ru_idrss);
110		CP(ru, ru32, ru_isrss);
111		CP(ru, ru32, ru_minflt);
112		CP(ru, ru32, ru_majflt);
113		CP(ru, ru32, ru_nswap);
114		CP(ru, ru32, ru_inblock);
115		CP(ru, ru32, ru_oublock);
116		CP(ru, ru32, ru_msgsnd);
117		CP(ru, ru32, ru_msgrcv);
118		CP(ru, ru32, ru_nsignals);
119		CP(ru, ru32, ru_nvcsw);
120		CP(ru, ru32, ru_nivcsw);
121		error = copyout(&ru32, rusage32, sizeof(ru32));
122	}
123	return (error);
124}
125
126static void
127copy_statfs(struct statfs *in, struct statfs32 *out)
128{
129	CP(*in, *out, f_bsize);
130	CP(*in, *out, f_iosize);
131	CP(*in, *out, f_blocks);
132	CP(*in, *out, f_bfree);
133	CP(*in, *out, f_bavail);
134	CP(*in, *out, f_files);
135	CP(*in, *out, f_ffree);
136	CP(*in, *out, f_fsid);
137	CP(*in, *out, f_owner);
138	CP(*in, *out, f_type);
139	CP(*in, *out, f_flags);
140	CP(*in, *out, f_flags);
141	CP(*in, *out, f_syncwrites);
142	CP(*in, *out, f_asyncwrites);
143	bcopy(in->f_fstypename,
144	      out->f_fstypename, MFSNAMELEN);
145	bcopy(in->f_mntonname,
146	      out->f_mntonname, MNAMELEN);
147	CP(*in, *out, f_syncreads);
148	CP(*in, *out, f_asyncreads);
149	bcopy(in->f_mntfromname,
150	      out->f_mntfromname, MNAMELEN);
151}
152
153int
154freebsd32_getfsstat(struct thread *td, struct freebsd32_getfsstat_args *uap)
155{
156	int error;
157	caddr_t sg;
158	struct statfs32 *sp32, stat32;
159	struct statfs *sp = NULL, stat;
160	int maxcount, count, i;
161
162	sp32 = uap->buf;
163	maxcount = uap->bufsize / sizeof(struct statfs32);
164
165	if (sp32) {
166		sg = stackgap_init();
167		sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
168		uap->buf = (struct statfs32 *)sp;
169	}
170	error = getfsstat(td, (struct getfsstat_args *) uap);
171	if (sp32 && !error) {
172		count = td->td_retval[0];
173		for (i = 0; i < count; i++) {
174			error = copyin(&sp[i], &stat, sizeof(stat));
175			if (error)
176				return (error);
177			copy_statfs(&stat, &stat32);
178			error = copyout(&stat32, &sp32[i], sizeof(stat32));
179			if (error)
180				return (error);
181		}
182	}
183	return (error);
184}
185
186struct sigaltstack32 {
187	u_int32_t	ss_sp;
188	u_int32_t	ss_size;
189	int		ss_flags;
190};
191
192CTASSERT(sizeof(struct sigaltstack32) == 12);
193
194int
195freebsd32_sigaltstack(struct thread *td,
196		      struct freebsd32_sigaltstack_args *uap)
197{
198	struct sigaltstack32 s32;
199	struct sigaltstack ss, oss, *ssp;
200	int error;
201
202	if (uap->ss != NULL) {
203		error = copyin(uap->ss, &s32, sizeof(s32));
204		if (error)
205			return (error);
206		PTRIN_CP(s32, ss, ss_sp);
207		CP(s32, ss, ss_size);
208		CP(s32, ss, ss_flags);
209		ssp = &ss;
210	} else
211		ssp = NULL;
212	error = kern_sigaltstack(td, ssp, &oss);
213	if (error == 0 && uap->oss != NULL) {
214		PTROUT_CP(oss, s32, ss_sp);
215		CP(oss, s32, ss_size);
216		CP(oss, s32, ss_flags);
217		error = copyout(&s32, uap->oss, sizeof(s32));
218	}
219	return (error);
220}
221
222int
223freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
224{
225	int error;
226	caddr_t sg;
227	struct execve_args ap;
228	u_int32_t *p32, arg;
229	char **p, *p64;
230	int count;
231
232	sg = stackgap_init();
233	ap.fname = uap->fname;
234
235	if (uap->argv) {
236		count = 0;
237		p32 = uap->argv;
238		do {
239			error = copyin(p32++, &arg, sizeof(arg));
240			if (error)
241				return error;
242			count++;
243		} while (arg != 0);
244		p = stackgap_alloc(&sg, count * sizeof(char *));
245		ap.argv = p;
246		p32 = uap->argv;
247		do {
248			error = copyin(p32++, &arg, sizeof(arg));
249			if (error)
250				return error;
251			p64 = PTRIN(arg);
252			error = copyout(&p64, p++, sizeof(p64));
253			if (error)
254				return error;
255		} while (arg != 0);
256	}
257	if (uap->envv) {
258		count = 0;
259		p32 = uap->envv;
260		do {
261			error = copyin(p32++, &arg, sizeof(arg));
262			if (error)
263				return error;
264			count++;
265		} while (arg != 0);
266		p = stackgap_alloc(&sg, count * sizeof(char *));
267		ap.envv = p;
268		p32 = uap->envv;
269		do {
270			error = copyin(p32++, &arg, sizeof(arg));
271			if (error)
272				return error;
273			p64 = PTRIN(arg);
274			error = copyout(&p64, p++, sizeof(p64));
275			if (error)
276				return error;
277		} while (arg != 0);
278	}
279
280	return execve(td, &ap);
281}
282
283#ifdef __ia64__
284static int
285freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
286		       int prot, int fd, off_t pos)
287{
288	vm_map_t map;
289	vm_map_entry_t entry;
290	int rv;
291
292	map = &td->td_proc->p_vmspace->vm_map;
293	if (fd != -1)
294		prot |= VM_PROT_WRITE;
295
296	if (vm_map_lookup_entry(map, start, &entry)) {
297		if ((entry->protection & prot) != prot) {
298			rv = vm_map_protect(map,
299					    trunc_page(start),
300					    round_page(end),
301					    entry->protection | prot,
302					    FALSE);
303			if (rv != KERN_SUCCESS)
304				return (EINVAL);
305		}
306	} else {
307		vm_offset_t addr = trunc_page(start);
308		rv = vm_map_find(map, 0, 0,
309				 &addr, PAGE_SIZE, FALSE, prot,
310				 VM_PROT_ALL, 0);
311		if (rv != KERN_SUCCESS)
312			return (EINVAL);
313	}
314
315	if (fd != -1) {
316		struct pread_args r;
317		r.fd = fd;
318		r.buf = (void *) start;
319		r.nbyte = end - start;
320		r.offset = pos;
321		return (pread(td, &r));
322	} else {
323		while (start < end) {
324			subyte((void *) start, 0);
325			start++;
326		}
327		return (0);
328	}
329}
330#endif
331
332int
333freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
334{
335	struct mmap_args ap;
336	vm_offset_t addr = (vm_offset_t) uap->addr;
337	vm_size_t len	 = uap->len;
338	int prot	 = uap->prot;
339	int flags	 = uap->flags;
340	int fd		 = uap->fd;
341	off_t pos	 = (uap->poslo
342			    | ((off_t)uap->poshi << 32));
343#ifdef __ia64__
344	vm_size_t pageoff;
345	int error;
346
347	/*
348	 * Attempt to handle page size hassles.
349	 */
350	pageoff = (pos & PAGE_MASK);
351	if (flags & MAP_FIXED) {
352		vm_offset_t start, end;
353		start = addr;
354		end = addr + len;
355
356		if (start != trunc_page(start)) {
357			error = freebsd32_mmap_partial(td, start,
358						       round_page(start), prot,
359						       fd, pos);
360			if (fd != -1)
361				pos += round_page(start) - start;
362			start = round_page(start);
363		}
364		if (end != round_page(end)) {
365			vm_offset_t t = trunc_page(end);
366			error = freebsd32_mmap_partial(td, t, end,
367						  prot, fd,
368						  pos + t - start);
369			end = trunc_page(end);
370		}
371		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
372			/*
373			 * We can't map this region at all. The specified
374			 * address doesn't have the same alignment as the file
375			 * position. Fake the mapping by simply reading the
376			 * entire region into memory. First we need to make
377			 * sure the region exists.
378			 */
379			vm_map_t map;
380			struct pread_args r;
381			int rv;
382
383			prot |= VM_PROT_WRITE;
384			map = &td->td_proc->p_vmspace->vm_map;
385			rv = vm_map_remove(map, start, end);
386			if (rv != KERN_SUCCESS)
387				return (EINVAL);
388			rv = vm_map_find(map, 0, 0,
389					 &start, end - start, FALSE,
390					 prot, VM_PROT_ALL, 0);
391			if (rv != KERN_SUCCESS)
392				return (EINVAL);
393			r.fd = fd;
394			r.buf = (void *) start;
395			r.nbyte = end - start;
396			r.offset = pos;
397			error = pread(td, &r);
398			if (error)
399				return (error);
400
401			td->td_retval[0] = addr;
402			return (0);
403		}
404		if (end == start) {
405			/*
406			 * After dealing with the ragged ends, there
407			 * might be none left.
408			 */
409			td->td_retval[0] = addr;
410			return (0);
411		}
412		addr = start;
413		len = end - start;
414	}
415#endif
416
417	ap.addr = (void *) addr;
418	ap.len = len;
419	ap.prot = prot;
420	ap.flags = flags;
421	ap.fd = fd;
422	ap.pos = pos;
423
424	return (mmap(td, &ap));
425}
426
427struct itimerval32 {
428	struct timeval32 it_interval;
429	struct timeval32 it_value;
430};
431
432CTASSERT(sizeof(struct itimerval32) == 16);
433
434int
435freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
436{
437	int error;
438	caddr_t sg;
439	struct itimerval32 *p32, *op32, s32;
440	struct itimerval *p = NULL, *op = NULL, s;
441
442	p32 = uap->itv;
443	if (p32) {
444		sg = stackgap_init();
445		p = stackgap_alloc(&sg, sizeof(struct itimerval));
446		uap->itv = (struct itimerval32 *)p;
447		error = copyin(p32, &s32, sizeof(s32));
448		if (error)
449			return (error);
450		TV_CP(s32, s, it_interval);
451		TV_CP(s32, s, it_value);
452		error = copyout(&s, p, sizeof(s));
453		if (error)
454			return (error);
455	}
456	op32 = uap->oitv;
457	if (op32) {
458		sg = stackgap_init();
459		op = stackgap_alloc(&sg, sizeof(struct itimerval));
460		uap->oitv = (struct itimerval32 *)op;
461	}
462	error = setitimer(td, (struct setitimer_args *) uap);
463	if (error)
464		return (error);
465	if (op32) {
466		error = copyin(op, &s, sizeof(s));
467		if (error)
468			return (error);
469		TV_CP(s, s32, it_interval);
470		TV_CP(s, s32, it_value);
471		error = copyout(&s32, op32, sizeof(s32));
472	}
473	return (error);
474}
475
476int
477freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
478{
479	int error;
480	caddr_t sg;
481	struct timeval32 *p32, s32;
482	struct timeval *p = NULL, s;
483
484	p32 = uap->tv;
485	if (p32) {
486		sg = stackgap_init();
487		p = stackgap_alloc(&sg, sizeof(struct timeval));
488		uap->tv = (struct timeval32 *)p;
489		error = copyin(p32, &s32, sizeof(s32));
490		if (error)
491			return (error);
492		CP(s32, s, tv_sec);
493		CP(s32, s, tv_usec);
494		error = copyout(&s, p, sizeof(s));
495		if (error)
496			return (error);
497	}
498	/*
499	 * XXX big-endian needs to convert the fd_sets too.
500	 */
501	return (select(td, (struct select_args *) uap));
502}
503
504struct kevent32 {
505	u_int32_t	ident;		/* identifier for this event */
506	short		filter;		/* filter for event */
507	u_short		flags;
508	u_int		fflags;
509	int32_t		data;
510	u_int32_t	udata;		/* opaque user data identifier */
511};
512
513CTASSERT(sizeof(struct kevent32) == 20);
514
515int
516freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
517{
518	int error;
519	caddr_t sg;
520	struct timespec32 ts32;
521	struct timespec ts;
522	struct kevent32 ks32;
523	struct kevent *ks;
524	struct kevent_args a;
525	int i;
526
527	sg = stackgap_init();
528
529	a.fd = uap->fd;
530	a.changelist = uap->changelist;
531	a.nchanges = uap->nchanges;
532	a.eventlist = uap->eventlist;
533	a.nevents = uap->nevents;
534	a.timeout = NULL;
535
536	if (uap->timeout) {
537		a.timeout = stackgap_alloc(&sg, sizeof(struct timespec));
538		error = copyin(uap->timeout, &ts32, sizeof(ts32));
539		if (error)
540			return (error);
541		CP(ts32, ts, tv_sec);
542		CP(ts32, ts, tv_nsec);
543		error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts));
544		if (error)
545			return (error);
546	}
547	if (uap->changelist) {
548		a.changelist = (struct kevent *)stackgap_alloc(&sg,
549		    uap->nchanges * sizeof(struct kevent));
550		for (i = 0; i < uap->nchanges; i++) {
551			error = copyin(&uap->changelist[i], &ks32,
552			    sizeof(ks32));
553			if (error)
554				return (error);
555			ks = (struct kevent *)(uintptr_t)&a.changelist[i];
556			CP(ks32, *ks, ident);
557			CP(ks32, *ks, filter);
558			CP(ks32, *ks, flags);
559			CP(ks32, *ks, fflags);
560			CP(ks32, *ks, data);
561			PTRIN_CP(ks32, *ks, udata);
562		}
563	}
564	if (uap->eventlist) {
565		a.eventlist = stackgap_alloc(&sg,
566		    uap->nevents * sizeof(struct kevent));
567	}
568	error = kevent(td, &a);
569	if (uap->eventlist && error > 0) {
570		for (i = 0; i < error; i++) {
571			ks = &a.eventlist[i];
572			CP(*ks, ks32, ident);
573			CP(*ks, ks32, filter);
574			CP(*ks, ks32, flags);
575			CP(*ks, ks32, fflags);
576			CP(*ks, ks32, data);
577			PTROUT_CP(*ks, ks32, udata);
578			error = copyout(&ks32, &uap->eventlist[i],
579			    sizeof(ks32));
580			if (error)
581				return (error);
582		}
583	}
584	return error;
585}
586
587int
588freebsd32_gettimeofday(struct thread *td,
589		       struct freebsd32_gettimeofday_args *uap)
590{
591	struct timeval atv;
592	struct timeval32 atv32;
593	struct timezone rtz;
594	int error = 0;
595
596	if (uap->tp) {
597		microtime(&atv);
598		CP(atv, atv32, tv_sec);
599		CP(atv, atv32, tv_usec);
600		error = copyout(&atv32, uap->tp, sizeof (atv32));
601	}
602	if (error == 0 && uap->tzp != NULL) {
603		rtz.tz_minuteswest = tz_minuteswest;
604		rtz.tz_dsttime = tz_dsttime;
605		error = copyout(&rtz, uap->tzp, sizeof (rtz));
606	}
607	return (error);
608}
609
610int
611freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
612{
613	int error;
614	caddr_t sg;
615	struct rusage32 *p32, s32;
616	struct rusage *p = NULL, s;
617
618	p32 = uap->rusage;
619	if (p32) {
620		sg = stackgap_init();
621		p = stackgap_alloc(&sg, sizeof(struct rusage));
622		uap->rusage = (struct rusage32 *)p;
623	}
624	error = getrusage(td, (struct getrusage_args *) uap);
625	if (error)
626		return (error);
627	if (p32) {
628		error = copyin(p, &s, sizeof(s));
629		if (error)
630			return (error);
631		TV_CP(s, s32, ru_utime);
632		TV_CP(s, s32, ru_stime);
633		CP(s, s32, ru_maxrss);
634		CP(s, s32, ru_ixrss);
635		CP(s, s32, ru_idrss);
636		CP(s, s32, ru_isrss);
637		CP(s, s32, ru_minflt);
638		CP(s, s32, ru_majflt);
639		CP(s, s32, ru_nswap);
640		CP(s, s32, ru_inblock);
641		CP(s, s32, ru_oublock);
642		CP(s, s32, ru_msgsnd);
643		CP(s, s32, ru_msgrcv);
644		CP(s, s32, ru_nsignals);
645		CP(s, s32, ru_nvcsw);
646		CP(s, s32, ru_nivcsw);
647		error = copyout(&s32, p32, sizeof(s32));
648	}
649	return (error);
650}
651
652struct iovec32 {
653	u_int32_t iov_base;
654	int	iov_len;
655};
656#define	STACKGAPLEN	400
657
658CTASSERT(sizeof(struct iovec32) == 8);
659
660int
661freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
662{
663	int error, osize, nsize, i;
664	caddr_t sg;
665	struct readv_args /* {
666		syscallarg(int) fd;
667		syscallarg(struct iovec *) iovp;
668		syscallarg(u_int) iovcnt;
669	} */ a;
670	struct iovec32 *oio;
671	struct iovec *nio;
672
673	sg = stackgap_init();
674
675	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
676		return (EINVAL);
677
678	osize = uap->iovcnt * sizeof (struct iovec32);
679	nsize = uap->iovcnt * sizeof (struct iovec);
680
681	oio = malloc(osize, M_TEMP, M_WAITOK);
682	nio = malloc(nsize, M_TEMP, M_WAITOK);
683
684	error = 0;
685	if ((error = copyin(uap->iovp, oio, osize)))
686		goto punt;
687	for (i = 0; i < uap->iovcnt; i++) {
688		nio[i].iov_base = PTRIN(oio[i].iov_base);
689		nio[i].iov_len = oio[i].iov_len;
690	}
691
692	a.fd = uap->fd;
693	a.iovp = stackgap_alloc(&sg, nsize);
694	a.iovcnt = uap->iovcnt;
695
696	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
697		goto punt;
698	error = readv(td, &a);
699
700punt:
701	free(oio, M_TEMP);
702	free(nio, M_TEMP);
703	return (error);
704}
705
706int
707freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
708{
709	int error, i, nsize, osize;
710	caddr_t sg;
711	struct writev_args /* {
712		syscallarg(int) fd;
713		syscallarg(struct iovec *) iovp;
714		syscallarg(u_int) iovcnt;
715	} */ a;
716	struct iovec32 *oio;
717	struct iovec *nio;
718
719	sg = stackgap_init();
720
721	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
722		return (EINVAL);
723
724	osize = uap->iovcnt * sizeof (struct iovec32);
725	nsize = uap->iovcnt * sizeof (struct iovec);
726
727	oio = malloc(osize, M_TEMP, M_WAITOK);
728	nio = malloc(nsize, M_TEMP, M_WAITOK);
729
730	error = 0;
731	if ((error = copyin(uap->iovp, oio, osize)))
732		goto punt;
733	for (i = 0; i < uap->iovcnt; i++) {
734		nio[i].iov_base = PTRIN(oio[i].iov_base);
735		nio[i].iov_len = oio[i].iov_len;
736	}
737
738	a.fd = uap->fd;
739	a.iovp = stackgap_alloc(&sg, nsize);
740	a.iovcnt = uap->iovcnt;
741
742	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
743		goto punt;
744	error = writev(td, &a);
745
746punt:
747	free(oio, M_TEMP);
748	free(nio, M_TEMP);
749	return (error);
750}
751
752int
753freebsd32_settimeofday(struct thread *td,
754		       struct freebsd32_settimeofday_args *uap)
755{
756	int error;
757	caddr_t sg;
758	struct timeval32 *p32, s32;
759	struct timeval *p = NULL, s;
760
761	p32 = uap->tv;
762	if (p32) {
763		sg = stackgap_init();
764		p = stackgap_alloc(&sg, sizeof(struct timeval));
765		uap->tv = (struct timeval32 *)p;
766		error = copyin(p32, &s32, sizeof(s32));
767		if (error)
768			return (error);
769		CP(s32, s, tv_sec);
770		CP(s32, s, tv_usec);
771		error = copyout(&s, p, sizeof(s));
772		if (error)
773			return (error);
774	}
775	return (settimeofday(td, (struct settimeofday_args *) uap));
776}
777
778int
779freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
780{
781	int error;
782	caddr_t sg;
783	struct timeval32 *p32, s32[2];
784	struct timeval *p = NULL, s[2];
785
786	p32 = uap->tptr;
787	if (p32) {
788		sg = stackgap_init();
789		p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
790		uap->tptr = (struct timeval32 *)p;
791		error = copyin(p32, s32, sizeof(s32));
792		if (error)
793			return (error);
794		CP(s32[0], s[0], tv_sec);
795		CP(s32[0], s[0], tv_usec);
796		CP(s32[1], s[1], tv_sec);
797		CP(s32[1], s[1], tv_usec);
798		error = copyout(s, p, sizeof(s));
799		if (error)
800			return (error);
801	}
802	return (utimes(td, (struct utimes_args *) uap));
803}
804
805int
806freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
807{
808	int error;
809	caddr_t sg;
810	struct timeval32 *p32, *op32, s32;
811	struct timeval *p = NULL, *op = NULL, s;
812
813	p32 = uap->delta;
814	if (p32) {
815		sg = stackgap_init();
816		p = stackgap_alloc(&sg, sizeof(struct timeval));
817		uap->delta = (struct timeval32 *)p;
818		error = copyin(p32, &s32, sizeof(s32));
819		if (error)
820			return (error);
821		CP(s32, s, tv_sec);
822		CP(s32, s, tv_usec);
823		error = copyout(&s, p, sizeof(s));
824		if (error)
825			return (error);
826	}
827	op32 = uap->olddelta;
828	if (op32) {
829		sg = stackgap_init();
830		op = stackgap_alloc(&sg, sizeof(struct timeval));
831		uap->olddelta = (struct timeval32 *)op;
832	}
833	error = utimes(td, (struct utimes_args *) uap);
834	if (error)
835		return error;
836	if (op32) {
837		error = copyin(op, &s, sizeof(s));
838		if (error)
839			return (error);
840		CP(s, s32, tv_sec);
841		CP(s, s32, tv_usec);
842		error = copyout(&s32, op32, sizeof(s32));
843	}
844	return (error);
845}
846
847int
848freebsd32_statfs(struct thread *td, struct freebsd32_statfs_args *uap)
849{
850	int error;
851	caddr_t sg;
852	struct statfs32 *p32, s32;
853	struct statfs *p = NULL, s;
854
855	p32 = uap->buf;
856	if (p32) {
857		sg = stackgap_init();
858		p = stackgap_alloc(&sg, sizeof(struct statfs));
859		uap->buf = (struct statfs32 *)p;
860	}
861	error = statfs(td, (struct statfs_args *) uap);
862	if (error)
863		return (error);
864	if (p32) {
865		error = copyin(p, &s, sizeof(s));
866		if (error)
867			return (error);
868		copy_statfs(&s, &s32);
869		error = copyout(&s32, p32, sizeof(s32));
870	}
871	return (error);
872}
873
874int
875freebsd32_fstatfs(struct thread *td, struct freebsd32_fstatfs_args *uap)
876{
877	int error;
878	caddr_t sg;
879	struct statfs32 *p32, s32;
880	struct statfs *p = NULL, s;
881
882	p32 = uap->buf;
883	if (p32) {
884		sg = stackgap_init();
885		p = stackgap_alloc(&sg, sizeof(struct statfs));
886		uap->buf = (struct statfs32 *)p;
887	}
888	error = fstatfs(td, (struct fstatfs_args *) uap);
889	if (error)
890		return (error);
891	if (p32) {
892		error = copyin(p, &s, sizeof(s));
893		if (error)
894			return (error);
895		copy_statfs(&s, &s32);
896		error = copyout(&s32, p32, sizeof(s32));
897	}
898	return (error);
899}
900
901int
902freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
903{
904	/*
905	 * Vector through to semsys if it is loaded.
906	 */
907	return sysent[169].sy_call(td, uap);
908}
909
910int
911freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
912{
913	/*
914	 * Vector through to msgsys if it is loaded.
915	 */
916	return sysent[170].sy_call(td, uap);
917}
918
919int
920freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
921{
922	/*
923	 * Vector through to shmsys if it is loaded.
924	 */
925	return sysent[171].sy_call(td, uap);
926}
927
928int
929freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
930{
931	struct pread_args ap;
932
933	ap.fd = uap->fd;
934	ap.buf = uap->buf;
935	ap.nbyte = uap->nbyte;
936	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
937	return (pread(td, &ap));
938}
939
940int
941freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
942{
943	struct pwrite_args ap;
944
945	ap.fd = uap->fd;
946	ap.buf = uap->buf;
947	ap.nbyte = uap->nbyte;
948	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
949	return (pwrite(td, &ap));
950}
951
952int
953freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
954{
955	int error;
956	struct lseek_args ap;
957	off_t pos;
958
959	ap.fd = uap->fd;
960	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
961	ap.whence = uap->whence;
962	error = lseek(td, &ap);
963	/* Expand the quad return into two parts for eax and edx */
964	pos = *(off_t *)(td->td_retval);
965	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
966	td->td_retval[1] = pos >> 32;		/* %edx */
967	return error;
968}
969
970int
971freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
972{
973	struct truncate_args ap;
974
975	ap.path = uap->path;
976	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
977	return (truncate(td, &ap));
978}
979
980int
981freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
982{
983	struct ftruncate_args ap;
984
985	ap.fd = uap->fd;
986	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
987	return (ftruncate(td, &ap));
988}
989
990#ifdef COMPAT_FREEBSD4
991int
992freebsd4_freebsd32_sendfile(struct thread *td,
993    struct freebsd4_freebsd32_sendfile_args *uap)
994{
995	struct freebsd4_sendfile_args ap;
996
997	ap.fd = uap->fd;
998	ap.s = uap->s;
999	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1000	ap.nbytes = uap->nbytes;	/* XXX check */
1001	ap.hdtr = uap->hdtr;		/* XXX check */
1002	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1003	ap.flags = uap->flags;
1004	return (freebsd4_sendfile(td, &ap));
1005}
1006#endif
1007
1008int
1009freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1010{
1011	struct sendfile_args ap;
1012
1013	ap.fd = uap->fd;
1014	ap.s = uap->s;
1015	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1016	ap.nbytes = uap->nbytes;	/* XXX check */
1017	ap.hdtr = uap->hdtr;		/* XXX check */
1018	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1019	ap.flags = uap->flags;
1020	return (sendfile(td, &ap));
1021}
1022
1023struct stat32 {
1024	udev_t	st_dev;
1025	ino_t	st_ino;
1026	mode_t	st_mode;
1027	nlink_t	st_nlink;
1028	uid_t	st_uid;
1029	gid_t	st_gid;
1030	udev_t	st_rdev;
1031	struct timespec32 st_atimespec;
1032	struct timespec32 st_mtimespec;
1033	struct timespec32 st_ctimespec;
1034	off_t	st_size;
1035	int64_t	st_blocks;
1036	u_int32_t st_blksize;
1037	u_int32_t st_flags;
1038	u_int32_t st_gen;
1039	struct timespec32 st_birthtimespec;
1040	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1041	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1042};
1043
1044
1045CTASSERT(sizeof(struct stat32) == 96);
1046
1047static void
1048copy_stat( struct stat *in, struct stat32 *out)
1049{
1050	CP(*in, *out, st_dev);
1051	CP(*in, *out, st_ino);
1052	CP(*in, *out, st_mode);
1053	CP(*in, *out, st_nlink);
1054	CP(*in, *out, st_uid);
1055	CP(*in, *out, st_gid);
1056	CP(*in, *out, st_rdev);
1057	TS_CP(*in, *out, st_atimespec);
1058	TS_CP(*in, *out, st_mtimespec);
1059	TS_CP(*in, *out, st_ctimespec);
1060	CP(*in, *out, st_size);
1061	CP(*in, *out, st_blocks);
1062	CP(*in, *out, st_blksize);
1063	CP(*in, *out, st_flags);
1064	CP(*in, *out, st_gen);
1065}
1066
1067int
1068freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1069{
1070	int error;
1071	caddr_t sg;
1072	struct stat32 *p32, s32;
1073	struct stat *p = NULL, s;
1074
1075	p32 = uap->ub;
1076	if (p32) {
1077		sg = stackgap_init();
1078		p = stackgap_alloc(&sg, sizeof(struct stat));
1079		uap->ub = (struct stat32 *)p;
1080	}
1081	error = stat(td, (struct stat_args *) uap);
1082	if (error)
1083		return (error);
1084	if (p32) {
1085		error = copyin(p, &s, sizeof(s));
1086		if (error)
1087			return (error);
1088		copy_stat(&s, &s32);
1089		error = copyout(&s32, p32, sizeof(s32));
1090	}
1091	return (error);
1092}
1093
1094int
1095freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1096{
1097	int error;
1098	caddr_t sg;
1099	struct stat32 *p32, s32;
1100	struct stat *p = NULL, s;
1101
1102	p32 = uap->ub;
1103	if (p32) {
1104		sg = stackgap_init();
1105		p = stackgap_alloc(&sg, sizeof(struct stat));
1106		uap->ub = (struct stat32 *)p;
1107	}
1108	error = fstat(td, (struct fstat_args *) uap);
1109	if (error)
1110		return (error);
1111	if (p32) {
1112		error = copyin(p, &s, sizeof(s));
1113		if (error)
1114			return (error);
1115		copy_stat(&s, &s32);
1116		error = copyout(&s32, p32, sizeof(s32));
1117	}
1118	return (error);
1119}
1120
1121int
1122freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1123{
1124	int error;
1125	caddr_t sg;
1126	struct stat32 *p32, s32;
1127	struct stat *p = NULL, s;
1128
1129	p32 = uap->ub;
1130	if (p32) {
1131		sg = stackgap_init();
1132		p = stackgap_alloc(&sg, sizeof(struct stat));
1133		uap->ub = (struct stat32 *)p;
1134	}
1135	error = lstat(td, (struct lstat_args *) uap);
1136	if (error)
1137		return (error);
1138	if (p32) {
1139		error = copyin(p, &s, sizeof(s));
1140		if (error)
1141			return (error);
1142		copy_stat(&s, &s32);
1143		error = copyout(&s32, p32, sizeof(s32));
1144	}
1145	return (error);
1146}
1147
1148/*
1149 * MPSAFE
1150 */
1151int
1152freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1153{
1154	int error, name[CTL_MAXNAME];
1155	size_t j, oldlen;
1156
1157	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1158		return (EINVAL);
1159
1160 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1161 	if (error)
1162		return (error);
1163
1164	mtx_lock(&Giant);
1165
1166	if (uap->oldlenp)
1167		oldlen = fuword32(uap->oldlenp);
1168	else
1169		oldlen = 0;
1170	error = userland_sysctl(td, name, uap->namelen,
1171		uap->old, &oldlen, 1,
1172		uap->new, uap->newlen, &j);
1173	if (error && error != ENOMEM)
1174		goto done2;
1175	if (uap->oldlenp) {
1176		suword32(uap->oldlenp, j);
1177	}
1178done2:
1179	mtx_unlock(&Giant);
1180	return (error);
1181}
1182
1183struct sigaction32 {
1184	u_int32_t	sa_u;
1185	int		sa_flags;
1186	sigset_t	sa_mask;
1187};
1188
1189CTASSERT(sizeof(struct sigaction32) == 24);
1190
1191int
1192freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1193{
1194	struct sigaction32 s32;
1195	struct sigaction sa, osa, *sap;
1196	int error;
1197
1198	if (uap->act) {
1199		error = copyin(uap->act, &s32, sizeof(s32));
1200		if (error)
1201			return (error);
1202		sa.sa_handler = PTRIN(s32.sa_u);
1203		CP(s32, sa, sa_flags);
1204		CP(s32, sa, sa_mask);
1205		sap = &sa;
1206	} else
1207		sap = NULL;
1208	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1209	if (error != 0 && uap->oact != NULL) {
1210		s32.sa_u = PTROUT(osa.sa_handler);
1211		CP(osa, s32, sa_flags);
1212		CP(osa, s32, sa_mask);
1213		error = copyout(&s32, uap->oact, sizeof(s32));
1214	}
1215	return (error);
1216}
1217
1218#ifdef COMPAT_FREEBSD4
1219int
1220freebsd4_freebsd32_sigaction(struct thread *td,
1221			     struct freebsd4_freebsd32_sigaction_args *uap)
1222{
1223	struct sigaction32 s32;
1224	struct sigaction sa, osa, *sap;
1225	int error;
1226
1227	if (uap->act) {
1228		error = copyin(uap->act, &s32, sizeof(s32));
1229		if (error)
1230			return (error);
1231		sa.sa_handler = PTRIN(s32.sa_u);
1232		CP(s32, sa, sa_flags);
1233		CP(s32, sa, sa_mask);
1234		sap = &sa;
1235	} else
1236		sap = NULL;
1237	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1238	if (error != 0 && uap->oact != NULL) {
1239		s32.sa_u = PTROUT(osa.sa_handler);
1240		CP(osa, s32, sa_flags);
1241		CP(osa, s32, sa_mask);
1242		error = copyout(&s32, uap->oact, sizeof(s32));
1243	}
1244	return (error);
1245}
1246#endif
1247
1248#if 0
1249
1250int
1251freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1252{
1253	int error;
1254	caddr_t sg;
1255	struct yyy32 *p32, s32;
1256	struct yyy *p = NULL, s;
1257
1258	p32 = uap->zzz;
1259	if (p32) {
1260		sg = stackgap_init();
1261		p = stackgap_alloc(&sg, sizeof(struct yyy));
1262		uap->zzz = (struct yyy32 *)p;
1263		error = copyin(p32, &s32, sizeof(s32));
1264		if (error)
1265			return (error);
1266		/* translate in */
1267		error = copyout(&s, p, sizeof(s));
1268		if (error)
1269			return (error);
1270	}
1271	error = xxx(td, (struct xxx_args *) uap);
1272	if (error)
1273		return (error);
1274	if (p32) {
1275		error = copyin(p, &s, sizeof(s));
1276		if (error)
1277			return (error);
1278		/* translate out */
1279		error = copyout(&s32, p32, sizeof(s32));
1280	}
1281	return (error);
1282}
1283
1284#endif
1285