freebsd32_misc.c revision 123744
155714Skris/*-
255714Skris * Copyright (c) 2002 Doug Rabson
355714Skris * All rights reserved.
455714Skris *
555714Skris * Redistribution and use in source and binary forms, with or without
655714Skris * modification, are permitted provided that the following conditions
755714Skris * are met:
8280304Sjkim * 1. Redistributions of source code must retain the above copyright
955714Skris *    notice, this list of conditions and the following disclaimer.
1055714Skris * 2. Redistributions in binary form must reproduce the above copyright
1155714Skris *    notice, this list of conditions and the following disclaimer in the
1255714Skris *    documentation and/or other materials provided with the distribution.
1355714Skris *
1455714Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15280304Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1655714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1755714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1855714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1955714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2055714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2155714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22280304Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2355714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2455714Skris * SUCH DAMAGE.
2555714Skris */
2655714Skris
2755714Skris#include <sys/cdefs.h>
2855714Skris__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 123744 2003-12-23 02:48:11Z peter $");
2955714Skris
3055714Skris#include "opt_compat.h"
3155714Skris
3255714Skris#include <sys/param.h>
3355714Skris#include <sys/systm.h>
3455714Skris#include <sys/bus.h>
3555714Skris#include <sys/exec.h>
3655714Skris#include <sys/fcntl.h>
37280304Sjkim#include <sys/filedesc.h>
3855714Skris#include <sys/imgact.h>
3955714Skris#include <sys/kernel.h>
40280304Sjkim#include <sys/lock.h>
4155714Skris#include <sys/malloc.h>
4255714Skris#include <sys/file.h>		/* Must come after sys/malloc.h */
4355714Skris#include <sys/mman.h>
4455714Skris#include <sys/module.h>
4555714Skris#include <sys/mount.h>
4655714Skris#include <sys/mutex.h>
4755714Skris#include <sys/namei.h>
4855714Skris#include <sys/param.h>
4955714Skris#include <sys/proc.h>
5055714Skris#include <sys/reboot.h>
5155714Skris#include <sys/resource.h>
52280304Sjkim#include <sys/resourcevar.h>
5355714Skris#include <sys/selinfo.h>
5455714Skris#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
5555714Skris#include <sys/signal.h>
5655714Skris#include <sys/signalvar.h>
5755714Skris#include <sys/socket.h>
5855714Skris#include <sys/socketvar.h>
5955714Skris#include <sys/stat.h>
6055714Skris#include <sys/syscallsubr.h>
61238405Sjkim#include <sys/sysctl.h>
62109998Smarkm#include <sys/sysent.h>
6355714Skris#include <sys/sysproto.h>
64238405Sjkim#include <sys/systm.h>
6555714Skris#include <sys/unistd.h>
66280304Sjkim#include <sys/user.h>
67280304Sjkim#include <sys/utsname.h>
68238405Sjkim#include <sys/vnode.h>
6955714Skris
70109998Smarkm#include <vm/vm.h>
71280304Sjkim#include <vm/vm_kern.h>
72280304Sjkim#include <vm/vm_param.h>
73280304Sjkim#include <vm/pmap.h>
74109998Smarkm#include <vm/vm_map.h>
7555714Skris#include <vm/vm_object.h>
76238405Sjkim#include <vm/vm_extern.h>
77238405Sjkim
78280304Sjkim#include <compat/freebsd32/freebsd32_util.h>
79280304Sjkim#include <compat/freebsd32/freebsd32.h>
80238405Sjkim#include <compat/freebsd32/freebsd32_proto.h>
81280304Sjkim
82280304SjkimCTASSERT(sizeof(struct timeval32) == 8);
83280304SjkimCTASSERT(sizeof(struct timespec32) == 8);
84280304SjkimCTASSERT(sizeof(struct statfs32) == 256);
85280304SjkimCTASSERT(sizeof(struct rusage32) == 72);
86280304Sjkim
87238405Sjkimint
88238405Sjkimfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
89238405Sjkim{
90280304Sjkim	int error;
91280304Sjkim	caddr_t sg;
92280304Sjkim	struct rusage32 *rusage32, ru32;
93280304Sjkim	struct rusage *rusage = NULL, ru;
94109998Smarkm
95238405Sjkim	rusage32 = uap->rusage;
96280304Sjkim	if (rusage32) {
97109998Smarkm		sg = stackgap_init();
98280304Sjkim		rusage = stackgap_alloc(&sg, sizeof(struct rusage));
9955714Skris		uap->rusage = (struct rusage32 *)rusage;
100280304Sjkim	}
101280304Sjkim	error = wait4(td, (struct wait_args *)uap);
102280304Sjkim	if (error)
103280304Sjkim		return (error);
104280304Sjkim	if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
105280304Sjkim		TV_CP(ru, ru32, ru_utime);
106280304Sjkim		TV_CP(ru, ru32, ru_stime);
107280304Sjkim		CP(ru, ru32, ru_maxrss);
108280304Sjkim		CP(ru, ru32, ru_ixrss);
109280304Sjkim		CP(ru, ru32, ru_idrss);
110280304Sjkim		CP(ru, ru32, ru_isrss);
111280304Sjkim		CP(ru, ru32, ru_minflt);
112109998Smarkm		CP(ru, ru32, ru_majflt);
11355714Skris		CP(ru, ru32, ru_nswap);
11455714Skris		CP(ru, ru32, ru_inblock);
115142425Snectar		CP(ru, ru32, ru_oublock);
116280304Sjkim		CP(ru, ru32, ru_msgsnd);
117280304Sjkim		CP(ru, ru32, ru_msgrcv);
118280304Sjkim		CP(ru, ru32, ru_nsignals);
119280304Sjkim		CP(ru, ru32, ru_nvcsw);
120280304Sjkim		CP(ru, ru32, ru_nivcsw);
121280304Sjkim		error = copyout(&ru32, rusage32, sizeof(ru32));
122280304Sjkim	}
123142425Snectar	return (error);
12455714Skris}
125280304Sjkim
126280304Sjkimstatic void
127280304Sjkimcopy_statfs(struct statfs *in, struct statfs32 *out)
128238405Sjkim{
129238405Sjkim	CP(*in, *out, f_bsize);
130238405Sjkim	CP(*in, *out, f_iosize);
131280304Sjkim	CP(*in, *out, f_blocks);
132238405Sjkim	CP(*in, *out, f_bfree);
133280304Sjkim	CP(*in, *out, f_bavail);
134280304Sjkim	CP(*in, *out, f_files);
135280304Sjkim	CP(*in, *out, f_ffree);
136238405Sjkim	CP(*in, *out, f_fsid);
137280304Sjkim	CP(*in, *out, f_owner);
138238405Sjkim	CP(*in, *out, f_type);
139280304Sjkim	CP(*in, *out, f_flags);
140280304Sjkim	CP(*in, *out, f_flags);
141280304Sjkim	CP(*in, *out, f_syncwrites);
142280304Sjkim	CP(*in, *out, f_asyncwrites);
143280304Sjkim	bcopy(in->f_fstypename,
144280304Sjkim	      out->f_fstypename, MFSNAMELEN);
145280304Sjkim	bcopy(in->f_mntonname,
146280304Sjkim	      out->f_mntonname, MNAMELEN);
147280304Sjkim	CP(*in, *out, f_syncreads);
148280304Sjkim	CP(*in, *out, f_asyncreads);
149280304Sjkim	bcopy(in->f_mntfromname,
150280304Sjkim	      out->f_mntfromname, MNAMELEN);
151238405Sjkim}
152280304Sjkim
153280304Sjkimint
154280304Sjkimfreebsd32_getfsstat(struct thread *td, struct freebsd32_getfsstat_args *uap)
155280304Sjkim{
156280304Sjkim	int error;
157280304Sjkim	caddr_t sg;
158280304Sjkim	struct statfs32 *sp32, stat32;
159280304Sjkim	struct statfs *sp = NULL, stat;
160280304Sjkim	int maxcount, count, i;
161280304Sjkim
162280304Sjkim	sp32 = uap->buf;
163238405Sjkim	maxcount = uap->bufsize / sizeof(struct statfs32);
164280304Sjkim
165280304Sjkim	if (sp32) {
166280304Sjkim		sg = stackgap_init();
167280304Sjkim		sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
168280304Sjkim		uap->buf = (struct statfs32 *)sp;
169238405Sjkim	}
170280304Sjkim	error = getfsstat(td, (struct getfsstat_args *) uap);
171280304Sjkim	if (sp32 && !error) {
172280304Sjkim		count = td->td_retval[0];
173280304Sjkim		for (i = 0; i < count; i++) {
174280304Sjkim			error = copyin(&sp[i], &stat, sizeof(stat));
175238405Sjkim			if (error)
176280304Sjkim				return (error);
177238405Sjkim			copy_statfs(&stat, &stat32);
178280304Sjkim			error = copyout(&stat32, &sp32[i], sizeof(stat32));
179238405Sjkim			if (error)
180280304Sjkim				return (error);
181280304Sjkim		}
182280304Sjkim	}
183280304Sjkim	return (error);
184280304Sjkim}
185280304Sjkim
186280304Sjkimstruct sigaltstack32 {
187280304Sjkim	u_int32_t	ss_sp;
188280304Sjkim	u_int32_t	ss_size;
189238405Sjkim	int		ss_flags;
190280304Sjkim};
191238405Sjkim
192280304SjkimCTASSERT(sizeof(struct sigaltstack32) == 12);
193238405Sjkim
194280304Sjkimint
195238405Sjkimfreebsd32_sigaltstack(struct thread *td,
196280304Sjkim		      struct freebsd32_sigaltstack_args *uap)
197280304Sjkim{
198238405Sjkim	struct sigaltstack32 s32;
199238405Sjkim	struct sigaltstack ss, oss, *ssp;
200238405Sjkim	int error;
201280304Sjkim
202280304Sjkim	if (uap->ss != NULL) {
203280304Sjkim		error = copyin(uap->ss, &s32, sizeof(s32));
204280304Sjkim		if (error)
205280304Sjkim			return (error);
206280304Sjkim		PTRIN_CP(s32, ss, ss_sp);
207238405Sjkim		CP(s32, ss, ss_size);
208280304Sjkim		CP(s32, ss, ss_flags);
209280304Sjkim		ssp = &ss;
210280304Sjkim	} else
211280304Sjkim		ssp = NULL;
212280304Sjkim	error = kern_sigaltstack(td, ssp, &oss);
213280304Sjkim	if (error == 0 && uap->oss != NULL) {
214280304Sjkim		PTROUT_CP(oss, s32, ss_sp);
215280304Sjkim		CP(oss, s32, ss_size);
216280304Sjkim		CP(oss, s32, ss_flags);
217280304Sjkim		error = copyout(&s32, uap->oss, sizeof(s32));
218280304Sjkim	}
219280304Sjkim	return (error);
220280304Sjkim}
221238405Sjkim
222280304Sjkimint
223238405Sjkimfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
224280304Sjkim{
225238405Sjkim	int error;
226280304Sjkim	caddr_t sg;
227280304Sjkim	struct execve_args ap;
228280304Sjkim	u_int32_t *p32, arg;
229280304Sjkim	char **p, *p64;
230280304Sjkim	int count;
231238405Sjkim
232280304Sjkim	sg = stackgap_init();
233280304Sjkim	ap.fname = uap->fname;
234280304Sjkim
235238405Sjkim	if (uap->argv) {
236280304Sjkim		count = 0;
237280304Sjkim		p32 = uap->argv;
238238405Sjkim		do {
239280304Sjkim			error = copyin(p32++, &arg, sizeof(arg));
240280304Sjkim			if (error)
241280304Sjkim				return error;
242280304Sjkim			count++;
243280304Sjkim		} while (arg != 0);
244280304Sjkim		p = stackgap_alloc(&sg, count * sizeof(char *));
245238405Sjkim		ap.argv = p;
246280304Sjkim		p32 = uap->argv;
247280304Sjkim		do {
248280304Sjkim			error = copyin(p32++, &arg, sizeof(arg));
249280304Sjkim			if (error)
250280304Sjkim				return error;
251280304Sjkim			p64 = PTRIN(arg);
252238405Sjkim			error = copyout(&p64, p++, sizeof(p64));
253280304Sjkim			if (error)
254238405Sjkim				return error;
255280304Sjkim		} while (arg != 0);
256280304Sjkim	}
257280304Sjkim	if (uap->envv) {
258280304Sjkim		count = 0;
259280304Sjkim		p32 = uap->envv;
260280304Sjkim		do {
261280304Sjkim			error = copyin(p32++, &arg, sizeof(arg));
262280304Sjkim			if (error)
263280304Sjkim				return error;
264280304Sjkim			count++;
265280304Sjkim		} while (arg != 0);
266280304Sjkim		p = stackgap_alloc(&sg, count * sizeof(char *));
267280304Sjkim		ap.envv = p;
268280304Sjkim		p32 = uap->envv;
269280304Sjkim		do {
270280304Sjkim			error = copyin(p32++, &arg, sizeof(arg));
271238405Sjkim			if (error)
272280304Sjkim				return error;
273280304Sjkim			p64 = PTRIN(arg);
274238405Sjkim			error = copyout(&p64, p++, sizeof(p64));
275280304Sjkim			if (error)
276280304Sjkim				return error;
277280304Sjkim		} while (arg != 0);
278280304Sjkim	}
279280304Sjkim
280238405Sjkim	return execve(td, &ap);
281280304Sjkim}
282280304Sjkim
283280304Sjkim#ifdef __ia64__
284280304Sjkimstatic int
285280304Sjkimfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
286280304Sjkim		       int prot, int fd, off_t pos)
287280304Sjkim{
288280304Sjkim	vm_map_t map;
289280304Sjkim	vm_map_entry_t entry;
290280304Sjkim	int rv;
291280304Sjkim
292280304Sjkim	map = &td->td_proc->p_vmspace->vm_map;
293280304Sjkim	if (fd != -1)
294280304Sjkim		prot |= VM_PROT_WRITE;
295280304Sjkim
296280304Sjkim	if (vm_map_lookup_entry(map, start, &entry)) {
297238405Sjkim		if ((entry->protection & prot) != prot) {
298238405Sjkim			rv = vm_map_protect(map,
299238405Sjkim					    trunc_page(start),
300238405Sjkim					    round_page(end),
301280304Sjkim					    entry->protection | prot,
302280304Sjkim					    FALSE);
303280304Sjkim			if (rv != KERN_SUCCESS)
304280304Sjkim				return (EINVAL);
305280304Sjkim		}
306280304Sjkim	} else {
307280304Sjkim		vm_offset_t addr = trunc_page(start);
308280304Sjkim		rv = vm_map_find(map, 0, 0,
309280304Sjkim				 &addr, PAGE_SIZE, FALSE, prot,
310280304Sjkim				 VM_PROT_ALL, 0);
311280304Sjkim		if (rv != KERN_SUCCESS)
312280304Sjkim			return (EINVAL);
313280304Sjkim	}
314280304Sjkim
315280304Sjkim	if (fd != -1) {
316280304Sjkim		struct pread_args r;
317238405Sjkim		r.fd = fd;
318280304Sjkim		r.buf = (void *) start;
319280304Sjkim		r.nbyte = end - start;
320238405Sjkim		r.offset = pos;
321280304Sjkim		return (pread(td, &r));
322280304Sjkim	} else {
323238405Sjkim		while (start < end) {
324280304Sjkim			subyte((void *) start, 0);
325280304Sjkim			start++;
326280304Sjkim		}
327280304Sjkim		return (0);
328280304Sjkim	}
329280304Sjkim}
330280304Sjkim#endif
331280304Sjkim
332238405Sjkimint
333280304Sjkimfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
334280304Sjkim{
335238405Sjkim	struct mmap_args ap;
336238405Sjkim	vm_offset_t addr = (vm_offset_t) uap->addr;
337280304Sjkim	vm_size_t len	 = uap->len;
338280304Sjkim	int prot	 = uap->prot;
339280304Sjkim	int flags	 = uap->flags;
340109998Smarkm	int fd		 = uap->fd;
34155714Skris	off_t pos	 = (uap->poslo
342109998Smarkm			    | ((off_t)uap->poshi << 32));
343280304Sjkim#ifdef __ia64__
344109998Smarkm	vm_size_t pageoff;
345280304Sjkim	int error;
346109998Smarkm
347280304Sjkim	/*
348109998Smarkm	 * Attempt to handle page size hassles.
34955714Skris	 */
350280304Sjkim	pageoff = (pos & PAGE_MASK);
351280304Sjkim	if (flags & MAP_FIXED) {
352280304Sjkim		vm_offset_t start, end;
353280304Sjkim		start = addr;
354280304Sjkim		end = addr + len;
355280304Sjkim
35655714Skris		if (start != trunc_page(start)) {
357109998Smarkm			error = freebsd32_mmap_partial(td, start,
358109998Smarkm						       round_page(start), prot,
359280304Sjkim						       fd, pos);
360280304Sjkim			if (fd != -1)
361280304Sjkim				pos += round_page(start) - start;
362280304Sjkim			start = round_page(start);
363280304Sjkim		}
364280304Sjkim		if (end != round_page(end)) {
365280304Sjkim			vm_offset_t t = trunc_page(end);
366280304Sjkim			error = freebsd32_mmap_partial(td, t, end,
367280304Sjkim						  prot, fd,
368280304Sjkim						  pos + t - start);
369109998Smarkm			end = trunc_page(end);
370109998Smarkm		}
371238405Sjkim		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
372280304Sjkim			/*
373280304Sjkim			 * We can't map this region at all. The specified
374280304Sjkim			 * address doesn't have the same alignment as the file
375280304Sjkim			 * position. Fake the mapping by simply reading the
376280304Sjkim			 * entire region into memory. First we need to make
377238405Sjkim			 * sure the region exists.
378238405Sjkim			 */
379280304Sjkim			vm_map_t map;
380280304Sjkim			struct pread_args r;
381280304Sjkim			int rv;
382280304Sjkim
383280304Sjkim			prot |= VM_PROT_WRITE;
384280304Sjkim			map = &td->td_proc->p_vmspace->vm_map;
385238405Sjkim			rv = vm_map_remove(map, start, end);
386238405Sjkim			if (rv != KERN_SUCCESS)
387280304Sjkim				return (EINVAL);
388280304Sjkim			rv = vm_map_find(map, 0, 0,
389280304Sjkim					 &start, end - start, FALSE,
390280304Sjkim					 prot, VM_PROT_ALL, 0);
391280304Sjkim			if (rv != KERN_SUCCESS)
392280304Sjkim				return (EINVAL);
393280304Sjkim			r.fd = fd;
394238405Sjkim			r.buf = (void *) start;
395238405Sjkim			r.nbyte = end - start;
396280304Sjkim			r.offset = pos;
397280304Sjkim			error = pread(td, &r);
398280304Sjkim			if (error)
399280304Sjkim				return (error);
400238405Sjkim
401238405Sjkim			td->td_retval[0] = addr;
402280304Sjkim			return (0);
403280304Sjkim		}
404280304Sjkim		if (end == start) {
405238405Sjkim			/*
406280304Sjkim			 * After dealing with the ragged ends, there
407280304Sjkim			 * might be none left.
408280304Sjkim			 */
409280304Sjkim			td->td_retval[0] = addr;
410280304Sjkim			return (0);
411280304Sjkim		}
412280304Sjkim		addr = start;
413238405Sjkim		len = end - start;
414280304Sjkim	}
415280304Sjkim#endif
416238405Sjkim
417280304Sjkim	ap.addr = (void *) addr;
418280304Sjkim	ap.len = len;
419280304Sjkim	ap.prot = prot;
420280304Sjkim	ap.flags = flags;
421280304Sjkim	ap.fd = fd;
422280304Sjkim	ap.pos = pos;
423280304Sjkim
424280304Sjkim	return (mmap(td, &ap));
425238405Sjkim}
426280304Sjkim
427238405Sjkimstruct itimerval32 {
428238405Sjkim	struct timeval32 it_interval;
429280304Sjkim	struct timeval32 it_value;
430280304Sjkim};
431280304Sjkim
432280304SjkimCTASSERT(sizeof(struct itimerval32) == 16);
433280304Sjkim
434280304Sjkimint
435280304Sjkimfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
436280304Sjkim{
437280304Sjkim	int error;
438280304Sjkim	caddr_t sg;
439280304Sjkim	struct itimerval32 *p32, *op32, s32;
440280304Sjkim	struct itimerval *p = NULL, *op = NULL, s;
441280304Sjkim
442280304Sjkim	p32 = uap->itv;
443280304Sjkim	if (p32) {
444280304Sjkim		sg = stackgap_init();
445280304Sjkim		p = stackgap_alloc(&sg, sizeof(struct itimerval));
446280304Sjkim		uap->itv = (struct itimerval32 *)p;
447280304Sjkim		error = copyin(p32, &s32, sizeof(s32));
448280304Sjkim		if (error)
449280304Sjkim			return (error);
450280304Sjkim		TV_CP(s32, s, it_interval);
451280304Sjkim		TV_CP(s32, s, it_value);
452280304Sjkim		error = copyout(&s, p, sizeof(s));
453280304Sjkim		if (error)
454280304Sjkim			return (error);
455280304Sjkim	}
456280304Sjkim	op32 = uap->oitv;
457280304Sjkim	if (op32) {
458280304Sjkim		sg = stackgap_init();
459280304Sjkim		op = stackgap_alloc(&sg, sizeof(struct itimerval));
460280304Sjkim		uap->oitv = (struct itimerval32 *)op;
461280304Sjkim	}
462238405Sjkim	error = setitimer(td, (struct setitimer_args *) uap);
463238405Sjkim	if (error)
464280304Sjkim		return (error);
465280304Sjkim	if (op32) {
466280304Sjkim		error = copyin(op, &s, sizeof(s));
467280304Sjkim		if (error)
468280304Sjkim			return (error);
469280304Sjkim		TV_CP(s, s32, it_interval);
470238405Sjkim		TV_CP(s, s32, it_value);
471280304Sjkim		error = copyout(&s32, op32, sizeof(s32));
472280304Sjkim	}
473280304Sjkim	return (error);
474280304Sjkim}
475280304Sjkim
476280304Sjkimint
477280304Sjkimfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
478280304Sjkim{
479280304Sjkim	int error;
480280304Sjkim	caddr_t sg;
481280304Sjkim	struct timeval32 *p32, s32;
482280304Sjkim	struct timeval *p = NULL, s;
483280304Sjkim
484280304Sjkim	p32 = uap->tv;
485280304Sjkim	if (p32) {
486280304Sjkim		sg = stackgap_init();
487280304Sjkim		p = stackgap_alloc(&sg, sizeof(struct timeval));
488280304Sjkim		uap->tv = (struct timeval32 *)p;
489280304Sjkim		error = copyin(p32, &s32, sizeof(s32));
490280304Sjkim		if (error)
491238405Sjkim			return (error);
492238405Sjkim		CP(s32, s, tv_sec);
493280304Sjkim		CP(s32, s, tv_usec);
494280304Sjkim		error = copyout(&s, p, sizeof(s));
495280304Sjkim		if (error)
496280304Sjkim			return (error);
497280304Sjkim	}
498238405Sjkim	/*
499238405Sjkim	 * XXX big-endian needs to convert the fd_sets too.
500280304Sjkim	 */
501280304Sjkim	return (select(td, (struct select_args *) uap));
502280304Sjkim}
503238405Sjkim
504238405Sjkimstruct kevent32 {
505280304Sjkim	u_int32_t	ident;		/* identifier for this event */
506280304Sjkim	short		filter;		/* filter for event */
507280304Sjkim	u_short		flags;
508238405Sjkim	u_int		fflags;
50955714Skris	int32_t		data;
510280304Sjkim	u_int32_t	udata;		/* opaque user data identifier */
51155714Skris};
512280304Sjkim
51355714SkrisCTASSERT(sizeof(struct kevent32) == 20);
514280304Sjkim
51555714Skrisint
516freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
517{
518	int error;
519	caddr_t sg;
520	struct timespec32 ts32;
521	struct timespec ts;
522	struct kevent32 ks32;
523	struct kevent *ks;
524	struct kevent_args a;
525	int i;
526
527	sg = stackgap_init();
528
529	a.fd = uap->fd;
530	a.changelist = uap->changelist;
531	a.nchanges = uap->nchanges;
532	a.eventlist = uap->eventlist;
533	a.nevents = uap->nevents;
534	a.timeout = NULL;
535
536	if (uap->timeout) {
537		a.timeout = stackgap_alloc(&sg, sizeof(struct timespec));
538		error = copyin(uap->timeout, &ts32, sizeof(ts32));
539		if (error)
540			return (error);
541		CP(ts32, ts, tv_sec);
542		CP(ts32, ts, tv_nsec);
543		error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts));
544		if (error)
545			return (error);
546	}
547	if (uap->changelist) {
548		a.changelist = (struct kevent *)stackgap_alloc(&sg,
549		    uap->nchanges * sizeof(struct kevent));
550		for (i = 0; i < uap->nchanges; i++) {
551			error = copyin(&uap->changelist[i], &ks32,
552			    sizeof(ks32));
553			if (error)
554				return (error);
555			ks = (struct kevent *)(uintptr_t)&a.changelist[i];
556			CP(ks32, *ks, ident);
557			CP(ks32, *ks, filter);
558			CP(ks32, *ks, flags);
559			CP(ks32, *ks, fflags);
560			CP(ks32, *ks, data);
561			PTRIN_CP(ks32, *ks, udata);
562		}
563	}
564	if (uap->eventlist) {
565		a.eventlist = stackgap_alloc(&sg,
566		    uap->nevents * sizeof(struct kevent));
567	}
568	error = kevent(td, &a);
569	if (uap->eventlist && error > 0) {
570		for (i = 0; i < error; i++) {
571			ks = &a.eventlist[i];
572			CP(*ks, ks32, ident);
573			CP(*ks, ks32, filter);
574			CP(*ks, ks32, flags);
575			CP(*ks, ks32, fflags);
576			CP(*ks, ks32, data);
577			PTROUT_CP(*ks, ks32, udata);
578			error = copyout(&ks32, &uap->eventlist[i],
579			    sizeof(ks32));
580			if (error)
581				return (error);
582		}
583	}
584	return error;
585}
586
587int
588freebsd32_gettimeofday(struct thread *td,
589		       struct freebsd32_gettimeofday_args *uap)
590{
591	struct timeval atv;
592	struct timeval32 atv32;
593	struct timezone rtz;
594	int error = 0;
595
596	if (uap->tp) {
597		microtime(&atv);
598		CP(atv, atv32, tv_sec);
599		CP(atv, atv32, tv_usec);
600		error = copyout(&atv32, uap->tp, sizeof (atv32));
601	}
602	if (error == 0 && uap->tzp != NULL) {
603		rtz.tz_minuteswest = tz_minuteswest;
604		rtz.tz_dsttime = tz_dsttime;
605		error = copyout(&rtz, uap->tzp, sizeof (rtz));
606	}
607	return (error);
608}
609
610int
611freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
612{
613	int error;
614	caddr_t sg;
615	struct rusage32 *p32, s32;
616	struct rusage *p = NULL, s;
617
618	p32 = uap->rusage;
619	if (p32) {
620		sg = stackgap_init();
621		p = stackgap_alloc(&sg, sizeof(struct rusage));
622		uap->rusage = (struct rusage32 *)p;
623	}
624	error = getrusage(td, (struct getrusage_args *) uap);
625	if (error)
626		return (error);
627	if (p32) {
628		error = copyin(p, &s, sizeof(s));
629		if (error)
630			return (error);
631		TV_CP(s, s32, ru_utime);
632		TV_CP(s, s32, ru_stime);
633		CP(s, s32, ru_maxrss);
634		CP(s, s32, ru_ixrss);
635		CP(s, s32, ru_idrss);
636		CP(s, s32, ru_isrss);
637		CP(s, s32, ru_minflt);
638		CP(s, s32, ru_majflt);
639		CP(s, s32, ru_nswap);
640		CP(s, s32, ru_inblock);
641		CP(s, s32, ru_oublock);
642		CP(s, s32, ru_msgsnd);
643		CP(s, s32, ru_msgrcv);
644		CP(s, s32, ru_nsignals);
645		CP(s, s32, ru_nvcsw);
646		CP(s, s32, ru_nivcsw);
647		error = copyout(&s32, p32, sizeof(s32));
648	}
649	return (error);
650}
651
652struct iovec32 {
653	u_int32_t iov_base;
654	int	iov_len;
655};
656#define	STACKGAPLEN	400
657
658CTASSERT(sizeof(struct iovec32) == 8);
659
660int
661freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
662{
663	int error, osize, nsize, i;
664	caddr_t sg;
665	struct readv_args /* {
666		syscallarg(int) fd;
667		syscallarg(struct iovec *) iovp;
668		syscallarg(u_int) iovcnt;
669	} */ a;
670	struct iovec32 *oio;
671	struct iovec *nio;
672
673	sg = stackgap_init();
674
675	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
676		return (EINVAL);
677
678	osize = uap->iovcnt * sizeof (struct iovec32);
679	nsize = uap->iovcnt * sizeof (struct iovec);
680
681	oio = malloc(osize, M_TEMP, M_WAITOK);
682	nio = malloc(nsize, M_TEMP, M_WAITOK);
683
684	error = 0;
685	if ((error = copyin(uap->iovp, oio, osize)))
686		goto punt;
687	for (i = 0; i < uap->iovcnt; i++) {
688		nio[i].iov_base = PTRIN(oio[i].iov_base);
689		nio[i].iov_len = oio[i].iov_len;
690	}
691
692	a.fd = uap->fd;
693	a.iovp = stackgap_alloc(&sg, nsize);
694	a.iovcnt = uap->iovcnt;
695
696	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
697		goto punt;
698	error = readv(td, &a);
699
700punt:
701	free(oio, M_TEMP);
702	free(nio, M_TEMP);
703	return (error);
704}
705
706int
707freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
708{
709	int error, i, nsize, osize;
710	caddr_t sg;
711	struct writev_args /* {
712		syscallarg(int) fd;
713		syscallarg(struct iovec *) iovp;
714		syscallarg(u_int) iovcnt;
715	} */ a;
716	struct iovec32 *oio;
717	struct iovec *nio;
718
719	sg = stackgap_init();
720
721	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
722		return (EINVAL);
723
724	osize = uap->iovcnt * sizeof (struct iovec32);
725	nsize = uap->iovcnt * sizeof (struct iovec);
726
727	oio = malloc(osize, M_TEMP, M_WAITOK);
728	nio = malloc(nsize, M_TEMP, M_WAITOK);
729
730	error = 0;
731	if ((error = copyin(uap->iovp, oio, osize)))
732		goto punt;
733	for (i = 0; i < uap->iovcnt; i++) {
734		nio[i].iov_base = PTRIN(oio[i].iov_base);
735		nio[i].iov_len = oio[i].iov_len;
736	}
737
738	a.fd = uap->fd;
739	a.iovp = stackgap_alloc(&sg, nsize);
740	a.iovcnt = uap->iovcnt;
741
742	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
743		goto punt;
744	error = writev(td, &a);
745
746punt:
747	free(oio, M_TEMP);
748	free(nio, M_TEMP);
749	return (error);
750}
751
752int
753freebsd32_settimeofday(struct thread *td,
754		       struct freebsd32_settimeofday_args *uap)
755{
756	int error;
757	caddr_t sg;
758	struct timeval32 *p32, s32;
759	struct timeval *p = NULL, s;
760
761	p32 = uap->tv;
762	if (p32) {
763		sg = stackgap_init();
764		p = stackgap_alloc(&sg, sizeof(struct timeval));
765		uap->tv = (struct timeval32 *)p;
766		error = copyin(p32, &s32, sizeof(s32));
767		if (error)
768			return (error);
769		CP(s32, s, tv_sec);
770		CP(s32, s, tv_usec);
771		error = copyout(&s, p, sizeof(s));
772		if (error)
773			return (error);
774	}
775	return (settimeofday(td, (struct settimeofday_args *) uap));
776}
777
778int
779freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
780{
781	int error;
782	caddr_t sg;
783	struct timeval32 *p32, s32[2];
784	struct timeval *p = NULL, s[2];
785
786	p32 = uap->tptr;
787	if (p32) {
788		sg = stackgap_init();
789		p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
790		uap->tptr = (struct timeval32 *)p;
791		error = copyin(p32, s32, sizeof(s32));
792		if (error)
793			return (error);
794		CP(s32[0], s[0], tv_sec);
795		CP(s32[0], s[0], tv_usec);
796		CP(s32[1], s[1], tv_sec);
797		CP(s32[1], s[1], tv_usec);
798		error = copyout(s, p, sizeof(s));
799		if (error)
800			return (error);
801	}
802	return (utimes(td, (struct utimes_args *) uap));
803}
804
805int
806freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
807{
808	int error;
809	caddr_t sg;
810	struct timeval32 *p32, *op32, s32;
811	struct timeval *p = NULL, *op = NULL, s;
812
813	p32 = uap->delta;
814	if (p32) {
815		sg = stackgap_init();
816		p = stackgap_alloc(&sg, sizeof(struct timeval));
817		uap->delta = (struct timeval32 *)p;
818		error = copyin(p32, &s32, sizeof(s32));
819		if (error)
820			return (error);
821		CP(s32, s, tv_sec);
822		CP(s32, s, tv_usec);
823		error = copyout(&s, p, sizeof(s));
824		if (error)
825			return (error);
826	}
827	op32 = uap->olddelta;
828	if (op32) {
829		sg = stackgap_init();
830		op = stackgap_alloc(&sg, sizeof(struct timeval));
831		uap->olddelta = (struct timeval32 *)op;
832	}
833	error = utimes(td, (struct utimes_args *) uap);
834	if (error)
835		return error;
836	if (op32) {
837		error = copyin(op, &s, sizeof(s));
838		if (error)
839			return (error);
840		CP(s, s32, tv_sec);
841		CP(s, s32, tv_usec);
842		error = copyout(&s32, op32, sizeof(s32));
843	}
844	return (error);
845}
846
847int
848freebsd32_statfs(struct thread *td, struct freebsd32_statfs_args *uap)
849{
850	int error;
851	caddr_t sg;
852	struct statfs32 *p32, s32;
853	struct statfs *p = NULL, s;
854
855	p32 = uap->buf;
856	if (p32) {
857		sg = stackgap_init();
858		p = stackgap_alloc(&sg, sizeof(struct statfs));
859		uap->buf = (struct statfs32 *)p;
860	}
861	error = statfs(td, (struct statfs_args *) uap);
862	if (error)
863		return (error);
864	if (p32) {
865		error = copyin(p, &s, sizeof(s));
866		if (error)
867			return (error);
868		copy_statfs(&s, &s32);
869		error = copyout(&s32, p32, sizeof(s32));
870	}
871	return (error);
872}
873
874int
875freebsd32_fstatfs(struct thread *td, struct freebsd32_fstatfs_args *uap)
876{
877	int error;
878	caddr_t sg;
879	struct statfs32 *p32, s32;
880	struct statfs *p = NULL, s;
881
882	p32 = uap->buf;
883	if (p32) {
884		sg = stackgap_init();
885		p = stackgap_alloc(&sg, sizeof(struct statfs));
886		uap->buf = (struct statfs32 *)p;
887	}
888	error = fstatfs(td, (struct fstatfs_args *) uap);
889	if (error)
890		return (error);
891	if (p32) {
892		error = copyin(p, &s, sizeof(s));
893		if (error)
894			return (error);
895		copy_statfs(&s, &s32);
896		error = copyout(&s32, p32, sizeof(s32));
897	}
898	return (error);
899}
900
901int
902freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
903{
904	/*
905	 * Vector through to semsys if it is loaded.
906	 */
907	return sysent[169].sy_call(td, uap);
908}
909
910int
911freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
912{
913	/*
914	 * Vector through to msgsys if it is loaded.
915	 */
916	return sysent[170].sy_call(td, uap);
917}
918
919int
920freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
921{
922	/*
923	 * Vector through to shmsys if it is loaded.
924	 */
925	return sysent[171].sy_call(td, uap);
926}
927
928int
929freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
930{
931	struct pread_args ap;
932
933	ap.fd = uap->fd;
934	ap.buf = uap->buf;
935	ap.nbyte = uap->nbyte;
936	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
937	return (pread(td, &ap));
938}
939
940int
941freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
942{
943	struct pwrite_args ap;
944
945	ap.fd = uap->fd;
946	ap.buf = uap->buf;
947	ap.nbyte = uap->nbyte;
948	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
949	return (pwrite(td, &ap));
950}
951
952int
953freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
954{
955	int error;
956	struct lseek_args ap;
957	off_t pos;
958
959	ap.fd = uap->fd;
960	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
961	ap.whence = uap->whence;
962	error = lseek(td, &ap);
963	/* Expand the quad return into two parts for eax and edx */
964	pos = *(off_t *)(td->td_retval);
965	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
966	td->td_retval[1] = pos >> 32;		/* %edx */
967	return error;
968}
969
970int
971freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
972{
973	struct truncate_args ap;
974
975	ap.path = uap->path;
976	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
977	return (truncate(td, &ap));
978}
979
980int
981freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
982{
983	struct ftruncate_args ap;
984
985	ap.fd = uap->fd;
986	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
987	return (ftruncate(td, &ap));
988}
989
990#ifdef COMPAT_FREEBSD4
991int
992freebsd4_freebsd32_sendfile(struct thread *td,
993    struct freebsd4_freebsd32_sendfile_args *uap)
994{
995	struct freebsd4_sendfile_args ap;
996
997	ap.fd = uap->fd;
998	ap.s = uap->s;
999	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1000	ap.nbytes = uap->nbytes;	/* XXX check */
1001	ap.hdtr = uap->hdtr;		/* XXX check */
1002	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1003	ap.flags = uap->flags;
1004	return (freebsd4_sendfile(td, &ap));
1005}
1006#endif
1007
1008int
1009freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1010{
1011	struct sendfile_args ap;
1012
1013	ap.fd = uap->fd;
1014	ap.s = uap->s;
1015	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1016	ap.nbytes = uap->nbytes;	/* XXX check */
1017	ap.hdtr = uap->hdtr;		/* XXX check */
1018	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1019	ap.flags = uap->flags;
1020	return (sendfile(td, &ap));
1021}
1022
1023struct stat32 {
1024	udev_t	st_dev;
1025	ino_t	st_ino;
1026	mode_t	st_mode;
1027	nlink_t	st_nlink;
1028	uid_t	st_uid;
1029	gid_t	st_gid;
1030	udev_t	st_rdev;
1031	struct timespec32 st_atimespec;
1032	struct timespec32 st_mtimespec;
1033	struct timespec32 st_ctimespec;
1034	off_t	st_size;
1035	int64_t	st_blocks;
1036	u_int32_t st_blksize;
1037	u_int32_t st_flags;
1038	u_int32_t st_gen;
1039	struct timespec32 st_birthtimespec;
1040	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1041	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1042};
1043
1044
1045CTASSERT(sizeof(struct stat32) == 96);
1046
1047static void
1048copy_stat( struct stat *in, struct stat32 *out)
1049{
1050	CP(*in, *out, st_dev);
1051	CP(*in, *out, st_ino);
1052	CP(*in, *out, st_mode);
1053	CP(*in, *out, st_nlink);
1054	CP(*in, *out, st_uid);
1055	CP(*in, *out, st_gid);
1056	CP(*in, *out, st_rdev);
1057	TS_CP(*in, *out, st_atimespec);
1058	TS_CP(*in, *out, st_mtimespec);
1059	TS_CP(*in, *out, st_ctimespec);
1060	CP(*in, *out, st_size);
1061	CP(*in, *out, st_blocks);
1062	CP(*in, *out, st_blksize);
1063	CP(*in, *out, st_flags);
1064	CP(*in, *out, st_gen);
1065}
1066
1067int
1068freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1069{
1070	int error;
1071	caddr_t sg;
1072	struct stat32 *p32, s32;
1073	struct stat *p = NULL, s;
1074
1075	p32 = uap->ub;
1076	if (p32) {
1077		sg = stackgap_init();
1078		p = stackgap_alloc(&sg, sizeof(struct stat));
1079		uap->ub = (struct stat32 *)p;
1080	}
1081	error = stat(td, (struct stat_args *) uap);
1082	if (error)
1083		return (error);
1084	if (p32) {
1085		error = copyin(p, &s, sizeof(s));
1086		if (error)
1087			return (error);
1088		copy_stat(&s, &s32);
1089		error = copyout(&s32, p32, sizeof(s32));
1090	}
1091	return (error);
1092}
1093
1094int
1095freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1096{
1097	int error;
1098	caddr_t sg;
1099	struct stat32 *p32, s32;
1100	struct stat *p = NULL, s;
1101
1102	p32 = uap->ub;
1103	if (p32) {
1104		sg = stackgap_init();
1105		p = stackgap_alloc(&sg, sizeof(struct stat));
1106		uap->ub = (struct stat32 *)p;
1107	}
1108	error = fstat(td, (struct fstat_args *) uap);
1109	if (error)
1110		return (error);
1111	if (p32) {
1112		error = copyin(p, &s, sizeof(s));
1113		if (error)
1114			return (error);
1115		copy_stat(&s, &s32);
1116		error = copyout(&s32, p32, sizeof(s32));
1117	}
1118	return (error);
1119}
1120
1121int
1122freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1123{
1124	int error;
1125	caddr_t sg;
1126	struct stat32 *p32, s32;
1127	struct stat *p = NULL, s;
1128
1129	p32 = uap->ub;
1130	if (p32) {
1131		sg = stackgap_init();
1132		p = stackgap_alloc(&sg, sizeof(struct stat));
1133		uap->ub = (struct stat32 *)p;
1134	}
1135	error = lstat(td, (struct lstat_args *) uap);
1136	if (error)
1137		return (error);
1138	if (p32) {
1139		error = copyin(p, &s, sizeof(s));
1140		if (error)
1141			return (error);
1142		copy_stat(&s, &s32);
1143		error = copyout(&s32, p32, sizeof(s32));
1144	}
1145	return (error);
1146}
1147
1148/*
1149 * MPSAFE
1150 */
1151int
1152freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1153{
1154	int error, name[CTL_MAXNAME];
1155	size_t j, oldlen;
1156
1157	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1158		return (EINVAL);
1159
1160 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1161 	if (error)
1162		return (error);
1163
1164	mtx_lock(&Giant);
1165
1166	if (uap->oldlenp)
1167		oldlen = fuword32(uap->oldlenp);
1168	else
1169		oldlen = 0;
1170	error = userland_sysctl(td, name, uap->namelen,
1171		uap->old, &oldlen, 1,
1172		uap->new, uap->newlen, &j);
1173	if (error && error != ENOMEM)
1174		goto done2;
1175	if (uap->oldlenp) {
1176		suword32(uap->oldlenp, j);
1177	}
1178done2:
1179	mtx_unlock(&Giant);
1180	return (error);
1181}
1182
1183struct sigaction32 {
1184	u_int32_t	sa_u;
1185	int		sa_flags;
1186	sigset_t	sa_mask;
1187};
1188
1189CTASSERT(sizeof(struct sigaction32) == 24);
1190
1191int
1192freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1193{
1194	struct sigaction32 s32;
1195	struct sigaction sa, osa, *sap;
1196	int error;
1197
1198	if (uap->act) {
1199		error = copyin(uap->act, &s32, sizeof(s32));
1200		if (error)
1201			return (error);
1202		sa.sa_handler = PTRIN(s32.sa_u);
1203		CP(s32, sa, sa_flags);
1204		CP(s32, sa, sa_mask);
1205		sap = &sa;
1206	} else
1207		sap = NULL;
1208	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1209	if (error != 0 && uap->oact != NULL) {
1210		s32.sa_u = PTROUT(osa.sa_handler);
1211		CP(osa, s32, sa_flags);
1212		CP(osa, s32, sa_mask);
1213		error = copyout(&s32, uap->oact, sizeof(s32));
1214	}
1215	return (error);
1216}
1217
1218#ifdef COMPAT_FREEBSD4
1219int
1220freebsd4_freebsd32_sigaction(struct thread *td,
1221			     struct freebsd4_freebsd32_sigaction_args *uap)
1222{
1223	struct sigaction32 s32;
1224	struct sigaction sa, osa, *sap;
1225	int error;
1226
1227	if (uap->act) {
1228		error = copyin(uap->act, &s32, sizeof(s32));
1229		if (error)
1230			return (error);
1231		sa.sa_handler = PTRIN(s32.sa_u);
1232		CP(s32, sa, sa_flags);
1233		CP(s32, sa, sa_mask);
1234		sap = &sa;
1235	} else
1236		sap = NULL;
1237	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1238	if (error != 0 && uap->oact != NULL) {
1239		s32.sa_u = PTROUT(osa.sa_handler);
1240		CP(osa, s32, sa_flags);
1241		CP(osa, s32, sa_mask);
1242		error = copyout(&s32, uap->oact, sizeof(s32));
1243	}
1244	return (error);
1245}
1246#endif
1247
1248#if 0
1249
1250int
1251freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1252{
1253	int error;
1254	caddr_t sg;
1255	struct yyy32 *p32, s32;
1256	struct yyy *p = NULL, s;
1257
1258	p32 = uap->zzz;
1259	if (p32) {
1260		sg = stackgap_init();
1261		p = stackgap_alloc(&sg, sizeof(struct yyy));
1262		uap->zzz = (struct yyy32 *)p;
1263		error = copyin(p32, &s32, sizeof(s32));
1264		if (error)
1265			return (error);
1266		/* translate in */
1267		error = copyout(&s, p, sizeof(s));
1268		if (error)
1269			return (error);
1270	}
1271	error = xxx(td, (struct xxx_args *) uap);
1272	if (error)
1273		return (error);
1274	if (p32) {
1275		error = copyin(p, &s, sizeof(s));
1276		if (error)
1277			return (error);
1278		/* translate out */
1279		error = copyout(&s32, p32, sizeof(s32));
1280	}
1281	return (error);
1282}
1283
1284#endif
1285