freebsd32_misc.c revision 142059
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 142059 2005-02-18 18:56:04Z jhb $");
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	int error;
560114987Speter	caddr_t sg;
561114987Speter	struct timespec32 ts32;
562114987Speter	struct timespec ts;
563114987Speter	struct kevent32 ks32;
564114987Speter	struct kevent *ks;
565114987Speter	struct kevent_args a;
566114987Speter	int i;
567114987Speter
568114987Speter	sg = stackgap_init();
569114987Speter
570114987Speter	a.fd = uap->fd;
571114987Speter	a.changelist = uap->changelist;
572114987Speter	a.nchanges = uap->nchanges;
573114987Speter	a.eventlist = uap->eventlist;
574114987Speter	a.nevents = uap->nevents;
575114987Speter	a.timeout = NULL;
576114987Speter
577114987Speter	if (uap->timeout) {
578114987Speter		a.timeout = stackgap_alloc(&sg, sizeof(struct timespec));
579114987Speter		error = copyin(uap->timeout, &ts32, sizeof(ts32));
580114987Speter		if (error)
581114987Speter			return (error);
582114987Speter		CP(ts32, ts, tv_sec);
583114987Speter		CP(ts32, ts, tv_nsec);
584114987Speter		error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts));
585114987Speter		if (error)
586114987Speter			return (error);
587114987Speter	}
588114987Speter	if (uap->changelist) {
589119333Speter		a.changelist = (struct kevent *)stackgap_alloc(&sg,
590119333Speter		    uap->nchanges * sizeof(struct kevent));
591114987Speter		for (i = 0; i < uap->nchanges; i++) {
592119333Speter			error = copyin(&uap->changelist[i], &ks32,
593119333Speter			    sizeof(ks32));
594114987Speter			if (error)
595114987Speter				return (error);
596114987Speter			ks = (struct kevent *)(uintptr_t)&a.changelist[i];
597114987Speter			CP(ks32, *ks, ident);
598114987Speter			CP(ks32, *ks, filter);
599114987Speter			CP(ks32, *ks, flags);
600114987Speter			CP(ks32, *ks, fflags);
601114987Speter			CP(ks32, *ks, data);
602114987Speter			PTRIN_CP(ks32, *ks, udata);
603114987Speter		}
604114987Speter	}
605114987Speter	if (uap->eventlist) {
606119333Speter		a.eventlist = stackgap_alloc(&sg,
607119333Speter		    uap->nevents * sizeof(struct kevent));
608114987Speter	}
609114987Speter	error = kevent(td, &a);
610114987Speter	if (uap->eventlist && error > 0) {
611114987Speter		for (i = 0; i < error; i++) {
612114987Speter			ks = &a.eventlist[i];
613114987Speter			CP(*ks, ks32, ident);
614114987Speter			CP(*ks, ks32, filter);
615114987Speter			CP(*ks, ks32, flags);
616114987Speter			CP(*ks, ks32, fflags);
617114987Speter			CP(*ks, ks32, data);
618114987Speter			PTROUT_CP(*ks, ks32, udata);
619119333Speter			error = copyout(&ks32, &uap->eventlist[i],
620119333Speter			    sizeof(ks32));
621114987Speter			if (error)
622114987Speter				return (error);
623114987Speter		}
624114987Speter	}
625114987Speter	return error;
626114987Speter}
627114987Speter
628114987Speterint
629119333Speterfreebsd32_gettimeofday(struct thread *td,
630119333Speter		       struct freebsd32_gettimeofday_args *uap)
631100384Speter{
632123425Speter	struct timeval atv;
633123425Speter	struct timeval32 atv32;
634123425Speter	struct timezone rtz;
635123425Speter	int error = 0;
636100384Speter
637123425Speter	if (uap->tp) {
638123425Speter		microtime(&atv);
639123425Speter		CP(atv, atv32, tv_sec);
640123425Speter		CP(atv, atv32, tv_usec);
641123425Speter		error = copyout(&atv32, uap->tp, sizeof (atv32));
642100384Speter	}
643123425Speter	if (error == 0 && uap->tzp != NULL) {
644123425Speter		rtz.tz_minuteswest = tz_minuteswest;
645123425Speter		rtz.tz_dsttime = tz_dsttime;
646123425Speter		error = copyout(&rtz, uap->tzp, sizeof (rtz));
647100384Speter	}
648100384Speter	return (error);
649100384Speter}
650100384Speter
651100384Speterint
652119333Speterfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
653100384Speter{
654136152Sjhb	struct rusage32 s32;
655136152Sjhb	struct rusage s;
656100384Speter	int error;
657100384Speter
658136152Sjhb	error = kern_getrusage(td, uap->who, &s);
659100384Speter	if (error)
660100384Speter		return (error);
661136152Sjhb	if (uap->rusage != NULL) {
662100384Speter		TV_CP(s, s32, ru_utime);
663100384Speter		TV_CP(s, s32, ru_stime);
664100384Speter		CP(s, s32, ru_maxrss);
665100384Speter		CP(s, s32, ru_ixrss);
666100384Speter		CP(s, s32, ru_idrss);
667100384Speter		CP(s, s32, ru_isrss);
668100384Speter		CP(s, s32, ru_minflt);
669100384Speter		CP(s, s32, ru_majflt);
670100384Speter		CP(s, s32, ru_nswap);
671100384Speter		CP(s, s32, ru_inblock);
672100384Speter		CP(s, s32, ru_oublock);
673100384Speter		CP(s, s32, ru_msgsnd);
674100384Speter		CP(s, s32, ru_msgrcv);
675100384Speter		CP(s, s32, ru_nsignals);
676100384Speter		CP(s, s32, ru_nvcsw);
677100384Speter		CP(s, s32, ru_nivcsw);
678136152Sjhb		error = copyout(&s32, uap->rusage, sizeof(s32));
679100384Speter	}
680100384Speter	return (error);
681100384Speter}
682100384Speter
683100384Speterstruct iovec32 {
684100384Speter	u_int32_t iov_base;
685100384Speter	int	iov_len;
686100384Speter};
687100384Speter#define	STACKGAPLEN	400
688100384Speter
689121719SpeterCTASSERT(sizeof(struct iovec32) == 8);
690121719Speter
691100384Speterint
692119333Speterfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
693100384Speter{
694100384Speter	int error, osize, nsize, i;
695100384Speter	caddr_t sg;
696100384Speter	struct readv_args /* {
697100384Speter		syscallarg(int) fd;
698100384Speter		syscallarg(struct iovec *) iovp;
699100384Speter		syscallarg(u_int) iovcnt;
700100384Speter	} */ a;
701100384Speter	struct iovec32 *oio;
702100384Speter	struct iovec *nio;
703100384Speter
704100384Speter	sg = stackgap_init();
705100384Speter
706107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
707100384Speter		return (EINVAL);
708100384Speter
709107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
710107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
711100384Speter
712111119Simp	oio = malloc(osize, M_TEMP, M_WAITOK);
713111119Simp	nio = malloc(nsize, M_TEMP, M_WAITOK);
714100384Speter
715100384Speter	error = 0;
716107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
717100384Speter		goto punt;
718107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
719100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
720100384Speter		nio[i].iov_len = oio[i].iov_len;
721100384Speter	}
722100384Speter
723107849Salfred	a.fd = uap->fd;
724107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
725107849Salfred	a.iovcnt = uap->iovcnt;
726100384Speter
727107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
728100384Speter		goto punt;
729100384Speter	error = readv(td, &a);
730100384Speter
731100384Speterpunt:
732100384Speter	free(oio, M_TEMP);
733100384Speter	free(nio, M_TEMP);
734100384Speter	return (error);
735100384Speter}
736100384Speter
737100384Speterint
738119333Speterfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
739100384Speter{
740100384Speter	int error, i, nsize, osize;
741100384Speter	caddr_t sg;
742100384Speter	struct writev_args /* {
743100384Speter		syscallarg(int) fd;
744100384Speter		syscallarg(struct iovec *) iovp;
745100384Speter		syscallarg(u_int) iovcnt;
746100384Speter	} */ a;
747100384Speter	struct iovec32 *oio;
748100384Speter	struct iovec *nio;
749100384Speter
750100384Speter	sg = stackgap_init();
751100384Speter
752107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
753100384Speter		return (EINVAL);
754100384Speter
755107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
756107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
757100384Speter
758111119Simp	oio = malloc(osize, M_TEMP, M_WAITOK);
759111119Simp	nio = malloc(nsize, M_TEMP, M_WAITOK);
760100384Speter
761100384Speter	error = 0;
762107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
763100384Speter		goto punt;
764107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
765100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
766100384Speter		nio[i].iov_len = oio[i].iov_len;
767100384Speter	}
768100384Speter
769107849Salfred	a.fd = uap->fd;
770107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
771107849Salfred	a.iovcnt = uap->iovcnt;
772100384Speter
773107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
774100384Speter		goto punt;
775100384Speter	error = writev(td, &a);
776100384Speter
777100384Speterpunt:
778100384Speter	free(oio, M_TEMP);
779100384Speter	free(nio, M_TEMP);
780100384Speter	return (error);
781100384Speter}
782100384Speter
783100384Speterint
784119333Speterfreebsd32_settimeofday(struct thread *td,
785119333Speter		       struct freebsd32_settimeofday_args *uap)
786100384Speter{
787100384Speter	int error;
788100384Speter	caddr_t sg;
789100384Speter	struct timeval32 *p32, s32;
790100384Speter	struct timeval *p = NULL, s;
791100384Speter
792107849Salfred	p32 = uap->tv;
793100384Speter	if (p32) {
794100384Speter		sg = stackgap_init();
795100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
796107849Salfred		uap->tv = (struct timeval32 *)p;
797100384Speter		error = copyin(p32, &s32, sizeof(s32));
798100384Speter		if (error)
799100384Speter			return (error);
800100384Speter		CP(s32, s, tv_sec);
801100384Speter		CP(s32, s, tv_usec);
802100384Speter		error = copyout(&s, p, sizeof(s));
803100384Speter		if (error)
804100384Speter			return (error);
805100384Speter	}
806100384Speter	return (settimeofday(td, (struct settimeofday_args *) uap));
807100384Speter}
808100384Speter
809100384Speterint
810119333Speterfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
811100384Speter{
812142059Sjhb	struct timeval32 s32[2];
813142059Sjhb	struct timeval s[2], *sp;
814100384Speter	int error;
815100384Speter
816142059Sjhb	if (uap->tptr != NULL) {
817142059Sjhb		error = copyin(uap->tptr, s32, sizeof(s32));
818100384Speter		if (error)
819100384Speter			return (error);
820100384Speter		CP(s32[0], s[0], tv_sec);
821100384Speter		CP(s32[0], s[0], tv_usec);
822100384Speter		CP(s32[1], s[1], tv_sec);
823100384Speter		CP(s32[1], s[1], tv_usec);
824142059Sjhb		sp = s;
825142059Sjhb	} else
826142059Sjhb		sp = NULL;
827142059Sjhb	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
828100384Speter}
829100384Speter
830100384Speterint
831119333Speterfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
832100384Speter{
833100384Speter	int error;
834100384Speter	caddr_t sg;
835100384Speter	struct timeval32 *p32, *op32, s32;
836100384Speter	struct timeval *p = NULL, *op = NULL, s;
837100384Speter
838107849Salfred	p32 = uap->delta;
839100384Speter	if (p32) {
840100384Speter		sg = stackgap_init();
841100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
842107849Salfred		uap->delta = (struct timeval32 *)p;
843100384Speter		error = copyin(p32, &s32, sizeof(s32));
844100384Speter		if (error)
845100384Speter			return (error);
846100384Speter		CP(s32, s, tv_sec);
847100384Speter		CP(s32, s, tv_usec);
848100384Speter		error = copyout(&s, p, sizeof(s));
849100384Speter		if (error)
850100384Speter			return (error);
851100384Speter	}
852107849Salfred	op32 = uap->olddelta;
853100384Speter	if (op32) {
854100384Speter		sg = stackgap_init();
855100384Speter		op = stackgap_alloc(&sg, sizeof(struct timeval));
856107849Salfred		uap->olddelta = (struct timeval32 *)op;
857100384Speter	}
858142059Sjhb	error = adjtime(td, (struct adjtime_args *) uap);
859100384Speter	if (error)
860100384Speter		return error;
861100384Speter	if (op32) {
862100384Speter		error = copyin(op, &s, sizeof(s));
863100384Speter		if (error)
864100384Speter			return (error);
865100384Speter		CP(s, s32, tv_sec);
866100384Speter		CP(s, s32, tv_usec);
867100384Speter		error = copyout(&s32, op32, sizeof(s32));
868100384Speter	}
869100384Speter	return (error);
870100384Speter}
871100384Speter
872128597Smarcel#ifdef COMPAT_FREEBSD4
873100384Speterint
874128260Speterfreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
875100384Speter{
876142059Sjhb	struct statfs32 s32;
877142059Sjhb	struct statfs s;
878100384Speter	int error;
879100384Speter
880142059Sjhb	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
881100384Speter	if (error)
882100384Speter		return (error);
883142059Sjhb	copy_statfs(&s, &s32);
884142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
885100384Speter}
886128597Smarcel#endif
887100384Speter
888128597Smarcel#ifdef COMPAT_FREEBSD4
889100384Speterint
890128260Speterfreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
891100384Speter{
892142059Sjhb	struct statfs32 s32;
893142059Sjhb	struct statfs s;
894100384Speter	int error;
895100384Speter
896142059Sjhb	error = kern_fstatfs(td, uap->fd, &s);
897100384Speter	if (error)
898100384Speter		return (error);
899142059Sjhb	copy_statfs(&s, &s32);
900142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
901100384Speter}
902128597Smarcel#endif
903100384Speter
904128597Smarcel#ifdef COMPAT_FREEBSD4
905100384Speterint
906128260Speterfreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
907128260Speter{
908142059Sjhb	struct statfs32 s32;
909142059Sjhb	struct statfs s;
910142059Sjhb	fhandle_t fh;
911128260Speter	int error;
912128260Speter
913142059Sjhb	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
914142059Sjhb		return (error);
915142059Sjhb	error = kern_fhstatfs(td, fh, &s);
916128260Speter	if (error)
917128260Speter		return (error);
918142059Sjhb	copy_statfs(&s, &s32);
919142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
920128260Speter}
921128597Smarcel#endif
922128260Speter
923128260Speterint
924119333Speterfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
925100384Speter{
926100384Speter	/*
927100384Speter	 * Vector through to semsys if it is loaded.
928100384Speter	 */
929100384Speter	return sysent[169].sy_call(td, uap);
930100384Speter}
931100384Speter
932100384Speterint
933119333Speterfreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
934100384Speter{
935100384Speter	/*
936100384Speter	 * Vector through to msgsys if it is loaded.
937100384Speter	 */
938100384Speter	return sysent[170].sy_call(td, uap);
939100384Speter}
940100384Speter
941100384Speterint
942119333Speterfreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
943100384Speter{
944100384Speter	/*
945100384Speter	 * Vector through to shmsys if it is loaded.
946100384Speter	 */
947100384Speter	return sysent[171].sy_call(td, uap);
948100384Speter}
949100384Speter
950100384Speterint
951119333Speterfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
952100384Speter{
953100384Speter	struct pread_args ap;
954100384Speter
955107849Salfred	ap.fd = uap->fd;
956107849Salfred	ap.buf = uap->buf;
957107849Salfred	ap.nbyte = uap->nbyte;
958119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
959100384Speter	return (pread(td, &ap));
960100384Speter}
961100384Speter
962100384Speterint
963119333Speterfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
964100384Speter{
965100384Speter	struct pwrite_args ap;
966100384Speter
967107849Salfred	ap.fd = uap->fd;
968107849Salfred	ap.buf = uap->buf;
969107849Salfred	ap.nbyte = uap->nbyte;
970119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
971100384Speter	return (pwrite(td, &ap));
972100384Speter}
973100384Speter
974100384Speterint
975119333Speterfreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
976100384Speter{
977100384Speter	int error;
978100384Speter	struct lseek_args ap;
979100384Speter	off_t pos;
980100384Speter
981107849Salfred	ap.fd = uap->fd;
982119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
983107849Salfred	ap.whence = uap->whence;
984100384Speter	error = lseek(td, &ap);
985100384Speter	/* Expand the quad return into two parts for eax and edx */
986100384Speter	pos = *(off_t *)(td->td_retval);
987100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
988100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
989100384Speter	return error;
990100384Speter}
991100384Speter
992100384Speterint
993119333Speterfreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
994100384Speter{
995100384Speter	struct truncate_args ap;
996100384Speter
997107849Salfred	ap.path = uap->path;
998119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
999100384Speter	return (truncate(td, &ap));
1000100384Speter}
1001100384Speter
1002100384Speterint
1003119333Speterfreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1004100384Speter{
1005100384Speter	struct ftruncate_args ap;
1006100384Speter
1007107849Salfred	ap.fd = uap->fd;
1008119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1009100384Speter	return (ftruncate(td, &ap));
1010100384Speter}
1011100384Speter
1012104738Speter#ifdef COMPAT_FREEBSD4
1013100384Speterint
1014119333Speterfreebsd4_freebsd32_sendfile(struct thread *td,
1015119333Speter    struct freebsd4_freebsd32_sendfile_args *uap)
1016104738Speter{
1017104738Speter	struct freebsd4_sendfile_args ap;
1018104738Speter
1019107849Salfred	ap.fd = uap->fd;
1020107849Salfred	ap.s = uap->s;
1021119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1022107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1023107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1024107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1025107849Salfred	ap.flags = uap->flags;
1026104738Speter	return (freebsd4_sendfile(td, &ap));
1027104738Speter}
1028104738Speter#endif
1029104738Speter
1030104738Speterint
1031119333Speterfreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1032100384Speter{
1033100384Speter	struct sendfile_args ap;
1034100384Speter
1035107849Salfred	ap.fd = uap->fd;
1036107849Salfred	ap.s = uap->s;
1037119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1038107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1039107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1040107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1041107849Salfred	ap.flags = uap->flags;
1042100384Speter	return (sendfile(td, &ap));
1043100384Speter}
1044100384Speter
1045100384Speterstruct stat32 {
1046130640Sphk	dev_t	st_dev;
1047100384Speter	ino_t	st_ino;
1048100384Speter	mode_t	st_mode;
1049100384Speter	nlink_t	st_nlink;
1050100384Speter	uid_t	st_uid;
1051100384Speter	gid_t	st_gid;
1052130640Sphk	dev_t	st_rdev;
1053100384Speter	struct timespec32 st_atimespec;
1054100384Speter	struct timespec32 st_mtimespec;
1055100384Speter	struct timespec32 st_ctimespec;
1056100384Speter	off_t	st_size;
1057100384Speter	int64_t	st_blocks;
1058100384Speter	u_int32_t st_blksize;
1059100384Speter	u_int32_t st_flags;
1060100384Speter	u_int32_t st_gen;
1061121719Speter	struct timespec32 st_birthtimespec;
1062121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1063121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1064100384Speter};
1065100384Speter
1066121719Speter
1067121719SpeterCTASSERT(sizeof(struct stat32) == 96);
1068121719Speter
1069100384Speterstatic void
1070100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1071100384Speter{
1072100384Speter	CP(*in, *out, st_dev);
1073100384Speter	CP(*in, *out, st_ino);
1074100384Speter	CP(*in, *out, st_mode);
1075100384Speter	CP(*in, *out, st_nlink);
1076100384Speter	CP(*in, *out, st_uid);
1077100384Speter	CP(*in, *out, st_gid);
1078100384Speter	CP(*in, *out, st_rdev);
1079100384Speter	TS_CP(*in, *out, st_atimespec);
1080100384Speter	TS_CP(*in, *out, st_mtimespec);
1081100384Speter	TS_CP(*in, *out, st_ctimespec);
1082100384Speter	CP(*in, *out, st_size);
1083100384Speter	CP(*in, *out, st_blocks);
1084100384Speter	CP(*in, *out, st_blksize);
1085100384Speter	CP(*in, *out, st_flags);
1086100384Speter	CP(*in, *out, st_gen);
1087100384Speter}
1088100384Speter
1089100384Speterint
1090119333Speterfreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1091100384Speter{
1092123746Speter	struct stat sb;
1093123746Speter	struct stat32 sb32;
1094100384Speter	int error;
1095100384Speter
1096142059Sjhb	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1097100384Speter	if (error)
1098100384Speter		return (error);
1099123746Speter	copy_stat(&sb, &sb32);
1100123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1101100384Speter	return (error);
1102100384Speter}
1103100384Speter
1104100384Speterint
1105119333Speterfreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1106100384Speter{
1107123746Speter	struct stat ub;
1108123746Speter	struct stat32 ub32;
1109100384Speter	int error;
1110100384Speter
1111142059Sjhb	error = kern_fstat(td, uap->fd, &ub);
1112100384Speter	if (error)
1113100384Speter		return (error);
1114123746Speter	copy_stat(&ub, &ub32);
1115123746Speter	error = copyout(&ub32, uap->ub, sizeof(ub32));
1116100384Speter	return (error);
1117100384Speter}
1118100384Speter
1119100384Speterint
1120119333Speterfreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1121100384Speter{
1122123746Speter	struct stat sb;
1123123746Speter	struct stat32 sb32;
1124142059Sjhb	int error;
1125100384Speter
1126142059Sjhb	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1127100384Speter	if (error)
1128100384Speter		return (error);
1129123746Speter	copy_stat(&sb, &sb32);
1130123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1131100384Speter	return (error);
1132100384Speter}
1133100384Speter
1134100384Speter/*
1135100384Speter * MPSAFE
1136100384Speter */
1137100384Speterint
1138119333Speterfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1139100384Speter{
1140100384Speter	int error, name[CTL_MAXNAME];
1141100384Speter	size_t j, oldlen;
1142100384Speter
1143100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1144100384Speter		return (EINVAL);
1145136404Speter 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1146100384Speter 	if (error)
1147100384Speter		return (error);
1148100384Speter	mtx_lock(&Giant);
1149100384Speter	if (uap->oldlenp)
1150100384Speter		oldlen = fuword32(uap->oldlenp);
1151100384Speter	else
1152100384Speter		oldlen = 0;
1153100384Speter	error = userland_sysctl(td, name, uap->namelen,
1154100384Speter		uap->old, &oldlen, 1,
1155136404Speter		uap->new, uap->newlen, &j, SCTL_MASK32);
1156100384Speter	if (error && error != ENOMEM)
1157100384Speter		goto done2;
1158136404Speter	if (uap->oldlenp)
1159100384Speter		suword32(uap->oldlenp, j);
1160100384Speterdone2:
1161100384Speter	mtx_unlock(&Giant);
1162100384Speter	return (error);
1163100384Speter}
1164100384Speter
1165100384Speterstruct sigaction32 {
1166100384Speter	u_int32_t	sa_u;
1167100384Speter	int		sa_flags;
1168100384Speter	sigset_t	sa_mask;
1169100384Speter};
1170100384Speter
1171121719SpeterCTASSERT(sizeof(struct sigaction32) == 24);
1172121719Speter
1173100384Speterint
1174119333Speterfreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1175100384Speter{
1176113859Sjhb	struct sigaction32 s32;
1177113859Sjhb	struct sigaction sa, osa, *sap;
1178100384Speter	int error;
1179100384Speter
1180113859Sjhb	if (uap->act) {
1181113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
1182100384Speter		if (error)
1183100384Speter			return (error);
1184113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
1185113859Sjhb		CP(s32, sa, sa_flags);
1186113859Sjhb		CP(s32, sa, sa_mask);
1187113859Sjhb		sap = &sa;
1188113859Sjhb	} else
1189113859Sjhb		sap = NULL;
1190113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1191113859Sjhb	if (error != 0 && uap->oact != NULL) {
1192113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
1193113859Sjhb		CP(osa, s32, sa_flags);
1194113859Sjhb		CP(osa, s32, sa_mask);
1195113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
1196100384Speter	}
1197100384Speter	return (error);
1198100384Speter}
1199100384Speter
1200114987Speter#ifdef COMPAT_FREEBSD4
1201114987Speterint
1202119333Speterfreebsd4_freebsd32_sigaction(struct thread *td,
1203119333Speter			     struct freebsd4_freebsd32_sigaction_args *uap)
1204114987Speter{
1205114987Speter	struct sigaction32 s32;
1206114987Speter	struct sigaction sa, osa, *sap;
1207114987Speter	int error;
1208114987Speter
1209114987Speter	if (uap->act) {
1210114987Speter		error = copyin(uap->act, &s32, sizeof(s32));
1211114987Speter		if (error)
1212114987Speter			return (error);
1213114987Speter		sa.sa_handler = PTRIN(s32.sa_u);
1214114987Speter		CP(s32, sa, sa_flags);
1215114987Speter		CP(s32, sa, sa_mask);
1216114987Speter		sap = &sa;
1217114987Speter	} else
1218114987Speter		sap = NULL;
1219114987Speter	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1220114987Speter	if (error != 0 && uap->oact != NULL) {
1221114987Speter		s32.sa_u = PTROUT(osa.sa_handler);
1222114987Speter		CP(osa, s32, sa_flags);
1223114987Speter		CP(osa, s32, sa_mask);
1224114987Speter		error = copyout(&s32, uap->oact, sizeof(s32));
1225114987Speter	}
1226114987Speter	return (error);
1227114987Speter}
1228114987Speter#endif
1229114987Speter
1230140481Spsint
1231140481Spsfreebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1232140481Sps{
1233140481Sps	struct timespec32 rmt32, rqt32;
1234140481Sps	struct timespec rmt, rqt;
1235140481Sps	int error;
1236140481Sps
1237140481Sps	error = copyin(uap->rqtp, &rqt32, sizeof(rqt));
1238140481Sps	if (error)
1239140481Sps		return (error);
1240140481Sps
1241140481Sps	CP(rqt32, rqt, tv_sec);
1242140481Sps	CP(rqt32, rqt, tv_nsec);
1243140481Sps
1244140481Sps	if (uap->rmtp &&
1245140481Sps	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1246140481Sps		return (EFAULT);
1247140481Sps	error = kern_nanosleep(td, &rqt, &rmt);
1248140481Sps	if (error && uap->rmtp) {
1249140481Sps		int error2;
1250140481Sps
1251140481Sps		CP(rmt, rmt32, tv_sec);
1252140481Sps		CP(rmt, rmt32, tv_nsec);
1253140481Sps
1254140481Sps		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt));
1255140481Sps		if (error2)
1256140481Sps			error = error2;
1257140481Sps	}
1258140481Sps	return (error);
1259140481Sps}
1260140481Sps
1261100384Speter#if 0
1262100384Speter
1263100384Speterint
1264119333Speterfreebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1265100384Speter{
1266100384Speter	int error;
1267100384Speter	caddr_t sg;
1268100384Speter	struct yyy32 *p32, s32;
1269100384Speter	struct yyy *p = NULL, s;
1270100384Speter
1271107849Salfred	p32 = uap->zzz;
1272100384Speter	if (p32) {
1273100384Speter		sg = stackgap_init();
1274100384Speter		p = stackgap_alloc(&sg, sizeof(struct yyy));
1275107849Salfred		uap->zzz = (struct yyy32 *)p;
1276100384Speter		error = copyin(p32, &s32, sizeof(s32));
1277100384Speter		if (error)
1278100384Speter			return (error);
1279100384Speter		/* translate in */
1280100384Speter		error = copyout(&s, p, sizeof(s));
1281100384Speter		if (error)
1282100384Speter			return (error);
1283100384Speter	}
1284100384Speter	error = xxx(td, (struct xxx_args *) uap);
1285100384Speter	if (error)
1286100384Speter		return (error);
1287100384Speter	if (p32) {
1288100384Speter		error = copyin(p, &s, sizeof(s));
1289100384Speter		if (error)
1290100384Speter			return (error);
1291100384Speter		/* translate out */
1292100384Speter		error = copyout(&s32, p32, sizeof(s32));
1293100384Speter	}
1294100384Speter	return (error);
1295100384Speter}
1296100384Speter
1297100384Speter#endif
1298