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