freebsd32_misc.c revision 142934
1100384Speter/*-
2100384Speter * Copyright (c) 2002 Doug Rabson
3100384Speter * All rights reserved.
4100384Speter *
5100384Speter * Redistribution and use in source and binary forms, with or without
6100384Speter * modification, are permitted provided that the following conditions
7100384Speter * are met:
8100384Speter * 1. Redistributions of source code must retain the above copyright
9100384Speter *    notice, this list of conditions and the following disclaimer.
10100384Speter * 2. Redistributions in binary form must reproduce the above copyright
11100384Speter *    notice, this list of conditions and the following disclaimer in the
12100384Speter *    documentation and/or other materials provided with the distribution.
13100384Speter *
14100384Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15100384Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16100384Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17100384Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18100384Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19100384Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20100384Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21100384Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22100384Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23100384Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24100384Speter * SUCH DAMAGE.
25100384Speter */
26100384Speter
27118031Sobrien#include <sys/cdefs.h>
28118031Sobrien__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 142934 2005-03-01 17:45:55Z ps $");
29118031Sobrien
30104738Speter#include "opt_compat.h"
31104738Speter
32100384Speter#include <sys/param.h>
33100384Speter#include <sys/systm.h>
34100384Speter#include <sys/bus.h>
35100384Speter#include <sys/exec.h>
36100384Speter#include <sys/fcntl.h>
37100384Speter#include <sys/filedesc.h>
38123746Speter#include <sys/namei.h>
39100384Speter#include <sys/imgact.h>
40100384Speter#include <sys/kernel.h>
41100384Speter#include <sys/lock.h>
42100384Speter#include <sys/malloc.h>
43100384Speter#include <sys/file.h>		/* Must come after sys/malloc.h */
44100384Speter#include <sys/mman.h>
45100384Speter#include <sys/module.h>
46100384Speter#include <sys/mount.h>
47100384Speter#include <sys/mutex.h>
48100384Speter#include <sys/namei.h>
49100384Speter#include <sys/param.h>
50100384Speter#include <sys/proc.h>
51100384Speter#include <sys/reboot.h>
52100384Speter#include <sys/resource.h>
53100384Speter#include <sys/resourcevar.h>
54100384Speter#include <sys/selinfo.h>
55100384Speter#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
56100384Speter#include <sys/signal.h>
57100384Speter#include <sys/signalvar.h>
58100384Speter#include <sys/socket.h>
59100384Speter#include <sys/socketvar.h>
60100384Speter#include <sys/stat.h>
61113859Sjhb#include <sys/syscallsubr.h>
62100384Speter#include <sys/sysctl.h>
63100384Speter#include <sys/sysent.h>
64100384Speter#include <sys/sysproto.h>
65100384Speter#include <sys/systm.h>
66100384Speter#include <sys/unistd.h>
67100384Speter#include <sys/vnode.h>
68127140Sjhb#include <sys/wait.h>
69100384Speter
70100384Speter#include <vm/vm.h>
71100384Speter#include <vm/vm_kern.h>
72100384Speter#include <vm/vm_param.h>
73100384Speter#include <vm/pmap.h>
74100384Speter#include <vm/vm_map.h>
75100384Speter#include <vm/vm_object.h>
76100384Speter#include <vm/vm_extern.h>
77100384Speter
78119333Speter#include <compat/freebsd32/freebsd32_util.h>
79119333Speter#include <compat/freebsd32/freebsd32.h>
80119333Speter#include <compat/freebsd32/freebsd32_proto.h>
81100384Speter
82121719SpeterCTASSERT(sizeof(struct timeval32) == 8);
83121719SpeterCTASSERT(sizeof(struct timespec32) == 8);
84121719SpeterCTASSERT(sizeof(struct statfs32) == 256);
85121719SpeterCTASSERT(sizeof(struct rusage32) == 72);
86121719Speter
87100384Speterint
88119333Speterfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
89100384Speter{
90127140Sjhb	int error, status;
91127140Sjhb	struct rusage32 ru32;
92136152Sjhb	struct rusage ru, *rup;
93100384Speter
94136152Sjhb	if (uap->rusage != NULL)
95136152Sjhb		rup = &ru;
96136152Sjhb	else
97136152Sjhb		rup = NULL;
98136152Sjhb	error = kern_wait(td, uap->pid, &status, uap->options, rup);
99100384Speter	if (error)
100100384Speter		return (error);
101127140Sjhb	if (uap->status != NULL)
102127140Sjhb		error = copyout(&status, uap->status, sizeof(status));
103127140Sjhb	if (uap->rusage != NULL && error == 0) {
104100384Speter		TV_CP(ru, ru32, ru_utime);
105100384Speter		TV_CP(ru, ru32, ru_stime);
106100384Speter		CP(ru, ru32, ru_maxrss);
107100384Speter		CP(ru, ru32, ru_ixrss);
108100384Speter		CP(ru, ru32, ru_idrss);
109100384Speter		CP(ru, ru32, ru_isrss);
110100384Speter		CP(ru, ru32, ru_minflt);
111100384Speter		CP(ru, ru32, ru_majflt);
112100384Speter		CP(ru, ru32, ru_nswap);
113100384Speter		CP(ru, ru32, ru_inblock);
114100384Speter		CP(ru, ru32, ru_oublock);
115100384Speter		CP(ru, ru32, ru_msgsnd);
116100384Speter		CP(ru, ru32, ru_msgrcv);
117100384Speter		CP(ru, ru32, ru_nsignals);
118100384Speter		CP(ru, ru32, ru_nvcsw);
119100384Speter		CP(ru, ru32, ru_nivcsw);
120127140Sjhb		error = copyout(&ru32, uap->rusage, sizeof(ru32));
121100384Speter	}
122100384Speter	return (error);
123100384Speter}
124100384Speter
125128597Smarcel#ifdef COMPAT_FREEBSD4
126100384Speterstatic void
127100384Spetercopy_statfs(struct statfs *in, struct statfs32 *out)
128100384Speter{
129100384Speter	CP(*in, *out, f_bsize);
130100384Speter	CP(*in, *out, f_iosize);
131100384Speter	CP(*in, *out, f_blocks);
132100384Speter	CP(*in, *out, f_bfree);
133100384Speter	CP(*in, *out, f_bavail);
134100384Speter	CP(*in, *out, f_files);
135100384Speter	CP(*in, *out, f_ffree);
136100384Speter	CP(*in, *out, f_fsid);
137100384Speter	CP(*in, *out, f_owner);
138100384Speter	CP(*in, *out, f_type);
139100384Speter	CP(*in, *out, f_flags);
140100384Speter	CP(*in, *out, f_flags);
141100384Speter	CP(*in, *out, f_syncwrites);
142100384Speter	CP(*in, *out, f_asyncwrites);
143100384Speter	bcopy(in->f_fstypename,
144100384Speter	      out->f_fstypename, MFSNAMELEN);
145100384Speter	bcopy(in->f_mntonname,
146128260Speter	      out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
147100384Speter	CP(*in, *out, f_syncreads);
148100384Speter	CP(*in, *out, f_asyncreads);
149100384Speter	bcopy(in->f_mntfromname,
150128260Speter	      out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
151100384Speter}
152128597Smarcel#endif
153100384Speter
154128597Smarcel#ifdef COMPAT_FREEBSD4
155100384Speterint
156128260Speterfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
157100384Speter{
158100384Speter	int error;
159100384Speter	caddr_t sg;
160100384Speter	struct statfs32 *sp32, stat32;
161100384Speter	struct statfs *sp = NULL, stat;
162100384Speter	int maxcount, count, i;
163100384Speter
164107849Salfred	sp32 = uap->buf;
165107849Salfred	maxcount = uap->bufsize / sizeof(struct statfs32);
166100384Speter
167100384Speter	if (sp32) {
168100384Speter		sg = stackgap_init();
169100384Speter		sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
170107849Salfred		uap->buf = (struct statfs32 *)sp;
171100384Speter	}
172100384Speter	error = getfsstat(td, (struct getfsstat_args *) uap);
173100384Speter	if (sp32 && !error) {
174100384Speter		count = td->td_retval[0];
175100384Speter		for (i = 0; i < count; i++) {
176100384Speter			error = copyin(&sp[i], &stat, sizeof(stat));
177100384Speter			if (error)
178100384Speter				return (error);
179100384Speter			copy_statfs(&stat, &stat32);
180100384Speter			error = copyout(&stat32, &sp32[i], sizeof(stat32));
181100384Speter			if (error)
182100384Speter				return (error);
183100384Speter		}
184100384Speter	}
185100384Speter	return (error);
186100384Speter}
187128597Smarcel#endif
188100384Speter
189100384Speterstruct sigaltstack32 {
190100384Speter	u_int32_t	ss_sp;
191100384Speter	u_int32_t	ss_size;
192100384Speter	int		ss_flags;
193100384Speter};
194100384Speter
195121719SpeterCTASSERT(sizeof(struct sigaltstack32) == 12);
196121719Speter
197100384Speterint
198119333Speterfreebsd32_sigaltstack(struct thread *td,
199119333Speter		      struct freebsd32_sigaltstack_args *uap)
200100384Speter{
201113859Sjhb	struct sigaltstack32 s32;
202113859Sjhb	struct sigaltstack ss, oss, *ssp;
203100384Speter	int error;
204100384Speter
205113859Sjhb	if (uap->ss != NULL) {
206113859Sjhb		error = copyin(uap->ss, &s32, sizeof(s32));
207100384Speter		if (error)
208100384Speter			return (error);
209113859Sjhb		PTRIN_CP(s32, ss, ss_sp);
210113859Sjhb		CP(s32, ss, ss_size);
211113859Sjhb		CP(s32, ss, ss_flags);
212113859Sjhb		ssp = &ss;
213113859Sjhb	} else
214113859Sjhb		ssp = NULL;
215113859Sjhb	error = kern_sigaltstack(td, ssp, &oss);
216113859Sjhb	if (error == 0 && uap->oss != NULL) {
217113859Sjhb		PTROUT_CP(oss, s32, ss_sp);
218113859Sjhb		CP(oss, s32, ss_size);
219113859Sjhb		CP(oss, s32, ss_flags);
220113859Sjhb		error = copyout(&s32, uap->oss, sizeof(s32));
221100384Speter	}
222100384Speter	return (error);
223100384Speter}
224100384Speter
225142059Sjhb/*
226142059Sjhb * Custom version of exec_copyin_args() so that we can translate
227142059Sjhb * the pointers.
228142059Sjhb */
229142059Sjhbstatic int
230142059Sjhbfreebsd32_exec_copyin_args(struct image_args *args, char *fname,
231142059Sjhb    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
232100384Speter{
233142059Sjhb	char *argp, *envp;
234142059Sjhb	u_int32_t *p32, arg;
235142059Sjhb	size_t length;
236100384Speter	int error;
237100384Speter
238142059Sjhb	bzero(args, sizeof(*args));
239142059Sjhb	if (argv == NULL)
240142059Sjhb		return (EFAULT);
241100384Speter
242142059Sjhb	/*
243142059Sjhb	 * Allocate temporary demand zeroed space for argument and
244142059Sjhb	 *	environment strings
245142059Sjhb	 */
246142059Sjhb	args->buf = (char *) kmem_alloc_wait(exec_map, PATH_MAX + ARG_MAX);
247142059Sjhb	if (args->buf == NULL)
248142059Sjhb		return (ENOMEM);
249142059Sjhb	args->begin_argv = args->buf;
250142059Sjhb	args->endp = args->begin_argv;
251142059Sjhb	args->stringspace = ARG_MAX;
252142059Sjhb
253142059Sjhb	args->fname = args->buf + ARG_MAX;
254142059Sjhb
255142059Sjhb	/*
256142059Sjhb	 * Copy the file name.
257142059Sjhb	 */
258142059Sjhb	error = (segflg == UIO_SYSSPACE) ?
259142059Sjhb	    copystr(fname, args->fname, PATH_MAX, &length) :
260142059Sjhb	    copyinstr(fname, args->fname, PATH_MAX, &length);
261142059Sjhb	if (error != 0)
262142059Sjhb		return (error);
263142059Sjhb
264142059Sjhb	/*
265142059Sjhb	 * extract arguments first
266142059Sjhb	 */
267142059Sjhb	p32 = argv;
268142059Sjhb	for (;;) {
269142059Sjhb		error = copyin(p32++, &arg, sizeof(arg));
270142059Sjhb		if (error)
271142059Sjhb			return (error);
272142059Sjhb		if (arg == 0)
273142059Sjhb			break;
274142059Sjhb		argp = PTRIN(arg);
275142059Sjhb		error = copyinstr(argp, args->endp, args->stringspace, &length);
276142059Sjhb		if (error) {
277142059Sjhb			if (error == ENAMETOOLONG)
278142059Sjhb				return (E2BIG);
279142059Sjhb			else
280142059Sjhb				return (error);
281142059Sjhb		}
282142059Sjhb		args->stringspace -= length;
283142059Sjhb		args->endp += length;
284142059Sjhb		args->argc++;
285100384Speter	}
286142059Sjhb
287142059Sjhb	args->begin_envv = args->endp;
288142059Sjhb
289142059Sjhb	/*
290142059Sjhb	 * extract environment strings
291142059Sjhb	 */
292142059Sjhb	if (envv) {
293142059Sjhb		p32 = envv;
294142059Sjhb		for (;;) {
295100384Speter			error = copyin(p32++, &arg, sizeof(arg));
296100384Speter			if (error)
297142059Sjhb				return (error);
298142059Sjhb			if (arg == 0)
299142059Sjhb				break;
300142059Sjhb			envp = PTRIN(arg);
301142059Sjhb			error = copyinstr(envp, args->endp, args->stringspace,
302142059Sjhb			    &length);
303142059Sjhb			if (error) {
304142059Sjhb				if (error == ENAMETOOLONG)
305142059Sjhb					return (E2BIG);
306142059Sjhb				else
307142059Sjhb					return (error);
308142059Sjhb			}
309142059Sjhb			args->stringspace -= length;
310142059Sjhb			args->endp += length;
311142059Sjhb			args->envc++;
312142059Sjhb		}
313100384Speter	}
314100384Speter
315142059Sjhb	return (0);
316100384Speter}
317100384Speter
318142059Sjhbint
319142059Sjhbfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
320142059Sjhb{
321142059Sjhb	struct image_args eargs;
322142059Sjhb	int error;
323142059Sjhb
324142059Sjhb	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
325142059Sjhb	    uap->argv, uap->envv);
326142059Sjhb	if (error == 0)
327142059Sjhb		error = kern_execve(td, &eargs, NULL);
328142059Sjhb	exec_free_args(&eargs);
329142059Sjhb	return (error);
330142059Sjhb}
331142059Sjhb
332114987Speter#ifdef __ia64__
333100384Speterstatic int
334119333Speterfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
335119333Speter		       int prot, int fd, off_t pos)
336100384Speter{
337100384Speter	vm_map_t map;
338100384Speter	vm_map_entry_t entry;
339100384Speter	int rv;
340100384Speter
341100384Speter	map = &td->td_proc->p_vmspace->vm_map;
342100384Speter	if (fd != -1)
343100384Speter		prot |= VM_PROT_WRITE;
344100384Speter
345100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
346100384Speter		if ((entry->protection & prot) != prot) {
347100384Speter			rv = vm_map_protect(map,
348100384Speter					    trunc_page(start),
349100384Speter					    round_page(end),
350100384Speter					    entry->protection | prot,
351100384Speter					    FALSE);
352100384Speter			if (rv != KERN_SUCCESS)
353100384Speter				return (EINVAL);
354100384Speter		}
355100384Speter	} else {
356100384Speter		vm_offset_t addr = trunc_page(start);
357100384Speter		rv = vm_map_find(map, 0, 0,
358100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
359100384Speter				 VM_PROT_ALL, 0);
360100384Speter		if (rv != KERN_SUCCESS)
361100384Speter			return (EINVAL);
362100384Speter	}
363100384Speter
364100384Speter	if (fd != -1) {
365100384Speter		struct pread_args r;
366107849Salfred		r.fd = fd;
367107849Salfred		r.buf = (void *) start;
368107849Salfred		r.nbyte = end - start;
369107849Salfred		r.offset = pos;
370100384Speter		return (pread(td, &r));
371100384Speter	} else {
372100384Speter		while (start < end) {
373100384Speter			subyte((void *) start, 0);
374100384Speter			start++;
375100384Speter		}
376100384Speter		return (0);
377100384Speter	}
378100384Speter}
379114987Speter#endif
380100384Speter
381100384Speterint
382119333Speterfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
383100384Speter{
384100384Speter	struct mmap_args ap;
385107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
386107849Salfred	vm_size_t len	 = uap->len;
387107849Salfred	int prot	 = uap->prot;
388107849Salfred	int flags	 = uap->flags;
389107849Salfred	int fd		 = uap->fd;
390107849Salfred	off_t pos	 = (uap->poslo
391107849Salfred			    | ((off_t)uap->poshi << 32));
392114987Speter#ifdef __ia64__
393100384Speter	vm_size_t pageoff;
394100384Speter	int error;
395100384Speter
396100384Speter	/*
397100384Speter	 * Attempt to handle page size hassles.
398100384Speter	 */
399100384Speter	pageoff = (pos & PAGE_MASK);
400100384Speter	if (flags & MAP_FIXED) {
401100384Speter		vm_offset_t start, end;
402100384Speter		start = addr;
403100384Speter		end = addr + len;
404100384Speter
405100384Speter		if (start != trunc_page(start)) {
406119333Speter			error = freebsd32_mmap_partial(td, start,
407119333Speter						       round_page(start), prot,
408119333Speter						       fd, pos);
409100384Speter			if (fd != -1)
410100384Speter				pos += round_page(start) - start;
411100384Speter			start = round_page(start);
412100384Speter		}
413100384Speter		if (end != round_page(end)) {
414100384Speter			vm_offset_t t = trunc_page(end);
415119333Speter			error = freebsd32_mmap_partial(td, t, end,
416100384Speter						  prot, fd,
417100384Speter						  pos + t - start);
418100384Speter			end = trunc_page(end);
419100384Speter		}
420100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
421100384Speter			/*
422100384Speter			 * We can't map this region at all. The specified
423100384Speter			 * address doesn't have the same alignment as the file
424100384Speter			 * position. Fake the mapping by simply reading the
425100384Speter			 * entire region into memory. First we need to make
426100384Speter			 * sure the region exists.
427100384Speter			 */
428100384Speter			vm_map_t map;
429100384Speter			struct pread_args r;
430100384Speter			int rv;
431100384Speter
432100384Speter			prot |= VM_PROT_WRITE;
433100384Speter			map = &td->td_proc->p_vmspace->vm_map;
434100384Speter			rv = vm_map_remove(map, start, end);
435100384Speter			if (rv != KERN_SUCCESS)
436100384Speter				return (EINVAL);
437100384Speter			rv = vm_map_find(map, 0, 0,
438100384Speter					 &start, end - start, FALSE,
439100384Speter					 prot, VM_PROT_ALL, 0);
440100384Speter			if (rv != KERN_SUCCESS)
441100384Speter				return (EINVAL);
442107849Salfred			r.fd = fd;
443107849Salfred			r.buf = (void *) start;
444107849Salfred			r.nbyte = end - start;
445107849Salfred			r.offset = pos;
446100384Speter			error = pread(td, &r);
447100384Speter			if (error)
448100384Speter				return (error);
449100384Speter
450100384Speter			td->td_retval[0] = addr;
451100384Speter			return (0);
452100384Speter		}
453100384Speter		if (end == start) {
454100384Speter			/*
455100384Speter			 * After dealing with the ragged ends, there
456100384Speter			 * might be none left.
457100384Speter			 */
458100384Speter			td->td_retval[0] = addr;
459100384Speter			return (0);
460100384Speter		}
461100384Speter		addr = start;
462100384Speter		len = end - start;
463100384Speter	}
464114987Speter#endif
465100384Speter
466107849Salfred	ap.addr = (void *) addr;
467107849Salfred	ap.len = len;
468107849Salfred	ap.prot = prot;
469107849Salfred	ap.flags = flags;
470107849Salfred	ap.fd = fd;
471107849Salfred	ap.pos = pos;
472100384Speter
473100384Speter	return (mmap(td, &ap));
474100384Speter}
475100384Speter
476100384Speterstruct itimerval32 {
477100384Speter	struct timeval32 it_interval;
478100384Speter	struct timeval32 it_value;
479100384Speter};
480100384Speter
481121719SpeterCTASSERT(sizeof(struct itimerval32) == 16);
482121719Speter
483100384Speterint
484119333Speterfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
485100384Speter{
486142059Sjhb	struct itimerval itv, oitv, *itvp;
487142059Sjhb	struct itimerval32 i32;
488100384Speter	int error;
489100384Speter
490142059Sjhb	if (uap->itv != NULL) {
491142059Sjhb		error = copyin(uap->itv, &i32, sizeof(i32));
492100384Speter		if (error)
493100384Speter			return (error);
494142059Sjhb		TV_CP(i32, itv, it_interval);
495142059Sjhb		TV_CP(i32, itv, it_value);
496142059Sjhb		itvp = &itv;
497142059Sjhb	} else
498142059Sjhb		itvp = NULL;
499142059Sjhb	error = kern_setitimer(td, uap->which, itvp, &oitv);
500142059Sjhb	if (error || uap->oitv == NULL)
501100384Speter		return (error);
502142059Sjhb	TV_CP(oitv, i32, it_interval);
503142059Sjhb	TV_CP(oitv, i32, it_value);
504142059Sjhb	return (copyout(&i32, uap->oitv, sizeof(i32)));
505100384Speter}
506100384Speter
507100384Speterint
508125171Speterfreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
509125171Speter{
510142059Sjhb	struct itimerval itv;
511142059Sjhb	struct itimerval32 i32;
512125171Speter	int error;
513125171Speter
514142059Sjhb	error = kern_getitimer(td, uap->which, &itv);
515142059Sjhb	if (error || uap->itv == NULL)
516125171Speter		return (error);
517142059Sjhb	TV_CP(itv, i32, it_interval);
518142059Sjhb	TV_CP(itv, i32, it_value);
519142059Sjhb	return (copyout(&i32, uap->itv, sizeof(i32)));
520125171Speter}
521125171Speter
522125171Speterint
523119333Speterfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
524100384Speter{
525142059Sjhb	struct timeval32 tv32;
526142059Sjhb	struct timeval tv, *tvp;
527100384Speter	int error;
528100384Speter
529142059Sjhb	if (uap->tv != NULL) {
530142059Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
531100384Speter		if (error)
532100384Speter			return (error);
533142059Sjhb		CP(tv32, tv, tv_sec);
534142059Sjhb		CP(tv32, tv, tv_usec);
535142059Sjhb		tvp = &tv;
536142059Sjhb	} else
537142059Sjhb		tvp = NULL;
538100384Speter	/*
539100384Speter	 * XXX big-endian needs to convert the fd_sets too.
540142059Sjhb	 * XXX Do pointers need PTRIN()?
541100384Speter	 */
542142059Sjhb	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
543100384Speter}
544100384Speter
545114987Speterstruct kevent32 {
546114987Speter	u_int32_t	ident;		/* identifier for this event */
547114987Speter	short		filter;		/* filter for event */
548114987Speter	u_short		flags;
549114987Speter	u_int		fflags;
550114987Speter	int32_t		data;
551114987Speter	u_int32_t	udata;		/* opaque user data identifier */
552114987Speter};
553114987Speter
554121719SpeterCTASSERT(sizeof(struct kevent32) == 20);
555121719Speter
556100384Speterint
557119333Speterfreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
558114987Speter{
559114987Speter	struct timespec32 ts32;
560142934Sps	struct timespec ts, *tsp;
561142934Sps	struct kevent *ks;
562114987Speter	struct kevent32 ks32;
563142934Sps	struct kevent *changes, *events;
564142934Sps	int error, i;
565114987Speter
566114987Speter
567114987Speter	if (uap->timeout) {
568114987Speter		error = copyin(uap->timeout, &ts32, sizeof(ts32));
569114987Speter		if (error)
570114987Speter			return (error);
571114987Speter		CP(ts32, ts, tv_sec);
572114987Speter		CP(ts32, ts, tv_nsec);
573142934Sps		tsp = &ts;
574142934Sps	} else
575142934Sps		tsp = NULL;
576142934Sps	if (uap->changelist && uap->nchanges > 0) {
577142934Sps		changes = malloc(sizeof(struct kevent) * uap->nchanges, M_TEMP,
578142934Sps		    M_WAITOK);
579114987Speter		for (i = 0; i < uap->nchanges; i++) {
580119333Speter			error = copyin(&uap->changelist[i], &ks32,
581119333Speter			    sizeof(ks32));
582142934Sps			if (error) {
583142934Sps				free(changes, M_TEMP);
584114987Speter				return (error);
585142934Sps			}
586142934Sps			ks = &changes[i];
587114987Speter			CP(ks32, *ks, ident);
588114987Speter			CP(ks32, *ks, filter);
589114987Speter			CP(ks32, *ks, flags);
590114987Speter			CP(ks32, *ks, fflags);
591114987Speter			CP(ks32, *ks, data);
592114987Speter			PTRIN_CP(ks32, *ks, udata);
593114987Speter		}
594142934Sps	} else
595142934Sps		changes = NULL;
596142934Sps	if (uap->eventlist && uap->nevents > 0)
597142934Sps		events = malloc(sizeof(struct kevent) * uap->nevents, M_TEMP,
598142934Sps		    M_WAITOK);
599142934Sps	else
600142934Sps		events = NULL;
601142934Sps	error = kern_kevent(td, uap->fd, changes, uap->nchanges, UIO_SYSSPACE,
602142934Sps	    events, uap->nevents, UIO_SYSSPACE, tsp);
603142934Sps	free(changes, M_TEMP);
604142934Sps	if (uap->eventlist && events && td->td_retval[0] > 0) {
605142934Sps		for (i = 0; i < td->td_retval[0]; i++) {
606142934Sps			ks = &events[i];
607114987Speter			CP(*ks, ks32, ident);
608114987Speter			CP(*ks, ks32, filter);
609114987Speter			CP(*ks, ks32, flags);
610114987Speter			CP(*ks, ks32, fflags);
611114987Speter			CP(*ks, ks32, data);
612114987Speter			PTROUT_CP(*ks, ks32, udata);
613119333Speter			error = copyout(&ks32, &uap->eventlist[i],
614119333Speter			    sizeof(ks32));
615114987Speter			if (error)
616142934Sps				break;
617114987Speter		}
618114987Speter	}
619142934Sps	if (events)
620142934Sps		free(events, M_TEMP);
621142934Sps	return (error);
622114987Speter}
623114987Speter
624114987Speterint
625119333Speterfreebsd32_gettimeofday(struct thread *td,
626119333Speter		       struct freebsd32_gettimeofday_args *uap)
627100384Speter{
628123425Speter	struct timeval atv;
629123425Speter	struct timeval32 atv32;
630123425Speter	struct timezone rtz;
631123425Speter	int error = 0;
632100384Speter
633123425Speter	if (uap->tp) {
634123425Speter		microtime(&atv);
635123425Speter		CP(atv, atv32, tv_sec);
636123425Speter		CP(atv, atv32, tv_usec);
637123425Speter		error = copyout(&atv32, uap->tp, sizeof (atv32));
638100384Speter	}
639123425Speter	if (error == 0 && uap->tzp != NULL) {
640123425Speter		rtz.tz_minuteswest = tz_minuteswest;
641123425Speter		rtz.tz_dsttime = tz_dsttime;
642123425Speter		error = copyout(&rtz, uap->tzp, sizeof (rtz));
643100384Speter	}
644100384Speter	return (error);
645100384Speter}
646100384Speter
647100384Speterint
648119333Speterfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
649100384Speter{
650136152Sjhb	struct rusage32 s32;
651136152Sjhb	struct rusage s;
652100384Speter	int error;
653100384Speter
654136152Sjhb	error = kern_getrusage(td, uap->who, &s);
655100384Speter	if (error)
656100384Speter		return (error);
657136152Sjhb	if (uap->rusage != NULL) {
658100384Speter		TV_CP(s, s32, ru_utime);
659100384Speter		TV_CP(s, s32, ru_stime);
660100384Speter		CP(s, s32, ru_maxrss);
661100384Speter		CP(s, s32, ru_ixrss);
662100384Speter		CP(s, s32, ru_idrss);
663100384Speter		CP(s, s32, ru_isrss);
664100384Speter		CP(s, s32, ru_minflt);
665100384Speter		CP(s, s32, ru_majflt);
666100384Speter		CP(s, s32, ru_nswap);
667100384Speter		CP(s, s32, ru_inblock);
668100384Speter		CP(s, s32, ru_oublock);
669100384Speter		CP(s, s32, ru_msgsnd);
670100384Speter		CP(s, s32, ru_msgrcv);
671100384Speter		CP(s, s32, ru_nsignals);
672100384Speter		CP(s, s32, ru_nvcsw);
673100384Speter		CP(s, s32, ru_nivcsw);
674136152Sjhb		error = copyout(&s32, uap->rusage, sizeof(s32));
675100384Speter	}
676100384Speter	return (error);
677100384Speter}
678100384Speter
679100384Speterstruct iovec32 {
680100384Speter	u_int32_t iov_base;
681100384Speter	int	iov_len;
682100384Speter};
683100384Speter#define	STACKGAPLEN	400
684100384Speter
685121719SpeterCTASSERT(sizeof(struct iovec32) == 8);
686121719Speter
687100384Speterint
688119333Speterfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
689100384Speter{
690100384Speter	int error, osize, nsize, i;
691100384Speter	caddr_t sg;
692100384Speter	struct readv_args /* {
693100384Speter		syscallarg(int) fd;
694100384Speter		syscallarg(struct iovec *) iovp;
695100384Speter		syscallarg(u_int) iovcnt;
696100384Speter	} */ a;
697100384Speter	struct iovec32 *oio;
698100384Speter	struct iovec *nio;
699100384Speter
700100384Speter	sg = stackgap_init();
701100384Speter
702107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
703100384Speter		return (EINVAL);
704100384Speter
705107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
706107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
707100384Speter
708111119Simp	oio = malloc(osize, M_TEMP, M_WAITOK);
709111119Simp	nio = malloc(nsize, M_TEMP, M_WAITOK);
710100384Speter
711100384Speter	error = 0;
712107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
713100384Speter		goto punt;
714107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
715100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
716100384Speter		nio[i].iov_len = oio[i].iov_len;
717100384Speter	}
718100384Speter
719107849Salfred	a.fd = uap->fd;
720107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
721107849Salfred	a.iovcnt = uap->iovcnt;
722100384Speter
723107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
724100384Speter		goto punt;
725100384Speter	error = readv(td, &a);
726100384Speter
727100384Speterpunt:
728100384Speter	free(oio, M_TEMP);
729100384Speter	free(nio, M_TEMP);
730100384Speter	return (error);
731100384Speter}
732100384Speter
733100384Speterint
734119333Speterfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
735100384Speter{
736100384Speter	int error, i, nsize, osize;
737100384Speter	caddr_t sg;
738100384Speter	struct writev_args /* {
739100384Speter		syscallarg(int) fd;
740100384Speter		syscallarg(struct iovec *) iovp;
741100384Speter		syscallarg(u_int) iovcnt;
742100384Speter	} */ a;
743100384Speter	struct iovec32 *oio;
744100384Speter	struct iovec *nio;
745100384Speter
746100384Speter	sg = stackgap_init();
747100384Speter
748107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
749100384Speter		return (EINVAL);
750100384Speter
751107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
752107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
753100384Speter
754111119Simp	oio = malloc(osize, M_TEMP, M_WAITOK);
755111119Simp	nio = malloc(nsize, M_TEMP, M_WAITOK);
756100384Speter
757100384Speter	error = 0;
758107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
759100384Speter		goto punt;
760107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
761100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
762100384Speter		nio[i].iov_len = oio[i].iov_len;
763100384Speter	}
764100384Speter
765107849Salfred	a.fd = uap->fd;
766107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
767107849Salfred	a.iovcnt = uap->iovcnt;
768100384Speter
769107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
770100384Speter		goto punt;
771100384Speter	error = writev(td, &a);
772100384Speter
773100384Speterpunt:
774100384Speter	free(oio, M_TEMP);
775100384Speter	free(nio, M_TEMP);
776100384Speter	return (error);
777100384Speter}
778100384Speter
779100384Speterint
780119333Speterfreebsd32_settimeofday(struct thread *td,
781119333Speter		       struct freebsd32_settimeofday_args *uap)
782100384Speter{
783100384Speter	int error;
784100384Speter	caddr_t sg;
785100384Speter	struct timeval32 *p32, s32;
786100384Speter	struct timeval *p = NULL, s;
787100384Speter
788107849Salfred	p32 = uap->tv;
789100384Speter	if (p32) {
790100384Speter		sg = stackgap_init();
791100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
792107849Salfred		uap->tv = (struct timeval32 *)p;
793100384Speter		error = copyin(p32, &s32, sizeof(s32));
794100384Speter		if (error)
795100384Speter			return (error);
796100384Speter		CP(s32, s, tv_sec);
797100384Speter		CP(s32, s, tv_usec);
798100384Speter		error = copyout(&s, p, sizeof(s));
799100384Speter		if (error)
800100384Speter			return (error);
801100384Speter	}
802100384Speter	return (settimeofday(td, (struct settimeofday_args *) uap));
803100384Speter}
804100384Speter
805100384Speterint
806119333Speterfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
807100384Speter{
808142059Sjhb	struct timeval32 s32[2];
809142059Sjhb	struct timeval s[2], *sp;
810100384Speter	int error;
811100384Speter
812142059Sjhb	if (uap->tptr != NULL) {
813142059Sjhb		error = copyin(uap->tptr, s32, sizeof(s32));
814100384Speter		if (error)
815100384Speter			return (error);
816100384Speter		CP(s32[0], s[0], tv_sec);
817100384Speter		CP(s32[0], s[0], tv_usec);
818100384Speter		CP(s32[1], s[1], tv_sec);
819100384Speter		CP(s32[1], s[1], tv_usec);
820142059Sjhb		sp = s;
821142059Sjhb	} else
822142059Sjhb		sp = NULL;
823142059Sjhb	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
824100384Speter}
825100384Speter
826100384Speterint
827119333Speterfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
828100384Speter{
829100384Speter	int error;
830100384Speter	caddr_t sg;
831100384Speter	struct timeval32 *p32, *op32, s32;
832100384Speter	struct timeval *p = NULL, *op = NULL, s;
833100384Speter
834107849Salfred	p32 = uap->delta;
835100384Speter	if (p32) {
836100384Speter		sg = stackgap_init();
837100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
838107849Salfred		uap->delta = (struct timeval32 *)p;
839100384Speter		error = copyin(p32, &s32, sizeof(s32));
840100384Speter		if (error)
841100384Speter			return (error);
842100384Speter		CP(s32, s, tv_sec);
843100384Speter		CP(s32, s, tv_usec);
844100384Speter		error = copyout(&s, p, sizeof(s));
845100384Speter		if (error)
846100384Speter			return (error);
847100384Speter	}
848107849Salfred	op32 = uap->olddelta;
849100384Speter	if (op32) {
850100384Speter		sg = stackgap_init();
851100384Speter		op = stackgap_alloc(&sg, sizeof(struct timeval));
852107849Salfred		uap->olddelta = (struct timeval32 *)op;
853100384Speter	}
854142059Sjhb	error = adjtime(td, (struct adjtime_args *) uap);
855100384Speter	if (error)
856100384Speter		return error;
857100384Speter	if (op32) {
858100384Speter		error = copyin(op, &s, sizeof(s));
859100384Speter		if (error)
860100384Speter			return (error);
861100384Speter		CP(s, s32, tv_sec);
862100384Speter		CP(s, s32, tv_usec);
863100384Speter		error = copyout(&s32, op32, sizeof(s32));
864100384Speter	}
865100384Speter	return (error);
866100384Speter}
867100384Speter
868128597Smarcel#ifdef COMPAT_FREEBSD4
869100384Speterint
870128260Speterfreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
871100384Speter{
872142059Sjhb	struct statfs32 s32;
873142059Sjhb	struct statfs s;
874100384Speter	int error;
875100384Speter
876142059Sjhb	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
877100384Speter	if (error)
878100384Speter		return (error);
879142059Sjhb	copy_statfs(&s, &s32);
880142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
881100384Speter}
882128597Smarcel#endif
883100384Speter
884128597Smarcel#ifdef COMPAT_FREEBSD4
885100384Speterint
886128260Speterfreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
887100384Speter{
888142059Sjhb	struct statfs32 s32;
889142059Sjhb	struct statfs s;
890100384Speter	int error;
891100384Speter
892142059Sjhb	error = kern_fstatfs(td, uap->fd, &s);
893100384Speter	if (error)
894100384Speter		return (error);
895142059Sjhb	copy_statfs(&s, &s32);
896142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
897100384Speter}
898128597Smarcel#endif
899100384Speter
900128597Smarcel#ifdef COMPAT_FREEBSD4
901100384Speterint
902128260Speterfreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
903128260Speter{
904142059Sjhb	struct statfs32 s32;
905142059Sjhb	struct statfs s;
906142059Sjhb	fhandle_t fh;
907128260Speter	int error;
908128260Speter
909142059Sjhb	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
910142059Sjhb		return (error);
911142059Sjhb	error = kern_fhstatfs(td, fh, &s);
912128260Speter	if (error)
913128260Speter		return (error);
914142059Sjhb	copy_statfs(&s, &s32);
915142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
916128260Speter}
917128597Smarcel#endif
918128260Speter
919128260Speterint
920119333Speterfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
921100384Speter{
922100384Speter	/*
923100384Speter	 * Vector through to semsys if it is loaded.
924100384Speter	 */
925100384Speter	return sysent[169].sy_call(td, uap);
926100384Speter}
927100384Speter
928100384Speterint
929119333Speterfreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
930100384Speter{
931100384Speter	/*
932100384Speter	 * Vector through to msgsys if it is loaded.
933100384Speter	 */
934100384Speter	return sysent[170].sy_call(td, uap);
935100384Speter}
936100384Speter
937100384Speterint
938119333Speterfreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
939100384Speter{
940100384Speter	/*
941100384Speter	 * Vector through to shmsys if it is loaded.
942100384Speter	 */
943100384Speter	return sysent[171].sy_call(td, uap);
944100384Speter}
945100384Speter
946100384Speterint
947119333Speterfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
948100384Speter{
949100384Speter	struct pread_args ap;
950100384Speter
951107849Salfred	ap.fd = uap->fd;
952107849Salfred	ap.buf = uap->buf;
953107849Salfred	ap.nbyte = uap->nbyte;
954119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
955100384Speter	return (pread(td, &ap));
956100384Speter}
957100384Speter
958100384Speterint
959119333Speterfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
960100384Speter{
961100384Speter	struct pwrite_args ap;
962100384Speter
963107849Salfred	ap.fd = uap->fd;
964107849Salfred	ap.buf = uap->buf;
965107849Salfred	ap.nbyte = uap->nbyte;
966119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
967100384Speter	return (pwrite(td, &ap));
968100384Speter}
969100384Speter
970100384Speterint
971119333Speterfreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
972100384Speter{
973100384Speter	int error;
974100384Speter	struct lseek_args ap;
975100384Speter	off_t pos;
976100384Speter
977107849Salfred	ap.fd = uap->fd;
978119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
979107849Salfred	ap.whence = uap->whence;
980100384Speter	error = lseek(td, &ap);
981100384Speter	/* Expand the quad return into two parts for eax and edx */
982100384Speter	pos = *(off_t *)(td->td_retval);
983100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
984100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
985100384Speter	return error;
986100384Speter}
987100384Speter
988100384Speterint
989119333Speterfreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
990100384Speter{
991100384Speter	struct truncate_args ap;
992100384Speter
993107849Salfred	ap.path = uap->path;
994119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
995100384Speter	return (truncate(td, &ap));
996100384Speter}
997100384Speter
998100384Speterint
999119333Speterfreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1000100384Speter{
1001100384Speter	struct ftruncate_args ap;
1002100384Speter
1003107849Salfred	ap.fd = uap->fd;
1004119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1005100384Speter	return (ftruncate(td, &ap));
1006100384Speter}
1007100384Speter
1008104738Speter#ifdef COMPAT_FREEBSD4
1009100384Speterint
1010119333Speterfreebsd4_freebsd32_sendfile(struct thread *td,
1011119333Speter    struct freebsd4_freebsd32_sendfile_args *uap)
1012104738Speter{
1013104738Speter	struct freebsd4_sendfile_args ap;
1014104738Speter
1015107849Salfred	ap.fd = uap->fd;
1016107849Salfred	ap.s = uap->s;
1017119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1018107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1019107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1020107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1021107849Salfred	ap.flags = uap->flags;
1022104738Speter	return (freebsd4_sendfile(td, &ap));
1023104738Speter}
1024104738Speter#endif
1025104738Speter
1026104738Speterint
1027119333Speterfreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1028100384Speter{
1029100384Speter	struct sendfile_args ap;
1030100384Speter
1031107849Salfred	ap.fd = uap->fd;
1032107849Salfred	ap.s = uap->s;
1033119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1034107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1035107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1036107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1037107849Salfred	ap.flags = uap->flags;
1038100384Speter	return (sendfile(td, &ap));
1039100384Speter}
1040100384Speter
1041100384Speterstruct stat32 {
1042130640Sphk	dev_t	st_dev;
1043100384Speter	ino_t	st_ino;
1044100384Speter	mode_t	st_mode;
1045100384Speter	nlink_t	st_nlink;
1046100384Speter	uid_t	st_uid;
1047100384Speter	gid_t	st_gid;
1048130640Sphk	dev_t	st_rdev;
1049100384Speter	struct timespec32 st_atimespec;
1050100384Speter	struct timespec32 st_mtimespec;
1051100384Speter	struct timespec32 st_ctimespec;
1052100384Speter	off_t	st_size;
1053100384Speter	int64_t	st_blocks;
1054100384Speter	u_int32_t st_blksize;
1055100384Speter	u_int32_t st_flags;
1056100384Speter	u_int32_t st_gen;
1057121719Speter	struct timespec32 st_birthtimespec;
1058121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1059121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1060100384Speter};
1061100384Speter
1062121719Speter
1063121719SpeterCTASSERT(sizeof(struct stat32) == 96);
1064121719Speter
1065100384Speterstatic void
1066100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1067100384Speter{
1068100384Speter	CP(*in, *out, st_dev);
1069100384Speter	CP(*in, *out, st_ino);
1070100384Speter	CP(*in, *out, st_mode);
1071100384Speter	CP(*in, *out, st_nlink);
1072100384Speter	CP(*in, *out, st_uid);
1073100384Speter	CP(*in, *out, st_gid);
1074100384Speter	CP(*in, *out, st_rdev);
1075100384Speter	TS_CP(*in, *out, st_atimespec);
1076100384Speter	TS_CP(*in, *out, st_mtimespec);
1077100384Speter	TS_CP(*in, *out, st_ctimespec);
1078100384Speter	CP(*in, *out, st_size);
1079100384Speter	CP(*in, *out, st_blocks);
1080100384Speter	CP(*in, *out, st_blksize);
1081100384Speter	CP(*in, *out, st_flags);
1082100384Speter	CP(*in, *out, st_gen);
1083100384Speter}
1084100384Speter
1085100384Speterint
1086119333Speterfreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1087100384Speter{
1088123746Speter	struct stat sb;
1089123746Speter	struct stat32 sb32;
1090100384Speter	int error;
1091100384Speter
1092142059Sjhb	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1093100384Speter	if (error)
1094100384Speter		return (error);
1095123746Speter	copy_stat(&sb, &sb32);
1096123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1097100384Speter	return (error);
1098100384Speter}
1099100384Speter
1100100384Speterint
1101119333Speterfreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1102100384Speter{
1103123746Speter	struct stat ub;
1104123746Speter	struct stat32 ub32;
1105100384Speter	int error;
1106100384Speter
1107142059Sjhb	error = kern_fstat(td, uap->fd, &ub);
1108100384Speter	if (error)
1109100384Speter		return (error);
1110123746Speter	copy_stat(&ub, &ub32);
1111123746Speter	error = copyout(&ub32, uap->ub, sizeof(ub32));
1112100384Speter	return (error);
1113100384Speter}
1114100384Speter
1115100384Speterint
1116119333Speterfreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1117100384Speter{
1118123746Speter	struct stat sb;
1119123746Speter	struct stat32 sb32;
1120142059Sjhb	int error;
1121100384Speter
1122142059Sjhb	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1123100384Speter	if (error)
1124100384Speter		return (error);
1125123746Speter	copy_stat(&sb, &sb32);
1126123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1127100384Speter	return (error);
1128100384Speter}
1129100384Speter
1130100384Speter/*
1131100384Speter * MPSAFE
1132100384Speter */
1133100384Speterint
1134119333Speterfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1135100384Speter{
1136100384Speter	int error, name[CTL_MAXNAME];
1137100384Speter	size_t j, oldlen;
1138100384Speter
1139100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1140100384Speter		return (EINVAL);
1141136404Speter 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1142100384Speter 	if (error)
1143100384Speter		return (error);
1144100384Speter	mtx_lock(&Giant);
1145100384Speter	if (uap->oldlenp)
1146100384Speter		oldlen = fuword32(uap->oldlenp);
1147100384Speter	else
1148100384Speter		oldlen = 0;
1149100384Speter	error = userland_sysctl(td, name, uap->namelen,
1150100384Speter		uap->old, &oldlen, 1,
1151136404Speter		uap->new, uap->newlen, &j, SCTL_MASK32);
1152100384Speter	if (error && error != ENOMEM)
1153100384Speter		goto done2;
1154136404Speter	if (uap->oldlenp)
1155100384Speter		suword32(uap->oldlenp, j);
1156100384Speterdone2:
1157100384Speter	mtx_unlock(&Giant);
1158100384Speter	return (error);
1159100384Speter}
1160100384Speter
1161100384Speterstruct sigaction32 {
1162100384Speter	u_int32_t	sa_u;
1163100384Speter	int		sa_flags;
1164100384Speter	sigset_t	sa_mask;
1165100384Speter};
1166100384Speter
1167121719SpeterCTASSERT(sizeof(struct sigaction32) == 24);
1168121719Speter
1169100384Speterint
1170119333Speterfreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1171100384Speter{
1172113859Sjhb	struct sigaction32 s32;
1173113859Sjhb	struct sigaction sa, osa, *sap;
1174100384Speter	int error;
1175100384Speter
1176113859Sjhb	if (uap->act) {
1177113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
1178100384Speter		if (error)
1179100384Speter			return (error);
1180113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
1181113859Sjhb		CP(s32, sa, sa_flags);
1182113859Sjhb		CP(s32, sa, sa_mask);
1183113859Sjhb		sap = &sa;
1184113859Sjhb	} else
1185113859Sjhb		sap = NULL;
1186113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1187113859Sjhb	if (error != 0 && uap->oact != NULL) {
1188113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
1189113859Sjhb		CP(osa, s32, sa_flags);
1190113859Sjhb		CP(osa, s32, sa_mask);
1191113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
1192100384Speter	}
1193100384Speter	return (error);
1194100384Speter}
1195100384Speter
1196114987Speter#ifdef COMPAT_FREEBSD4
1197114987Speterint
1198119333Speterfreebsd4_freebsd32_sigaction(struct thread *td,
1199119333Speter			     struct freebsd4_freebsd32_sigaction_args *uap)
1200114987Speter{
1201114987Speter	struct sigaction32 s32;
1202114987Speter	struct sigaction sa, osa, *sap;
1203114987Speter	int error;
1204114987Speter
1205114987Speter	if (uap->act) {
1206114987Speter		error = copyin(uap->act, &s32, sizeof(s32));
1207114987Speter		if (error)
1208114987Speter			return (error);
1209114987Speter		sa.sa_handler = PTRIN(s32.sa_u);
1210114987Speter		CP(s32, sa, sa_flags);
1211114987Speter		CP(s32, sa, sa_mask);
1212114987Speter		sap = &sa;
1213114987Speter	} else
1214114987Speter		sap = NULL;
1215114987Speter	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1216114987Speter	if (error != 0 && uap->oact != NULL) {
1217114987Speter		s32.sa_u = PTROUT(osa.sa_handler);
1218114987Speter		CP(osa, s32, sa_flags);
1219114987Speter		CP(osa, s32, sa_mask);
1220114987Speter		error = copyout(&s32, uap->oact, sizeof(s32));
1221114987Speter	}
1222114987Speter	return (error);
1223114987Speter}
1224114987Speter#endif
1225114987Speter
1226140481Spsint
1227140481Spsfreebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1228140481Sps{
1229140481Sps	struct timespec32 rmt32, rqt32;
1230140481Sps	struct timespec rmt, rqt;
1231140481Sps	int error;
1232140481Sps
1233140481Sps	error = copyin(uap->rqtp, &rqt32, sizeof(rqt));
1234140481Sps	if (error)
1235140481Sps		return (error);
1236140481Sps
1237140481Sps	CP(rqt32, rqt, tv_sec);
1238140481Sps	CP(rqt32, rqt, tv_nsec);
1239140481Sps
1240140481Sps	if (uap->rmtp &&
1241140481Sps	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1242140481Sps		return (EFAULT);
1243140481Sps	error = kern_nanosleep(td, &rqt, &rmt);
1244140481Sps	if (error && uap->rmtp) {
1245140481Sps		int error2;
1246140481Sps
1247140481Sps		CP(rmt, rmt32, tv_sec);
1248140481Sps		CP(rmt, rmt32, tv_nsec);
1249140481Sps
1250140481Sps		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt));
1251140481Sps		if (error2)
1252140481Sps			error = error2;
1253140481Sps	}
1254140481Sps	return (error);
1255140481Sps}
1256140481Sps
1257100384Speter#if 0
1258100384Speter
1259100384Speterint
1260119333Speterfreebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1261100384Speter{
1262100384Speter	int error;
1263100384Speter	caddr_t sg;
1264100384Speter	struct yyy32 *p32, s32;
1265100384Speter	struct yyy *p = NULL, s;
1266100384Speter
1267107849Salfred	p32 = uap->zzz;
1268100384Speter	if (p32) {
1269100384Speter		sg = stackgap_init();
1270100384Speter		p = stackgap_alloc(&sg, sizeof(struct yyy));
1271107849Salfred		uap->zzz = (struct yyy32 *)p;
1272100384Speter		error = copyin(p32, &s32, sizeof(s32));
1273100384Speter		if (error)
1274100384Speter			return (error);
1275100384Speter		/* translate in */
1276100384Speter		error = copyout(&s, p, sizeof(s));
1277100384Speter		if (error)
1278100384Speter			return (error);
1279100384Speter	}
1280100384Speter	error = xxx(td, (struct xxx_args *) uap);
1281100384Speter	if (error)
1282100384Speter		return (error);
1283100384Speter	if (p32) {
1284100384Speter		error = copyin(p, &s, sizeof(s));
1285100384Speter		if (error)
1286100384Speter			return (error);
1287100384Speter		/* translate out */
1288100384Speter		error = copyout(&s32, p32, sizeof(s32));
1289100384Speter	}
1290100384Speter	return (error);
1291100384Speter}
1292100384Speter
1293100384Speter#endif
1294