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