freebsd32_misc.c revision 121719
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 121719 2003-10-30 02:40:30Z 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;
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			*p++ = PTRIN(arg);
425		} while (arg != 0);
426	}
427	if (uap->envv) {
428		count = 0;
429		p32 = uap->envv;
430		do {
431			error = copyin(p32++, &arg, sizeof(arg));
432			if (error)
433				return error;
434			count++;
435		} while (arg != 0);
436		p = stackgap_alloc(&sg, count * sizeof(char *));
437		ap.envv = p;
438		p32 = uap->envv;
439		do {
440			error = copyin(p32++, &arg, sizeof(arg));
441			if (error)
442				return error;
443			*p++ = PTRIN(arg);
444		} while (arg != 0);
445	}
446
447	return execve(td, &ap);
448}
449
450#ifdef __ia64__
451static int
452freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
453		       int prot, int fd, off_t pos)
454{
455	vm_map_t map;
456	vm_map_entry_t entry;
457	int rv;
458
459	map = &td->td_proc->p_vmspace->vm_map;
460	if (fd != -1)
461		prot |= VM_PROT_WRITE;
462
463	if (vm_map_lookup_entry(map, start, &entry)) {
464		if ((entry->protection & prot) != prot) {
465			rv = vm_map_protect(map,
466					    trunc_page(start),
467					    round_page(end),
468					    entry->protection | prot,
469					    FALSE);
470			if (rv != KERN_SUCCESS)
471				return (EINVAL);
472		}
473	} else {
474		vm_offset_t addr = trunc_page(start);
475		rv = vm_map_find(map, 0, 0,
476				 &addr, PAGE_SIZE, FALSE, prot,
477				 VM_PROT_ALL, 0);
478		if (rv != KERN_SUCCESS)
479			return (EINVAL);
480	}
481
482	if (fd != -1) {
483		struct pread_args r;
484		r.fd = fd;
485		r.buf = (void *) start;
486		r.nbyte = end - start;
487		r.offset = pos;
488		return (pread(td, &r));
489	} else {
490		while (start < end) {
491			subyte((void *) start, 0);
492			start++;
493		}
494		return (0);
495	}
496}
497#endif
498
499int
500freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
501{
502	struct mmap_args ap;
503	vm_offset_t addr = (vm_offset_t) uap->addr;
504	vm_size_t len	 = uap->len;
505	int prot	 = uap->prot;
506	int flags	 = uap->flags;
507	int fd		 = uap->fd;
508	off_t pos	 = (uap->poslo
509			    | ((off_t)uap->poshi << 32));
510#ifdef __ia64__
511	vm_size_t pageoff;
512	int error;
513
514	/*
515	 * Attempt to handle page size hassles.
516	 */
517	pageoff = (pos & PAGE_MASK);
518	if (flags & MAP_FIXED) {
519		vm_offset_t start, end;
520		start = addr;
521		end = addr + len;
522
523		if (start != trunc_page(start)) {
524			error = freebsd32_mmap_partial(td, start,
525						       round_page(start), prot,
526						       fd, pos);
527			if (fd != -1)
528				pos += round_page(start) - start;
529			start = round_page(start);
530		}
531		if (end != round_page(end)) {
532			vm_offset_t t = trunc_page(end);
533			error = freebsd32_mmap_partial(td, t, end,
534						  prot, fd,
535						  pos + t - start);
536			end = trunc_page(end);
537		}
538		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
539			/*
540			 * We can't map this region at all. The specified
541			 * address doesn't have the same alignment as the file
542			 * position. Fake the mapping by simply reading the
543			 * entire region into memory. First we need to make
544			 * sure the region exists.
545			 */
546			vm_map_t map;
547			struct pread_args r;
548			int rv;
549
550			prot |= VM_PROT_WRITE;
551			map = &td->td_proc->p_vmspace->vm_map;
552			rv = vm_map_remove(map, start, end);
553			if (rv != KERN_SUCCESS)
554				return (EINVAL);
555			rv = vm_map_find(map, 0, 0,
556					 &start, end - start, FALSE,
557					 prot, VM_PROT_ALL, 0);
558			if (rv != KERN_SUCCESS)
559				return (EINVAL);
560			r.fd = fd;
561			r.buf = (void *) start;
562			r.nbyte = end - start;
563			r.offset = pos;
564			error = pread(td, &r);
565			if (error)
566				return (error);
567
568			td->td_retval[0] = addr;
569			return (0);
570		}
571		if (end == start) {
572			/*
573			 * After dealing with the ragged ends, there
574			 * might be none left.
575			 */
576			td->td_retval[0] = addr;
577			return (0);
578		}
579		addr = start;
580		len = end - start;
581	}
582#endif
583
584	ap.addr = (void *) addr;
585	ap.len = len;
586	ap.prot = prot;
587	ap.flags = flags;
588	ap.fd = fd;
589	ap.pos = pos;
590
591	return (mmap(td, &ap));
592}
593
594struct itimerval32 {
595	struct timeval32 it_interval;
596	struct timeval32 it_value;
597};
598
599CTASSERT(sizeof(struct itimerval32) == 16);
600
601int
602freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
603{
604	int error;
605	caddr_t sg;
606	struct itimerval32 *p32, *op32, s32;
607	struct itimerval *p = NULL, *op = NULL, s;
608
609	p32 = uap->itv;
610	if (p32) {
611		sg = stackgap_init();
612		p = stackgap_alloc(&sg, sizeof(struct itimerval));
613		uap->itv = (struct itimerval32 *)p;
614		error = copyin(p32, &s32, sizeof(s32));
615		if (error)
616			return (error);
617		TV_CP(s32, s, it_interval);
618		TV_CP(s32, s, it_value);
619		error = copyout(&s, p, sizeof(s));
620		if (error)
621			return (error);
622	}
623	op32 = uap->oitv;
624	if (op32) {
625		sg = stackgap_init();
626		op = stackgap_alloc(&sg, sizeof(struct itimerval));
627		uap->oitv = (struct itimerval32 *)op;
628	}
629	error = setitimer(td, (struct setitimer_args *) uap);
630	if (error)
631		return (error);
632	if (op32) {
633		error = copyin(op, &s, sizeof(s));
634		if (error)
635			return (error);
636		TV_CP(s, s32, it_interval);
637		TV_CP(s, s32, it_value);
638		error = copyout(&s32, op32, sizeof(s32));
639	}
640	return (error);
641}
642
643int
644freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
645{
646	int error;
647	caddr_t sg;
648	struct timeval32 *p32, s32;
649	struct timeval *p = NULL, s;
650
651	p32 = uap->tv;
652	if (p32) {
653		sg = stackgap_init();
654		p = stackgap_alloc(&sg, sizeof(struct timeval));
655		uap->tv = (struct timeval32 *)p;
656		error = copyin(p32, &s32, sizeof(s32));
657		if (error)
658			return (error);
659		CP(s32, s, tv_sec);
660		CP(s32, s, tv_usec);
661		error = copyout(&s, p, sizeof(s));
662		if (error)
663			return (error);
664	}
665	/*
666	 * XXX big-endian needs to convert the fd_sets too.
667	 */
668	return (select(td, (struct select_args *) uap));
669}
670
671struct kevent32 {
672	u_int32_t	ident;		/* identifier for this event */
673	short		filter;		/* filter for event */
674	u_short		flags;
675	u_int		fflags;
676	int32_t		data;
677	u_int32_t	udata;		/* opaque user data identifier */
678};
679
680CTASSERT(sizeof(struct kevent32) == 20);
681
682int
683freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
684{
685	int error;
686	caddr_t sg;
687	struct timespec32 ts32;
688	struct timespec ts;
689	struct kevent32 ks32;
690	struct kevent *ks;
691	struct kevent_args a;
692	int i;
693
694	sg = stackgap_init();
695
696	a.fd = uap->fd;
697	a.changelist = uap->changelist;
698	a.nchanges = uap->nchanges;
699	a.eventlist = uap->eventlist;
700	a.nevents = uap->nevents;
701	a.timeout = NULL;
702
703	if (uap->timeout) {
704		a.timeout = stackgap_alloc(&sg, sizeof(struct timespec));
705		error = copyin(uap->timeout, &ts32, sizeof(ts32));
706		if (error)
707			return (error);
708		CP(ts32, ts, tv_sec);
709		CP(ts32, ts, tv_nsec);
710		error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts));
711		if (error)
712			return (error);
713	}
714	if (uap->changelist) {
715		a.changelist = (struct kevent *)stackgap_alloc(&sg,
716		    uap->nchanges * sizeof(struct kevent));
717		for (i = 0; i < uap->nchanges; i++) {
718			error = copyin(&uap->changelist[i], &ks32,
719			    sizeof(ks32));
720			if (error)
721				return (error);
722			ks = (struct kevent *)(uintptr_t)&a.changelist[i];
723			CP(ks32, *ks, ident);
724			CP(ks32, *ks, filter);
725			CP(ks32, *ks, flags);
726			CP(ks32, *ks, fflags);
727			CP(ks32, *ks, data);
728			PTRIN_CP(ks32, *ks, udata);
729		}
730	}
731	if (uap->eventlist) {
732		a.eventlist = stackgap_alloc(&sg,
733		    uap->nevents * sizeof(struct kevent));
734	}
735	error = kevent(td, &a);
736	if (uap->eventlist && error > 0) {
737		for (i = 0; i < error; i++) {
738			ks = &a.eventlist[i];
739			CP(*ks, ks32, ident);
740			CP(*ks, ks32, filter);
741			CP(*ks, ks32, flags);
742			CP(*ks, ks32, fflags);
743			CP(*ks, ks32, data);
744			PTROUT_CP(*ks, ks32, udata);
745			error = copyout(&ks32, &uap->eventlist[i],
746			    sizeof(ks32));
747			if (error)
748				return (error);
749		}
750	}
751	return error;
752}
753
754int
755freebsd32_gettimeofday(struct thread *td,
756		       struct freebsd32_gettimeofday_args *uap)
757{
758	int error;
759	caddr_t sg;
760	struct timeval32 *p32, s32;
761	struct timeval *p = NULL, s;
762
763	p32 = uap->tp;
764	if (p32) {
765		sg = stackgap_init();
766		p = stackgap_alloc(&sg, sizeof(struct timeval));
767		uap->tp = (struct timeval32 *)p;
768	}
769	error = gettimeofday(td, (struct gettimeofday_args *) uap);
770	if (error)
771		return (error);
772	if (p32) {
773		error = copyin(p, &s, sizeof(s));
774		if (error)
775			return (error);
776		CP(s, s32, tv_sec);
777		CP(s, s32, tv_usec);
778		error = copyout(&s32, p32, sizeof(s32));
779		if (error)
780			return (error);
781	}
782	return (error);
783}
784
785int
786freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
787{
788	int error;
789	caddr_t sg;
790	struct rusage32 *p32, s32;
791	struct rusage *p = NULL, s;
792
793	p32 = uap->rusage;
794	if (p32) {
795		sg = stackgap_init();
796		p = stackgap_alloc(&sg, sizeof(struct rusage));
797		uap->rusage = (struct rusage32 *)p;
798	}
799	error = getrusage(td, (struct getrusage_args *) uap);
800	if (error)
801		return (error);
802	if (p32) {
803		error = copyin(p, &s, sizeof(s));
804		if (error)
805			return (error);
806		TV_CP(s, s32, ru_utime);
807		TV_CP(s, s32, ru_stime);
808		CP(s, s32, ru_maxrss);
809		CP(s, s32, ru_ixrss);
810		CP(s, s32, ru_idrss);
811		CP(s, s32, ru_isrss);
812		CP(s, s32, ru_minflt);
813		CP(s, s32, ru_majflt);
814		CP(s, s32, ru_nswap);
815		CP(s, s32, ru_inblock);
816		CP(s, s32, ru_oublock);
817		CP(s, s32, ru_msgsnd);
818		CP(s, s32, ru_msgrcv);
819		CP(s, s32, ru_nsignals);
820		CP(s, s32, ru_nvcsw);
821		CP(s, s32, ru_nivcsw);
822		error = copyout(&s32, p32, sizeof(s32));
823	}
824	return (error);
825}
826
827struct iovec32 {
828	u_int32_t iov_base;
829	int	iov_len;
830};
831#define	STACKGAPLEN	400
832
833CTASSERT(sizeof(struct iovec32) == 8);
834
835int
836freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
837{
838	int error, osize, nsize, i;
839	caddr_t sg;
840	struct readv_args /* {
841		syscallarg(int) fd;
842		syscallarg(struct iovec *) iovp;
843		syscallarg(u_int) iovcnt;
844	} */ a;
845	struct iovec32 *oio;
846	struct iovec *nio;
847
848	sg = stackgap_init();
849
850	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
851		return (EINVAL);
852
853	osize = uap->iovcnt * sizeof (struct iovec32);
854	nsize = uap->iovcnt * sizeof (struct iovec);
855
856	oio = malloc(osize, M_TEMP, M_WAITOK);
857	nio = malloc(nsize, M_TEMP, M_WAITOK);
858
859	error = 0;
860	if ((error = copyin(uap->iovp, oio, osize)))
861		goto punt;
862	for (i = 0; i < uap->iovcnt; i++) {
863		nio[i].iov_base = PTRIN(oio[i].iov_base);
864		nio[i].iov_len = oio[i].iov_len;
865	}
866
867	a.fd = uap->fd;
868	a.iovp = stackgap_alloc(&sg, nsize);
869	a.iovcnt = uap->iovcnt;
870
871	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
872		goto punt;
873	error = readv(td, &a);
874
875punt:
876	free(oio, M_TEMP);
877	free(nio, M_TEMP);
878	return (error);
879}
880
881int
882freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
883{
884	int error, i, nsize, osize;
885	caddr_t sg;
886	struct writev_args /* {
887		syscallarg(int) fd;
888		syscallarg(struct iovec *) iovp;
889		syscallarg(u_int) iovcnt;
890	} */ a;
891	struct iovec32 *oio;
892	struct iovec *nio;
893
894	sg = stackgap_init();
895
896	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
897		return (EINVAL);
898
899	osize = uap->iovcnt * sizeof (struct iovec32);
900	nsize = uap->iovcnt * sizeof (struct iovec);
901
902	oio = malloc(osize, M_TEMP, M_WAITOK);
903	nio = malloc(nsize, M_TEMP, M_WAITOK);
904
905	error = 0;
906	if ((error = copyin(uap->iovp, oio, osize)))
907		goto punt;
908	for (i = 0; i < uap->iovcnt; i++) {
909		nio[i].iov_base = PTRIN(oio[i].iov_base);
910		nio[i].iov_len = oio[i].iov_len;
911	}
912
913	a.fd = uap->fd;
914	a.iovp = stackgap_alloc(&sg, nsize);
915	a.iovcnt = uap->iovcnt;
916
917	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
918		goto punt;
919	error = writev(td, &a);
920
921punt:
922	free(oio, M_TEMP);
923	free(nio, M_TEMP);
924	return (error);
925}
926
927int
928freebsd32_settimeofday(struct thread *td,
929		       struct freebsd32_settimeofday_args *uap)
930{
931	int error;
932	caddr_t sg;
933	struct timeval32 *p32, s32;
934	struct timeval *p = NULL, s;
935
936	p32 = uap->tv;
937	if (p32) {
938		sg = stackgap_init();
939		p = stackgap_alloc(&sg, sizeof(struct timeval));
940		uap->tv = (struct timeval32 *)p;
941		error = copyin(p32, &s32, sizeof(s32));
942		if (error)
943			return (error);
944		CP(s32, s, tv_sec);
945		CP(s32, s, tv_usec);
946		error = copyout(&s, p, sizeof(s));
947		if (error)
948			return (error);
949	}
950	return (settimeofday(td, (struct settimeofday_args *) uap));
951}
952
953int
954freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
955{
956	int error;
957	caddr_t sg;
958	struct timeval32 *p32, s32[2];
959	struct timeval *p = NULL, s[2];
960
961	p32 = uap->tptr;
962	if (p32) {
963		sg = stackgap_init();
964		p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
965		uap->tptr = (struct timeval32 *)p;
966		error = copyin(p32, s32, sizeof(s32));
967		if (error)
968			return (error);
969		CP(s32[0], s[0], tv_sec);
970		CP(s32[0], s[0], tv_usec);
971		CP(s32[1], s[1], tv_sec);
972		CP(s32[1], s[1], tv_usec);
973		error = copyout(s, p, sizeof(s));
974		if (error)
975			return (error);
976	}
977	return (utimes(td, (struct utimes_args *) uap));
978}
979
980int
981freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
982{
983	int error;
984	caddr_t sg;
985	struct timeval32 *p32, *op32, s32;
986	struct timeval *p = NULL, *op = NULL, s;
987
988	p32 = uap->delta;
989	if (p32) {
990		sg = stackgap_init();
991		p = stackgap_alloc(&sg, sizeof(struct timeval));
992		uap->delta = (struct timeval32 *)p;
993		error = copyin(p32, &s32, sizeof(s32));
994		if (error)
995			return (error);
996		CP(s32, s, tv_sec);
997		CP(s32, s, tv_usec);
998		error = copyout(&s, p, sizeof(s));
999		if (error)
1000			return (error);
1001	}
1002	op32 = uap->olddelta;
1003	if (op32) {
1004		sg = stackgap_init();
1005		op = stackgap_alloc(&sg, sizeof(struct timeval));
1006		uap->olddelta = (struct timeval32 *)op;
1007	}
1008	error = utimes(td, (struct utimes_args *) uap);
1009	if (error)
1010		return error;
1011	if (op32) {
1012		error = copyin(op, &s, sizeof(s));
1013		if (error)
1014			return (error);
1015		CP(s, s32, tv_sec);
1016		CP(s, s32, tv_usec);
1017		error = copyout(&s32, op32, sizeof(s32));
1018	}
1019	return (error);
1020}
1021
1022int
1023freebsd32_statfs(struct thread *td, struct freebsd32_statfs_args *uap)
1024{
1025	int error;
1026	caddr_t sg;
1027	struct statfs32 *p32, s32;
1028	struct statfs *p = NULL, s;
1029
1030	p32 = uap->buf;
1031	if (p32) {
1032		sg = stackgap_init();
1033		p = stackgap_alloc(&sg, sizeof(struct statfs));
1034		uap->buf = (struct statfs32 *)p;
1035	}
1036	error = statfs(td, (struct statfs_args *) uap);
1037	if (error)
1038		return (error);
1039	if (p32) {
1040		error = copyin(p, &s, sizeof(s));
1041		if (error)
1042			return (error);
1043		copy_statfs(&s, &s32);
1044		error = copyout(&s32, p32, sizeof(s32));
1045	}
1046	return (error);
1047}
1048
1049int
1050freebsd32_fstatfs(struct thread *td, struct freebsd32_fstatfs_args *uap)
1051{
1052	int error;
1053	caddr_t sg;
1054	struct statfs32 *p32, s32;
1055	struct statfs *p = NULL, s;
1056
1057	p32 = uap->buf;
1058	if (p32) {
1059		sg = stackgap_init();
1060		p = stackgap_alloc(&sg, sizeof(struct statfs));
1061		uap->buf = (struct statfs32 *)p;
1062	}
1063	error = fstatfs(td, (struct fstatfs_args *) uap);
1064	if (error)
1065		return (error);
1066	if (p32) {
1067		error = copyin(p, &s, sizeof(s));
1068		if (error)
1069			return (error);
1070		copy_statfs(&s, &s32);
1071		error = copyout(&s32, p32, sizeof(s32));
1072	}
1073	return (error);
1074}
1075
1076int
1077freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1078{
1079	/*
1080	 * Vector through to semsys if it is loaded.
1081	 */
1082	return sysent[169].sy_call(td, uap);
1083}
1084
1085int
1086freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1087{
1088	/*
1089	 * Vector through to msgsys if it is loaded.
1090	 */
1091	return sysent[170].sy_call(td, uap);
1092}
1093
1094int
1095freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1096{
1097	/*
1098	 * Vector through to shmsys if it is loaded.
1099	 */
1100	return sysent[171].sy_call(td, uap);
1101}
1102
1103int
1104freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1105{
1106	struct pread_args ap;
1107
1108	ap.fd = uap->fd;
1109	ap.buf = uap->buf;
1110	ap.nbyte = uap->nbyte;
1111	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1112	return (pread(td, &ap));
1113}
1114
1115int
1116freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1117{
1118	struct pwrite_args ap;
1119
1120	ap.fd = uap->fd;
1121	ap.buf = uap->buf;
1122	ap.nbyte = uap->nbyte;
1123	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1124	return (pwrite(td, &ap));
1125}
1126
1127int
1128freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1129{
1130	int error;
1131	struct lseek_args ap;
1132	off_t pos;
1133
1134	ap.fd = uap->fd;
1135	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1136	ap.whence = uap->whence;
1137	error = lseek(td, &ap);
1138	/* Expand the quad return into two parts for eax and edx */
1139	pos = *(off_t *)(td->td_retval);
1140	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1141	td->td_retval[1] = pos >> 32;		/* %edx */
1142	return error;
1143}
1144
1145int
1146freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1147{
1148	struct truncate_args ap;
1149
1150	ap.path = uap->path;
1151	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1152	return (truncate(td, &ap));
1153}
1154
1155int
1156freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1157{
1158	struct ftruncate_args ap;
1159
1160	ap.fd = uap->fd;
1161	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1162	return (ftruncate(td, &ap));
1163}
1164
1165#ifdef COMPAT_FREEBSD4
1166int
1167freebsd4_freebsd32_sendfile(struct thread *td,
1168    struct freebsd4_freebsd32_sendfile_args *uap)
1169{
1170	struct freebsd4_sendfile_args ap;
1171
1172	ap.fd = uap->fd;
1173	ap.s = uap->s;
1174	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1175	ap.nbytes = uap->nbytes;	/* XXX check */
1176	ap.hdtr = uap->hdtr;		/* XXX check */
1177	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1178	ap.flags = uap->flags;
1179	return (freebsd4_sendfile(td, &ap));
1180}
1181#endif
1182
1183int
1184freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1185{
1186	struct sendfile_args ap;
1187
1188	ap.fd = uap->fd;
1189	ap.s = uap->s;
1190	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1191	ap.nbytes = uap->nbytes;	/* XXX check */
1192	ap.hdtr = uap->hdtr;		/* XXX check */
1193	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1194	ap.flags = uap->flags;
1195	return (sendfile(td, &ap));
1196}
1197
1198struct stat32 {
1199	udev_t	st_dev;
1200	ino_t	st_ino;
1201	mode_t	st_mode;
1202	nlink_t	st_nlink;
1203	uid_t	st_uid;
1204	gid_t	st_gid;
1205	udev_t	st_rdev;
1206	struct timespec32 st_atimespec;
1207	struct timespec32 st_mtimespec;
1208	struct timespec32 st_ctimespec;
1209	off_t	st_size;
1210	int64_t	st_blocks;
1211	u_int32_t st_blksize;
1212	u_int32_t st_flags;
1213	u_int32_t st_gen;
1214	struct timespec32 st_birthtimespec;
1215	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1216	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1217};
1218
1219
1220CTASSERT(sizeof(struct stat32) == 96);
1221
1222static void
1223copy_stat( struct stat *in, struct stat32 *out)
1224{
1225	CP(*in, *out, st_dev);
1226	CP(*in, *out, st_ino);
1227	CP(*in, *out, st_mode);
1228	CP(*in, *out, st_nlink);
1229	CP(*in, *out, st_uid);
1230	CP(*in, *out, st_gid);
1231	CP(*in, *out, st_rdev);
1232	TS_CP(*in, *out, st_atimespec);
1233	TS_CP(*in, *out, st_mtimespec);
1234	TS_CP(*in, *out, st_ctimespec);
1235	CP(*in, *out, st_size);
1236	CP(*in, *out, st_blocks);
1237	CP(*in, *out, st_blksize);
1238	CP(*in, *out, st_flags);
1239	CP(*in, *out, st_gen);
1240}
1241
1242int
1243freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1244{
1245	int error;
1246	caddr_t sg;
1247	struct stat32 *p32, s32;
1248	struct stat *p = NULL, s;
1249
1250	p32 = uap->ub;
1251	if (p32) {
1252		sg = stackgap_init();
1253		p = stackgap_alloc(&sg, sizeof(struct stat));
1254		uap->ub = (struct stat32 *)p;
1255	}
1256	error = stat(td, (struct stat_args *) uap);
1257	if (error)
1258		return (error);
1259	if (p32) {
1260		error = copyin(p, &s, sizeof(s));
1261		if (error)
1262			return (error);
1263		copy_stat(&s, &s32);
1264		error = copyout(&s32, p32, sizeof(s32));
1265	}
1266	return (error);
1267}
1268
1269int
1270freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1271{
1272	int error;
1273	caddr_t sg;
1274	struct stat32 *p32, s32;
1275	struct stat *p = NULL, s;
1276
1277	p32 = uap->ub;
1278	if (p32) {
1279		sg = stackgap_init();
1280		p = stackgap_alloc(&sg, sizeof(struct stat));
1281		uap->ub = (struct stat32 *)p;
1282	}
1283	error = fstat(td, (struct fstat_args *) uap);
1284	if (error)
1285		return (error);
1286	if (p32) {
1287		error = copyin(p, &s, sizeof(s));
1288		if (error)
1289			return (error);
1290		copy_stat(&s, &s32);
1291		error = copyout(&s32, p32, sizeof(s32));
1292	}
1293	return (error);
1294}
1295
1296int
1297freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1298{
1299	int error;
1300	caddr_t sg;
1301	struct stat32 *p32, s32;
1302	struct stat *p = NULL, s;
1303
1304	p32 = uap->ub;
1305	if (p32) {
1306		sg = stackgap_init();
1307		p = stackgap_alloc(&sg, sizeof(struct stat));
1308		uap->ub = (struct stat32 *)p;
1309	}
1310	error = lstat(td, (struct lstat_args *) uap);
1311	if (error)
1312		return (error);
1313	if (p32) {
1314		error = copyin(p, &s, sizeof(s));
1315		if (error)
1316			return (error);
1317		copy_stat(&s, &s32);
1318		error = copyout(&s32, p32, sizeof(s32));
1319	}
1320	return (error);
1321}
1322
1323/*
1324 * MPSAFE
1325 */
1326int
1327freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1328{
1329	int error, name[CTL_MAXNAME];
1330	size_t j, oldlen;
1331
1332	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1333		return (EINVAL);
1334
1335 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1336 	if (error)
1337		return (error);
1338
1339	mtx_lock(&Giant);
1340
1341	if (uap->oldlenp)
1342		oldlen = fuword32(uap->oldlenp);
1343	else
1344		oldlen = 0;
1345	error = userland_sysctl(td, name, uap->namelen,
1346		uap->old, &oldlen, 1,
1347		uap->new, uap->newlen, &j);
1348	if (error && error != ENOMEM)
1349		goto done2;
1350	if (uap->oldlenp) {
1351		suword32(uap->oldlenp, j);
1352	}
1353done2:
1354	mtx_unlock(&Giant);
1355	return (error);
1356}
1357
1358struct sigaction32 {
1359	u_int32_t	sa_u;
1360	int		sa_flags;
1361	sigset_t	sa_mask;
1362};
1363
1364CTASSERT(sizeof(struct sigaction32) == 24);
1365
1366int
1367freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1368{
1369	struct sigaction32 s32;
1370	struct sigaction sa, osa, *sap;
1371	int error;
1372
1373	if (uap->act) {
1374		error = copyin(uap->act, &s32, sizeof(s32));
1375		if (error)
1376			return (error);
1377		sa.sa_handler = PTRIN(s32.sa_u);
1378		CP(s32, sa, sa_flags);
1379		CP(s32, sa, sa_mask);
1380		sap = &sa;
1381	} else
1382		sap = NULL;
1383	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1384	if (error != 0 && uap->oact != NULL) {
1385		s32.sa_u = PTROUT(osa.sa_handler);
1386		CP(osa, s32, sa_flags);
1387		CP(osa, s32, sa_mask);
1388		error = copyout(&s32, uap->oact, sizeof(s32));
1389	}
1390	return (error);
1391}
1392
1393#ifdef COMPAT_FREEBSD4
1394int
1395freebsd4_freebsd32_sigaction(struct thread *td,
1396			     struct freebsd4_freebsd32_sigaction_args *uap)
1397{
1398	struct sigaction32 s32;
1399	struct sigaction sa, osa, *sap;
1400	int error;
1401
1402	if (uap->act) {
1403		error = copyin(uap->act, &s32, sizeof(s32));
1404		if (error)
1405			return (error);
1406		sa.sa_handler = PTRIN(s32.sa_u);
1407		CP(s32, sa, sa_flags);
1408		CP(s32, sa, sa_mask);
1409		sap = &sa;
1410	} else
1411		sap = NULL;
1412	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1413	if (error != 0 && uap->oact != NULL) {
1414		s32.sa_u = PTROUT(osa.sa_handler);
1415		CP(osa, s32, sa_flags);
1416		CP(osa, s32, sa_mask);
1417		error = copyout(&s32, uap->oact, sizeof(s32));
1418	}
1419	return (error);
1420}
1421#endif
1422
1423#if 0
1424
1425int
1426freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1427{
1428	int error;
1429	caddr_t sg;
1430	struct yyy32 *p32, s32;
1431	struct yyy *p = NULL, s;
1432
1433	p32 = uap->zzz;
1434	if (p32) {
1435		sg = stackgap_init();
1436		p = stackgap_alloc(&sg, sizeof(struct yyy));
1437		uap->zzz = (struct yyy32 *)p;
1438		error = copyin(p32, &s32, sizeof(s32));
1439		if (error)
1440			return (error);
1441		/* translate in */
1442		error = copyout(&s, p, sizeof(s));
1443		if (error)
1444			return (error);
1445	}
1446	error = xxx(td, (struct xxx_args *) uap);
1447	if (error)
1448		return (error);
1449	if (p32) {
1450		error = copyin(p, &s, sizeof(s));
1451		if (error)
1452			return (error);
1453		/* translate out */
1454		error = copyout(&s32, p32, sizeof(s32));
1455	}
1456	return (error);
1457}
1458
1459#endif
1460