freebsd32_misc.c revision 147654
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 147654 2005-06-29 15:16:20Z 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>
55146950Sps#include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
56100384Speter#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
57100384Speter#include <sys/signal.h>
58100384Speter#include <sys/signalvar.h>
59100384Speter#include <sys/socket.h>
60100384Speter#include <sys/socketvar.h>
61100384Speter#include <sys/stat.h>
62113859Sjhb#include <sys/syscallsubr.h>
63100384Speter#include <sys/sysctl.h>
64100384Speter#include <sys/sysent.h>
65100384Speter#include <sys/sysproto.h>
66100384Speter#include <sys/systm.h>
67100384Speter#include <sys/unistd.h>
68100384Speter#include <sys/vnode.h>
69127140Sjhb#include <sys/wait.h>
70100384Speter
71100384Speter#include <vm/vm.h>
72100384Speter#include <vm/vm_kern.h>
73100384Speter#include <vm/vm_param.h>
74100384Speter#include <vm/pmap.h>
75100384Speter#include <vm/vm_map.h>
76100384Speter#include <vm/vm_object.h>
77100384Speter#include <vm/vm_extern.h>
78100384Speter
79119333Speter#include <compat/freebsd32/freebsd32_util.h>
80119333Speter#include <compat/freebsd32/freebsd32.h>
81119333Speter#include <compat/freebsd32/freebsd32_proto.h>
82100384Speter
83121719SpeterCTASSERT(sizeof(struct timeval32) == 8);
84121719SpeterCTASSERT(sizeof(struct timespec32) == 8);
85121719SpeterCTASSERT(sizeof(struct statfs32) == 256);
86121719SpeterCTASSERT(sizeof(struct rusage32) == 72);
87121719Speter
88100384Speterint
89119333Speterfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
90100384Speter{
91127140Sjhb	int error, status;
92127140Sjhb	struct rusage32 ru32;
93136152Sjhb	struct rusage ru, *rup;
94100384Speter
95136152Sjhb	if (uap->rusage != NULL)
96136152Sjhb		rup = &ru;
97136152Sjhb	else
98136152Sjhb		rup = NULL;
99136152Sjhb	error = kern_wait(td, uap->pid, &status, uap->options, rup);
100100384Speter	if (error)
101100384Speter		return (error);
102127140Sjhb	if (uap->status != NULL)
103127140Sjhb		error = copyout(&status, uap->status, sizeof(status));
104127140Sjhb	if (uap->rusage != NULL && error == 0) {
105100384Speter		TV_CP(ru, ru32, ru_utime);
106100384Speter		TV_CP(ru, ru32, ru_stime);
107100384Speter		CP(ru, ru32, ru_maxrss);
108100384Speter		CP(ru, ru32, ru_ixrss);
109100384Speter		CP(ru, ru32, ru_idrss);
110100384Speter		CP(ru, ru32, ru_isrss);
111100384Speter		CP(ru, ru32, ru_minflt);
112100384Speter		CP(ru, ru32, ru_majflt);
113100384Speter		CP(ru, ru32, ru_nswap);
114100384Speter		CP(ru, ru32, ru_inblock);
115100384Speter		CP(ru, ru32, ru_oublock);
116100384Speter		CP(ru, ru32, ru_msgsnd);
117100384Speter		CP(ru, ru32, ru_msgrcv);
118100384Speter		CP(ru, ru32, ru_nsignals);
119100384Speter		CP(ru, ru32, ru_nvcsw);
120100384Speter		CP(ru, ru32, ru_nivcsw);
121127140Sjhb		error = copyout(&ru32, uap->rusage, sizeof(ru32));
122100384Speter	}
123100384Speter	return (error);
124100384Speter}
125100384Speter
126128597Smarcel#ifdef COMPAT_FREEBSD4
127100384Speterstatic void
128100384Spetercopy_statfs(struct statfs *in, struct statfs32 *out)
129100384Speter{
130100384Speter	CP(*in, *out, f_bsize);
131100384Speter	CP(*in, *out, f_iosize);
132100384Speter	CP(*in, *out, f_blocks);
133100384Speter	CP(*in, *out, f_bfree);
134100384Speter	CP(*in, *out, f_bavail);
135100384Speter	CP(*in, *out, f_files);
136100384Speter	CP(*in, *out, f_ffree);
137100384Speter	CP(*in, *out, f_fsid);
138100384Speter	CP(*in, *out, f_owner);
139100384Speter	CP(*in, *out, f_type);
140100384Speter	CP(*in, *out, f_flags);
141100384Speter	CP(*in, *out, f_flags);
142100384Speter	CP(*in, *out, f_syncwrites);
143100384Speter	CP(*in, *out, f_asyncwrites);
144100384Speter	bcopy(in->f_fstypename,
145100384Speter	      out->f_fstypename, MFSNAMELEN);
146100384Speter	bcopy(in->f_mntonname,
147128260Speter	      out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
148100384Speter	CP(*in, *out, f_syncreads);
149100384Speter	CP(*in, *out, f_asyncreads);
150100384Speter	bcopy(in->f_mntfromname,
151128260Speter	      out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
152100384Speter}
153128597Smarcel#endif
154100384Speter
155128597Smarcel#ifdef COMPAT_FREEBSD4
156100384Speterint
157128260Speterfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
158100384Speter{
159147178Spjd	struct statfs *buf, *sp;
160147178Spjd	struct statfs32 stat32;
161147178Spjd	size_t count, size;
162100384Speter	int error;
163100384Speter
164147178Spjd	count = uap->bufsize / sizeof(struct statfs32);
165147178Spjd	size = count * sizeof(struct statfs);
166147302Spjd	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
167147302Spjd	if (size > 0) {
168100384Speter		count = td->td_retval[0];
169147178Spjd		sp = buf;
170147178Spjd		while (count > 0 && error == 0) {
171147178Spjd			copy_statfs(sp, &stat32);
172147178Spjd			error = copyout(&stat32, uap->buf, sizeof(stat32));
173147178Spjd			sp++;
174147178Spjd			uap->buf++;
175147178Spjd			count--;
176100384Speter		}
177147178Spjd		free(buf, M_TEMP);
178100384Speter	}
179100384Speter	return (error);
180100384Speter}
181128597Smarcel#endif
182100384Speter
183100384Speterstruct sigaltstack32 {
184100384Speter	u_int32_t	ss_sp;
185100384Speter	u_int32_t	ss_size;
186100384Speter	int		ss_flags;
187100384Speter};
188100384Speter
189121719SpeterCTASSERT(sizeof(struct sigaltstack32) == 12);
190121719Speter
191100384Speterint
192119333Speterfreebsd32_sigaltstack(struct thread *td,
193119333Speter		      struct freebsd32_sigaltstack_args *uap)
194100384Speter{
195113859Sjhb	struct sigaltstack32 s32;
196113859Sjhb	struct sigaltstack ss, oss, *ssp;
197100384Speter	int error;
198100384Speter
199113859Sjhb	if (uap->ss != NULL) {
200113859Sjhb		error = copyin(uap->ss, &s32, sizeof(s32));
201100384Speter		if (error)
202100384Speter			return (error);
203113859Sjhb		PTRIN_CP(s32, ss, ss_sp);
204113859Sjhb		CP(s32, ss, ss_size);
205113859Sjhb		CP(s32, ss, ss_flags);
206113859Sjhb		ssp = &ss;
207113859Sjhb	} else
208113859Sjhb		ssp = NULL;
209113859Sjhb	error = kern_sigaltstack(td, ssp, &oss);
210113859Sjhb	if (error == 0 && uap->oss != NULL) {
211113859Sjhb		PTROUT_CP(oss, s32, ss_sp);
212113859Sjhb		CP(oss, s32, ss_size);
213113859Sjhb		CP(oss, s32, ss_flags);
214113859Sjhb		error = copyout(&s32, uap->oss, sizeof(s32));
215100384Speter	}
216100384Speter	return (error);
217100384Speter}
218100384Speter
219142059Sjhb/*
220142059Sjhb * Custom version of exec_copyin_args() so that we can translate
221142059Sjhb * the pointers.
222142059Sjhb */
223142059Sjhbstatic int
224142059Sjhbfreebsd32_exec_copyin_args(struct image_args *args, char *fname,
225142059Sjhb    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
226100384Speter{
227142059Sjhb	char *argp, *envp;
228142059Sjhb	u_int32_t *p32, arg;
229142059Sjhb	size_t length;
230100384Speter	int error;
231100384Speter
232142059Sjhb	bzero(args, sizeof(*args));
233142059Sjhb	if (argv == NULL)
234142059Sjhb		return (EFAULT);
235100384Speter
236142059Sjhb	/*
237142059Sjhb	 * Allocate temporary demand zeroed space for argument and
238142059Sjhb	 *	environment strings
239142059Sjhb	 */
240147588Sjhb	args->buf = (char *) kmem_alloc_wait(exec_map,
241147588Sjhb	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
242142059Sjhb	if (args->buf == NULL)
243142059Sjhb		return (ENOMEM);
244142059Sjhb	args->begin_argv = args->buf;
245142059Sjhb	args->endp = args->begin_argv;
246142059Sjhb	args->stringspace = ARG_MAX;
247142059Sjhb
248142059Sjhb	args->fname = args->buf + ARG_MAX;
249142059Sjhb
250142059Sjhb	/*
251142059Sjhb	 * Copy the file name.
252142059Sjhb	 */
253142059Sjhb	error = (segflg == UIO_SYSSPACE) ?
254142059Sjhb	    copystr(fname, args->fname, PATH_MAX, &length) :
255142059Sjhb	    copyinstr(fname, args->fname, PATH_MAX, &length);
256142059Sjhb	if (error != 0)
257142059Sjhb		return (error);
258142059Sjhb
259142059Sjhb	/*
260142059Sjhb	 * extract arguments first
261142059Sjhb	 */
262142059Sjhb	p32 = argv;
263142059Sjhb	for (;;) {
264142059Sjhb		error = copyin(p32++, &arg, sizeof(arg));
265142059Sjhb		if (error)
266142059Sjhb			return (error);
267142059Sjhb		if (arg == 0)
268142059Sjhb			break;
269142059Sjhb		argp = PTRIN(arg);
270142059Sjhb		error = copyinstr(argp, args->endp, args->stringspace, &length);
271142059Sjhb		if (error) {
272142059Sjhb			if (error == ENAMETOOLONG)
273142059Sjhb				return (E2BIG);
274142059Sjhb			else
275142059Sjhb				return (error);
276142059Sjhb		}
277142059Sjhb		args->stringspace -= length;
278142059Sjhb		args->endp += length;
279142059Sjhb		args->argc++;
280100384Speter	}
281142059Sjhb
282142059Sjhb	args->begin_envv = args->endp;
283142059Sjhb
284142059Sjhb	/*
285142059Sjhb	 * extract environment strings
286142059Sjhb	 */
287142059Sjhb	if (envv) {
288142059Sjhb		p32 = envv;
289142059Sjhb		for (;;) {
290100384Speter			error = copyin(p32++, &arg, sizeof(arg));
291100384Speter			if (error)
292142059Sjhb				return (error);
293142059Sjhb			if (arg == 0)
294142059Sjhb				break;
295142059Sjhb			envp = PTRIN(arg);
296142059Sjhb			error = copyinstr(envp, args->endp, args->stringspace,
297142059Sjhb			    &length);
298142059Sjhb			if (error) {
299142059Sjhb				if (error == ENAMETOOLONG)
300142059Sjhb					return (E2BIG);
301142059Sjhb				else
302142059Sjhb					return (error);
303142059Sjhb			}
304142059Sjhb			args->stringspace -= length;
305142059Sjhb			args->endp += length;
306142059Sjhb			args->envc++;
307142059Sjhb		}
308100384Speter	}
309100384Speter
310142059Sjhb	return (0);
311100384Speter}
312100384Speter
313142059Sjhbint
314142059Sjhbfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
315142059Sjhb{
316142059Sjhb	struct image_args eargs;
317142059Sjhb	int error;
318142059Sjhb
319142059Sjhb	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
320142059Sjhb	    uap->argv, uap->envv);
321142059Sjhb	if (error == 0)
322142059Sjhb		error = kern_execve(td, &eargs, NULL);
323142059Sjhb	exec_free_args(&eargs);
324142059Sjhb	return (error);
325142059Sjhb}
326142059Sjhb
327114987Speter#ifdef __ia64__
328100384Speterstatic int
329119333Speterfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
330119333Speter		       int prot, int fd, off_t pos)
331100384Speter{
332100384Speter	vm_map_t map;
333100384Speter	vm_map_entry_t entry;
334100384Speter	int rv;
335100384Speter
336100384Speter	map = &td->td_proc->p_vmspace->vm_map;
337100384Speter	if (fd != -1)
338100384Speter		prot |= VM_PROT_WRITE;
339100384Speter
340100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
341100384Speter		if ((entry->protection & prot) != prot) {
342100384Speter			rv = vm_map_protect(map,
343100384Speter					    trunc_page(start),
344100384Speter					    round_page(end),
345100384Speter					    entry->protection | prot,
346100384Speter					    FALSE);
347100384Speter			if (rv != KERN_SUCCESS)
348100384Speter				return (EINVAL);
349100384Speter		}
350100384Speter	} else {
351100384Speter		vm_offset_t addr = trunc_page(start);
352100384Speter		rv = vm_map_find(map, 0, 0,
353100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
354100384Speter				 VM_PROT_ALL, 0);
355100384Speter		if (rv != KERN_SUCCESS)
356100384Speter			return (EINVAL);
357100384Speter	}
358100384Speter
359100384Speter	if (fd != -1) {
360100384Speter		struct pread_args r;
361107849Salfred		r.fd = fd;
362107849Salfred		r.buf = (void *) start;
363107849Salfred		r.nbyte = end - start;
364107849Salfred		r.offset = pos;
365100384Speter		return (pread(td, &r));
366100384Speter	} else {
367100384Speter		while (start < end) {
368100384Speter			subyte((void *) start, 0);
369100384Speter			start++;
370100384Speter		}
371100384Speter		return (0);
372100384Speter	}
373100384Speter}
374114987Speter#endif
375100384Speter
376100384Speterint
377119333Speterfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
378100384Speter{
379100384Speter	struct mmap_args ap;
380107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
381107849Salfred	vm_size_t len	 = uap->len;
382107849Salfred	int prot	 = uap->prot;
383107849Salfred	int flags	 = uap->flags;
384107849Salfred	int fd		 = uap->fd;
385107849Salfred	off_t pos	 = (uap->poslo
386107849Salfred			    | ((off_t)uap->poshi << 32));
387114987Speter#ifdef __ia64__
388100384Speter	vm_size_t pageoff;
389100384Speter	int error;
390100384Speter
391100384Speter	/*
392100384Speter	 * Attempt to handle page size hassles.
393100384Speter	 */
394100384Speter	pageoff = (pos & PAGE_MASK);
395100384Speter	if (flags & MAP_FIXED) {
396100384Speter		vm_offset_t start, end;
397100384Speter		start = addr;
398100384Speter		end = addr + len;
399100384Speter
400100384Speter		if (start != trunc_page(start)) {
401119333Speter			error = freebsd32_mmap_partial(td, start,
402119333Speter						       round_page(start), prot,
403119333Speter						       fd, pos);
404100384Speter			if (fd != -1)
405100384Speter				pos += round_page(start) - start;
406100384Speter			start = round_page(start);
407100384Speter		}
408100384Speter		if (end != round_page(end)) {
409100384Speter			vm_offset_t t = trunc_page(end);
410119333Speter			error = freebsd32_mmap_partial(td, t, end,
411100384Speter						  prot, fd,
412100384Speter						  pos + t - start);
413100384Speter			end = trunc_page(end);
414100384Speter		}
415100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
416100384Speter			/*
417100384Speter			 * We can't map this region at all. The specified
418100384Speter			 * address doesn't have the same alignment as the file
419100384Speter			 * position. Fake the mapping by simply reading the
420100384Speter			 * entire region into memory. First we need to make
421100384Speter			 * sure the region exists.
422100384Speter			 */
423100384Speter			vm_map_t map;
424100384Speter			struct pread_args r;
425100384Speter			int rv;
426100384Speter
427100384Speter			prot |= VM_PROT_WRITE;
428100384Speter			map = &td->td_proc->p_vmspace->vm_map;
429100384Speter			rv = vm_map_remove(map, start, end);
430100384Speter			if (rv != KERN_SUCCESS)
431100384Speter				return (EINVAL);
432100384Speter			rv = vm_map_find(map, 0, 0,
433100384Speter					 &start, end - start, FALSE,
434100384Speter					 prot, VM_PROT_ALL, 0);
435100384Speter			if (rv != KERN_SUCCESS)
436100384Speter				return (EINVAL);
437107849Salfred			r.fd = fd;
438107849Salfred			r.buf = (void *) start;
439107849Salfred			r.nbyte = end - start;
440107849Salfred			r.offset = pos;
441100384Speter			error = pread(td, &r);
442100384Speter			if (error)
443100384Speter				return (error);
444100384Speter
445100384Speter			td->td_retval[0] = addr;
446100384Speter			return (0);
447100384Speter		}
448100384Speter		if (end == start) {
449100384Speter			/*
450100384Speter			 * After dealing with the ragged ends, there
451100384Speter			 * might be none left.
452100384Speter			 */
453100384Speter			td->td_retval[0] = addr;
454100384Speter			return (0);
455100384Speter		}
456100384Speter		addr = start;
457100384Speter		len = end - start;
458100384Speter	}
459114987Speter#endif
460100384Speter
461107849Salfred	ap.addr = (void *) addr;
462107849Salfred	ap.len = len;
463107849Salfred	ap.prot = prot;
464107849Salfred	ap.flags = flags;
465107849Salfred	ap.fd = fd;
466107849Salfred	ap.pos = pos;
467100384Speter
468100384Speter	return (mmap(td, &ap));
469100384Speter}
470100384Speter
471100384Speterstruct itimerval32 {
472100384Speter	struct timeval32 it_interval;
473100384Speter	struct timeval32 it_value;
474100384Speter};
475100384Speter
476121719SpeterCTASSERT(sizeof(struct itimerval32) == 16);
477121719Speter
478100384Speterint
479119333Speterfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
480100384Speter{
481142059Sjhb	struct itimerval itv, oitv, *itvp;
482142059Sjhb	struct itimerval32 i32;
483100384Speter	int error;
484100384Speter
485142059Sjhb	if (uap->itv != NULL) {
486142059Sjhb		error = copyin(uap->itv, &i32, sizeof(i32));
487100384Speter		if (error)
488100384Speter			return (error);
489142059Sjhb		TV_CP(i32, itv, it_interval);
490142059Sjhb		TV_CP(i32, itv, it_value);
491142059Sjhb		itvp = &itv;
492142059Sjhb	} else
493142059Sjhb		itvp = NULL;
494142059Sjhb	error = kern_setitimer(td, uap->which, itvp, &oitv);
495142059Sjhb	if (error || uap->oitv == NULL)
496100384Speter		return (error);
497142059Sjhb	TV_CP(oitv, i32, it_interval);
498142059Sjhb	TV_CP(oitv, i32, it_value);
499142059Sjhb	return (copyout(&i32, uap->oitv, sizeof(i32)));
500100384Speter}
501100384Speter
502100384Speterint
503125171Speterfreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
504125171Speter{
505142059Sjhb	struct itimerval itv;
506142059Sjhb	struct itimerval32 i32;
507125171Speter	int error;
508125171Speter
509142059Sjhb	error = kern_getitimer(td, uap->which, &itv);
510142059Sjhb	if (error || uap->itv == NULL)
511125171Speter		return (error);
512142059Sjhb	TV_CP(itv, i32, it_interval);
513142059Sjhb	TV_CP(itv, i32, it_value);
514142059Sjhb	return (copyout(&i32, uap->itv, sizeof(i32)));
515125171Speter}
516125171Speter
517125171Speterint
518119333Speterfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
519100384Speter{
520142059Sjhb	struct timeval32 tv32;
521142059Sjhb	struct timeval tv, *tvp;
522100384Speter	int error;
523100384Speter
524142059Sjhb	if (uap->tv != NULL) {
525142059Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
526100384Speter		if (error)
527100384Speter			return (error);
528142059Sjhb		CP(tv32, tv, tv_sec);
529142059Sjhb		CP(tv32, tv, tv_usec);
530142059Sjhb		tvp = &tv;
531142059Sjhb	} else
532142059Sjhb		tvp = NULL;
533100384Speter	/*
534100384Speter	 * XXX big-endian needs to convert the fd_sets too.
535142059Sjhb	 * XXX Do pointers need PTRIN()?
536100384Speter	 */
537142059Sjhb	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
538100384Speter}
539100384Speter
540114987Speterstruct kevent32 {
541114987Speter	u_int32_t	ident;		/* identifier for this event */
542114987Speter	short		filter;		/* filter for event */
543114987Speter	u_short		flags;
544114987Speter	u_int		fflags;
545114987Speter	int32_t		data;
546114987Speter	u_int32_t	udata;		/* opaque user data identifier */
547114987Speter};
548114987Speter
549121719SpeterCTASSERT(sizeof(struct kevent32) == 20);
550146950Spsstatic int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
551146950Spsstatic int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
552121719Speter
553146950Sps/*
554146950Sps * Copy 'count' items into the destination list pointed to by uap->eventlist.
555146950Sps */
556146950Spsstatic int
557146950Spsfreebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
558146950Sps{
559146950Sps	struct freebsd32_kevent_args *uap;
560146950Sps	struct kevent32	ks32[KQ_NEVENTS];
561146950Sps	int i, error = 0;
562146950Sps
563146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
564146950Sps	uap = (struct freebsd32_kevent_args *)arg;
565146950Sps
566146950Sps	for (i = 0; i < count; i++) {
567146950Sps		CP(kevp[i], ks32[i], ident);
568146950Sps		CP(kevp[i], ks32[i], filter);
569146950Sps		CP(kevp[i], ks32[i], flags);
570146950Sps		CP(kevp[i], ks32[i], fflags);
571146950Sps		CP(kevp[i], ks32[i], data);
572146950Sps		PTROUT_CP(kevp[i], ks32[i], udata);
573146950Sps	}
574146950Sps	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
575146950Sps	if (error == 0)
576146950Sps		uap->eventlist += count;
577146950Sps	return (error);
578146950Sps}
579146950Sps
580146950Sps/*
581146950Sps * Copy 'count' items from the list pointed to by uap->changelist.
582146950Sps */
583146950Spsstatic int
584146950Spsfreebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
585146950Sps{
586146950Sps	struct freebsd32_kevent_args *uap;
587146950Sps	struct kevent32	ks32[KQ_NEVENTS];
588146950Sps	int i, error = 0;
589146950Sps
590146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
591146950Sps	uap = (struct freebsd32_kevent_args *)arg;
592146950Sps
593146950Sps	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
594146950Sps	if (error)
595146950Sps		goto done;
596146950Sps	uap->changelist += count;
597146950Sps
598146950Sps	for (i = 0; i < count; i++) {
599146950Sps		CP(ks32[i], kevp[i], ident);
600146950Sps		CP(ks32[i], kevp[i], filter);
601146950Sps		CP(ks32[i], kevp[i], flags);
602146950Sps		CP(ks32[i], kevp[i], fflags);
603146950Sps		CP(ks32[i], kevp[i], data);
604146950Sps		PTRIN_CP(ks32[i], kevp[i], udata);
605146950Sps	}
606146950Spsdone:
607146950Sps	return (error);
608146950Sps}
609146950Sps
610100384Speterint
611119333Speterfreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
612114987Speter{
613114987Speter	struct timespec32 ts32;
614142934Sps	struct timespec ts, *tsp;
615146950Sps	struct kevent_copyops k_ops = { uap,
616146950Sps					freebsd32_kevent_copyout,
617146950Sps					freebsd32_kevent_copyin};
618146950Sps	int error;
619114987Speter
620114987Speter
621114987Speter	if (uap->timeout) {
622114987Speter		error = copyin(uap->timeout, &ts32, sizeof(ts32));
623114987Speter		if (error)
624114987Speter			return (error);
625114987Speter		CP(ts32, ts, tv_sec);
626114987Speter		CP(ts32, ts, tv_nsec);
627142934Sps		tsp = &ts;
628142934Sps	} else
629142934Sps		tsp = NULL;
630146950Sps	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
631146950Sps	    &k_ops, tsp);
632142934Sps	return (error);
633114987Speter}
634114987Speter
635114987Speterint
636119333Speterfreebsd32_gettimeofday(struct thread *td,
637119333Speter		       struct freebsd32_gettimeofday_args *uap)
638100384Speter{
639123425Speter	struct timeval atv;
640123425Speter	struct timeval32 atv32;
641123425Speter	struct timezone rtz;
642123425Speter	int error = 0;
643100384Speter
644123425Speter	if (uap->tp) {
645123425Speter		microtime(&atv);
646123425Speter		CP(atv, atv32, tv_sec);
647123425Speter		CP(atv, atv32, tv_usec);
648123425Speter		error = copyout(&atv32, uap->tp, sizeof (atv32));
649100384Speter	}
650123425Speter	if (error == 0 && uap->tzp != NULL) {
651123425Speter		rtz.tz_minuteswest = tz_minuteswest;
652123425Speter		rtz.tz_dsttime = tz_dsttime;
653123425Speter		error = copyout(&rtz, uap->tzp, sizeof (rtz));
654100384Speter	}
655100384Speter	return (error);
656100384Speter}
657100384Speter
658100384Speterint
659119333Speterfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
660100384Speter{
661136152Sjhb	struct rusage32 s32;
662136152Sjhb	struct rusage s;
663100384Speter	int error;
664100384Speter
665136152Sjhb	error = kern_getrusage(td, uap->who, &s);
666100384Speter	if (error)
667100384Speter		return (error);
668136152Sjhb	if (uap->rusage != NULL) {
669100384Speter		TV_CP(s, s32, ru_utime);
670100384Speter		TV_CP(s, s32, ru_stime);
671100384Speter		CP(s, s32, ru_maxrss);
672100384Speter		CP(s, s32, ru_ixrss);
673100384Speter		CP(s, s32, ru_idrss);
674100384Speter		CP(s, s32, ru_isrss);
675100384Speter		CP(s, s32, ru_minflt);
676100384Speter		CP(s, s32, ru_majflt);
677100384Speter		CP(s, s32, ru_nswap);
678100384Speter		CP(s, s32, ru_inblock);
679100384Speter		CP(s, s32, ru_oublock);
680100384Speter		CP(s, s32, ru_msgsnd);
681100384Speter		CP(s, s32, ru_msgrcv);
682100384Speter		CP(s, s32, ru_nsignals);
683100384Speter		CP(s, s32, ru_nvcsw);
684100384Speter		CP(s, s32, ru_nivcsw);
685136152Sjhb		error = copyout(&s32, uap->rusage, sizeof(s32));
686100384Speter	}
687100384Speter	return (error);
688100384Speter}
689100384Speter
690100384Speterstruct iovec32 {
691100384Speter	u_int32_t iov_base;
692100384Speter	int	iov_len;
693100384Speter};
694100384Speter
695121719SpeterCTASSERT(sizeof(struct iovec32) == 8);
696121719Speter
697144450Sjhbstatic int
698144450Sjhbfreebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
699100384Speter{
700144450Sjhb	struct iovec32 iov32;
701144450Sjhb	struct iovec *iov;
702144450Sjhb	struct uio *uio;
703144450Sjhb	u_int iovlen;
704144450Sjhb	int error, i;
705100384Speter
706144450Sjhb	*uiop = NULL;
707144450Sjhb	if (iovcnt > UIO_MAXIOV)
708100384Speter		return (EINVAL);
709144450Sjhb	iovlen = iovcnt * sizeof(struct iovec);
710144450Sjhb	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
711144450Sjhb	iov = (struct iovec *)(uio + 1);
712144450Sjhb	for (i = 0; i < iovcnt; i++) {
713144450Sjhb		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
714144450Sjhb		if (error) {
715144450Sjhb			free(uio, M_IOV);
716144450Sjhb			return (error);
717144450Sjhb		}
718144450Sjhb		iov[i].iov_base = PTRIN(iov32.iov_base);
719144450Sjhb		iov[i].iov_len = iov32.iov_len;
720100384Speter	}
721144450Sjhb	uio->uio_iov = iov;
722144450Sjhb	uio->uio_iovcnt = iovcnt;
723144450Sjhb	uio->uio_segflg = UIO_USERSPACE;
724144450Sjhb	uio->uio_offset = -1;
725144450Sjhb	uio->uio_resid = 0;
726144450Sjhb	for (i = 0; i < iovcnt; i++) {
727144450Sjhb		if (iov->iov_len > INT_MAX - uio->uio_resid) {
728144450Sjhb			free(uio, M_IOV);
729144450Sjhb			return (EINVAL);
730144450Sjhb		}
731144450Sjhb		uio->uio_resid += iov->iov_len;
732144450Sjhb		iov++;
733144450Sjhb	}
734144450Sjhb	*uiop = uio;
735144450Sjhb	return (0);
736144450Sjhb}
737100384Speter
738144450Sjhbint
739144450Sjhbfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
740144450Sjhb{
741144450Sjhb	struct uio *auio;
742144450Sjhb	int error;
743100384Speter
744144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
745144450Sjhb	if (error)
746144450Sjhb		return (error);
747144450Sjhb	error = kern_readv(td, uap->fd, auio);
748144450Sjhb	free(auio, M_IOV);
749100384Speter	return (error);
750100384Speter}
751100384Speter
752100384Speterint
753119333Speterfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
754100384Speter{
755144450Sjhb	struct uio *auio;
756144450Sjhb	int error;
757100384Speter
758144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
759144450Sjhb	if (error)
760144450Sjhb		return (error);
761144450Sjhb	error = kern_writev(td, uap->fd, auio);
762144450Sjhb	free(auio, M_IOV);
763100384Speter	return (error);
764100384Speter}
765100384Speter
766100384Speterint
767119333Speterfreebsd32_settimeofday(struct thread *td,
768119333Speter		       struct freebsd32_settimeofday_args *uap)
769100384Speter{
770144450Sjhb	struct timeval32 tv32;
771144450Sjhb	struct timeval tv, *tvp;
772144450Sjhb	struct timezone tz, *tzp;
773100384Speter	int error;
774100384Speter
775144450Sjhb	if (uap->tv) {
776144450Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
777100384Speter		if (error)
778100384Speter			return (error);
779144450Sjhb		CP(tv32, tv, tv_sec);
780144450Sjhb		CP(tv32, tv, tv_usec);
781144450Sjhb		tvp = &tv;
782144450Sjhb	} else
783144450Sjhb		tvp = NULL;
784144450Sjhb	if (uap->tzp) {
785144450Sjhb		error = copyin(uap->tzp, &tz, sizeof(tz));
786100384Speter		if (error)
787100384Speter			return (error);
788144450Sjhb		tzp = &tz;
789144450Sjhb	} else
790144450Sjhb		tzp = NULL;
791144450Sjhb	return (kern_settimeofday(td, tvp, tzp));
792100384Speter}
793100384Speter
794100384Speterint
795119333Speterfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
796100384Speter{
797142059Sjhb	struct timeval32 s32[2];
798142059Sjhb	struct timeval s[2], *sp;
799100384Speter	int error;
800100384Speter
801142059Sjhb	if (uap->tptr != NULL) {
802142059Sjhb		error = copyin(uap->tptr, s32, sizeof(s32));
803100384Speter		if (error)
804100384Speter			return (error);
805100384Speter		CP(s32[0], s[0], tv_sec);
806100384Speter		CP(s32[0], s[0], tv_usec);
807100384Speter		CP(s32[1], s[1], tv_sec);
808100384Speter		CP(s32[1], s[1], tv_usec);
809142059Sjhb		sp = s;
810142059Sjhb	} else
811142059Sjhb		sp = NULL;
812142059Sjhb	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
813100384Speter}
814100384Speter
815100384Speterint
816119333Speterfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
817100384Speter{
818144450Sjhb	struct timeval32 tv32;
819144450Sjhb	struct timeval delta, olddelta, *deltap;
820100384Speter	int error;
821100384Speter
822144450Sjhb	if (uap->delta) {
823144450Sjhb		error = copyin(uap->delta, &tv32, sizeof(tv32));
824100384Speter		if (error)
825100384Speter			return (error);
826144450Sjhb		CP(tv32, delta, tv_sec);
827144450Sjhb		CP(tv32, delta, tv_usec);
828144450Sjhb		deltap = &delta;
829144450Sjhb	} else
830144450Sjhb		deltap = NULL;
831144450Sjhb	error = kern_adjtime(td, deltap, &olddelta);
832144450Sjhb	if (uap->olddelta && error == 0) {
833144450Sjhb		CP(olddelta, tv32, tv_sec);
834144450Sjhb		CP(olddelta, tv32, tv_usec);
835144450Sjhb		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
836100384Speter	}
837100384Speter	return (error);
838100384Speter}
839100384Speter
840128597Smarcel#ifdef COMPAT_FREEBSD4
841100384Speterint
842128260Speterfreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
843100384Speter{
844142059Sjhb	struct statfs32 s32;
845142059Sjhb	struct statfs s;
846100384Speter	int error;
847100384Speter
848142059Sjhb	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
849100384Speter	if (error)
850100384Speter		return (error);
851142059Sjhb	copy_statfs(&s, &s32);
852142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
853100384Speter}
854128597Smarcel#endif
855100384Speter
856128597Smarcel#ifdef COMPAT_FREEBSD4
857100384Speterint
858128260Speterfreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
859100384Speter{
860142059Sjhb	struct statfs32 s32;
861142059Sjhb	struct statfs s;
862100384Speter	int error;
863100384Speter
864142059Sjhb	error = kern_fstatfs(td, uap->fd, &s);
865100384Speter	if (error)
866100384Speter		return (error);
867142059Sjhb	copy_statfs(&s, &s32);
868142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
869100384Speter}
870128597Smarcel#endif
871100384Speter
872128597Smarcel#ifdef COMPAT_FREEBSD4
873100384Speterint
874128260Speterfreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
875128260Speter{
876142059Sjhb	struct statfs32 s32;
877142059Sjhb	struct statfs s;
878142059Sjhb	fhandle_t fh;
879128260Speter	int error;
880128260Speter
881142059Sjhb	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
882142059Sjhb		return (error);
883142059Sjhb	error = kern_fhstatfs(td, fh, &s);
884128260Speter	if (error)
885128260Speter		return (error);
886142059Sjhb	copy_statfs(&s, &s32);
887142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
888128260Speter}
889128597Smarcel#endif
890128260Speter
891128260Speterint
892119333Speterfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
893100384Speter{
894100384Speter	/*
895100384Speter	 * Vector through to semsys if it is loaded.
896100384Speter	 */
897100384Speter	return sysent[169].sy_call(td, uap);
898100384Speter}
899100384Speter
900100384Speterint
901119333Speterfreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
902100384Speter{
903100384Speter	/*
904100384Speter	 * Vector through to msgsys if it is loaded.
905100384Speter	 */
906100384Speter	return sysent[170].sy_call(td, uap);
907100384Speter}
908100384Speter
909100384Speterint
910119333Speterfreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
911100384Speter{
912100384Speter	/*
913100384Speter	 * Vector through to shmsys if it is loaded.
914100384Speter	 */
915100384Speter	return sysent[171].sy_call(td, uap);
916100384Speter}
917100384Speter
918100384Speterint
919119333Speterfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
920100384Speter{
921100384Speter	struct pread_args ap;
922100384Speter
923107849Salfred	ap.fd = uap->fd;
924107849Salfred	ap.buf = uap->buf;
925107849Salfred	ap.nbyte = uap->nbyte;
926119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
927100384Speter	return (pread(td, &ap));
928100384Speter}
929100384Speter
930100384Speterint
931119333Speterfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
932100384Speter{
933100384Speter	struct pwrite_args ap;
934100384Speter
935107849Salfred	ap.fd = uap->fd;
936107849Salfred	ap.buf = uap->buf;
937107849Salfred	ap.nbyte = uap->nbyte;
938119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
939100384Speter	return (pwrite(td, &ap));
940100384Speter}
941100384Speter
942100384Speterint
943119333Speterfreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
944100384Speter{
945100384Speter	int error;
946100384Speter	struct lseek_args ap;
947100384Speter	off_t pos;
948100384Speter
949107849Salfred	ap.fd = uap->fd;
950119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
951107849Salfred	ap.whence = uap->whence;
952100384Speter	error = lseek(td, &ap);
953100384Speter	/* Expand the quad return into two parts for eax and edx */
954100384Speter	pos = *(off_t *)(td->td_retval);
955100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
956100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
957100384Speter	return error;
958100384Speter}
959100384Speter
960100384Speterint
961119333Speterfreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
962100384Speter{
963100384Speter	struct truncate_args ap;
964100384Speter
965107849Salfred	ap.path = uap->path;
966119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
967100384Speter	return (truncate(td, &ap));
968100384Speter}
969100384Speter
970100384Speterint
971119333Speterfreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
972100384Speter{
973100384Speter	struct ftruncate_args ap;
974100384Speter
975107849Salfred	ap.fd = uap->fd;
976119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
977100384Speter	return (ftruncate(td, &ap));
978100384Speter}
979100384Speter
980104738Speter#ifdef COMPAT_FREEBSD4
981100384Speterint
982119333Speterfreebsd4_freebsd32_sendfile(struct thread *td,
983119333Speter    struct freebsd4_freebsd32_sendfile_args *uap)
984104738Speter{
985104738Speter	struct freebsd4_sendfile_args ap;
986104738Speter
987107849Salfred	ap.fd = uap->fd;
988107849Salfred	ap.s = uap->s;
989119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
990107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
991107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
992107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
993107849Salfred	ap.flags = uap->flags;
994104738Speter	return (freebsd4_sendfile(td, &ap));
995104738Speter}
996104738Speter#endif
997104738Speter
998104738Speterint
999119333Speterfreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1000100384Speter{
1001100384Speter	struct sendfile_args ap;
1002100384Speter
1003107849Salfred	ap.fd = uap->fd;
1004107849Salfred	ap.s = uap->s;
1005119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1006107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1007107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1008107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1009107849Salfred	ap.flags = uap->flags;
1010100384Speter	return (sendfile(td, &ap));
1011100384Speter}
1012100384Speter
1013100384Speterstruct stat32 {
1014130640Sphk	dev_t	st_dev;
1015100384Speter	ino_t	st_ino;
1016100384Speter	mode_t	st_mode;
1017100384Speter	nlink_t	st_nlink;
1018100384Speter	uid_t	st_uid;
1019100384Speter	gid_t	st_gid;
1020130640Sphk	dev_t	st_rdev;
1021100384Speter	struct timespec32 st_atimespec;
1022100384Speter	struct timespec32 st_mtimespec;
1023100384Speter	struct timespec32 st_ctimespec;
1024100384Speter	off_t	st_size;
1025100384Speter	int64_t	st_blocks;
1026100384Speter	u_int32_t st_blksize;
1027100384Speter	u_int32_t st_flags;
1028100384Speter	u_int32_t st_gen;
1029121719Speter	struct timespec32 st_birthtimespec;
1030121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1031121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1032100384Speter};
1033100384Speter
1034121719Speter
1035121719SpeterCTASSERT(sizeof(struct stat32) == 96);
1036121719Speter
1037100384Speterstatic void
1038100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1039100384Speter{
1040100384Speter	CP(*in, *out, st_dev);
1041100384Speter	CP(*in, *out, st_ino);
1042100384Speter	CP(*in, *out, st_mode);
1043100384Speter	CP(*in, *out, st_nlink);
1044100384Speter	CP(*in, *out, st_uid);
1045100384Speter	CP(*in, *out, st_gid);
1046100384Speter	CP(*in, *out, st_rdev);
1047100384Speter	TS_CP(*in, *out, st_atimespec);
1048100384Speter	TS_CP(*in, *out, st_mtimespec);
1049100384Speter	TS_CP(*in, *out, st_ctimespec);
1050100384Speter	CP(*in, *out, st_size);
1051100384Speter	CP(*in, *out, st_blocks);
1052100384Speter	CP(*in, *out, st_blksize);
1053100384Speter	CP(*in, *out, st_flags);
1054100384Speter	CP(*in, *out, st_gen);
1055100384Speter}
1056100384Speter
1057100384Speterint
1058119333Speterfreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1059100384Speter{
1060123746Speter	struct stat sb;
1061123746Speter	struct stat32 sb32;
1062100384Speter	int error;
1063100384Speter
1064142059Sjhb	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1065100384Speter	if (error)
1066100384Speter		return (error);
1067123746Speter	copy_stat(&sb, &sb32);
1068123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1069100384Speter	return (error);
1070100384Speter}
1071100384Speter
1072100384Speterint
1073119333Speterfreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1074100384Speter{
1075123746Speter	struct stat ub;
1076123746Speter	struct stat32 ub32;
1077100384Speter	int error;
1078100384Speter
1079142059Sjhb	error = kern_fstat(td, uap->fd, &ub);
1080100384Speter	if (error)
1081100384Speter		return (error);
1082123746Speter	copy_stat(&ub, &ub32);
1083123746Speter	error = copyout(&ub32, uap->ub, sizeof(ub32));
1084100384Speter	return (error);
1085100384Speter}
1086100384Speter
1087100384Speterint
1088119333Speterfreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1089100384Speter{
1090123746Speter	struct stat sb;
1091123746Speter	struct stat32 sb32;
1092142059Sjhb	int error;
1093100384Speter
1094142059Sjhb	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1095100384Speter	if (error)
1096100384Speter		return (error);
1097123746Speter	copy_stat(&sb, &sb32);
1098123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1099100384Speter	return (error);
1100100384Speter}
1101100384Speter
1102100384Speter/*
1103100384Speter * MPSAFE
1104100384Speter */
1105100384Speterint
1106119333Speterfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1107100384Speter{
1108100384Speter	int error, name[CTL_MAXNAME];
1109100384Speter	size_t j, oldlen;
1110100384Speter
1111100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1112100384Speter		return (EINVAL);
1113136404Speter 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1114100384Speter 	if (error)
1115100384Speter		return (error);
1116100384Speter	mtx_lock(&Giant);
1117100384Speter	if (uap->oldlenp)
1118100384Speter		oldlen = fuword32(uap->oldlenp);
1119100384Speter	else
1120100384Speter		oldlen = 0;
1121100384Speter	error = userland_sysctl(td, name, uap->namelen,
1122100384Speter		uap->old, &oldlen, 1,
1123136404Speter		uap->new, uap->newlen, &j, SCTL_MASK32);
1124100384Speter	if (error && error != ENOMEM)
1125100384Speter		goto done2;
1126136404Speter	if (uap->oldlenp)
1127100384Speter		suword32(uap->oldlenp, j);
1128100384Speterdone2:
1129100384Speter	mtx_unlock(&Giant);
1130100384Speter	return (error);
1131100384Speter}
1132100384Speter
1133100384Speterstruct sigaction32 {
1134100384Speter	u_int32_t	sa_u;
1135100384Speter	int		sa_flags;
1136100384Speter	sigset_t	sa_mask;
1137100384Speter};
1138100384Speter
1139121719SpeterCTASSERT(sizeof(struct sigaction32) == 24);
1140121719Speter
1141100384Speterint
1142119333Speterfreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1143100384Speter{
1144113859Sjhb	struct sigaction32 s32;
1145113859Sjhb	struct sigaction sa, osa, *sap;
1146100384Speter	int error;
1147100384Speter
1148113859Sjhb	if (uap->act) {
1149113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
1150100384Speter		if (error)
1151100384Speter			return (error);
1152113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
1153113859Sjhb		CP(s32, sa, sa_flags);
1154113859Sjhb		CP(s32, sa, sa_mask);
1155113859Sjhb		sap = &sa;
1156113859Sjhb	} else
1157113859Sjhb		sap = NULL;
1158113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1159146583Sps	if (error == 0 && uap->oact != NULL) {
1160113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
1161113859Sjhb		CP(osa, s32, sa_flags);
1162113859Sjhb		CP(osa, s32, sa_mask);
1163113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
1164100384Speter	}
1165100384Speter	return (error);
1166100384Speter}
1167100384Speter
1168114987Speter#ifdef COMPAT_FREEBSD4
1169114987Speterint
1170119333Speterfreebsd4_freebsd32_sigaction(struct thread *td,
1171119333Speter			     struct freebsd4_freebsd32_sigaction_args *uap)
1172114987Speter{
1173114987Speter	struct sigaction32 s32;
1174114987Speter	struct sigaction sa, osa, *sap;
1175114987Speter	int error;
1176114987Speter
1177114987Speter	if (uap->act) {
1178114987Speter		error = copyin(uap->act, &s32, sizeof(s32));
1179114987Speter		if (error)
1180114987Speter			return (error);
1181114987Speter		sa.sa_handler = PTRIN(s32.sa_u);
1182114987Speter		CP(s32, sa, sa_flags);
1183114987Speter		CP(s32, sa, sa_mask);
1184114987Speter		sap = &sa;
1185114987Speter	} else
1186114987Speter		sap = NULL;
1187114987Speter	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1188146583Sps	if (error == 0 && uap->oact != NULL) {
1189114987Speter		s32.sa_u = PTROUT(osa.sa_handler);
1190114987Speter		CP(osa, s32, sa_flags);
1191114987Speter		CP(osa, s32, sa_mask);
1192114987Speter		error = copyout(&s32, uap->oact, sizeof(s32));
1193114987Speter	}
1194114987Speter	return (error);
1195114987Speter}
1196114987Speter#endif
1197114987Speter
1198140481Spsint
1199140481Spsfreebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1200140481Sps{
1201140481Sps	struct timespec32 rmt32, rqt32;
1202140481Sps	struct timespec rmt, rqt;
1203140481Sps	int error;
1204140481Sps
1205140481Sps	error = copyin(uap->rqtp, &rqt32, sizeof(rqt));
1206140481Sps	if (error)
1207140481Sps		return (error);
1208140481Sps
1209140481Sps	CP(rqt32, rqt, tv_sec);
1210140481Sps	CP(rqt32, rqt, tv_nsec);
1211140481Sps
1212140481Sps	if (uap->rmtp &&
1213140481Sps	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1214140481Sps		return (EFAULT);
1215140481Sps	error = kern_nanosleep(td, &rqt, &rmt);
1216140481Sps	if (error && uap->rmtp) {
1217140481Sps		int error2;
1218140481Sps
1219140481Sps		CP(rmt, rmt32, tv_sec);
1220140481Sps		CP(rmt, rmt32, tv_nsec);
1221140481Sps
1222140481Sps		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt));
1223140481Sps		if (error2)
1224140481Sps			error = error2;
1225140481Sps	}
1226140481Sps	return (error);
1227140481Sps}
1228140481Sps
1229100384Speter#if 0
1230100384Speter
1231100384Speterint
1232119333Speterfreebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1233100384Speter{
1234100384Speter	int error;
1235100384Speter	struct yyy32 *p32, s32;
1236100384Speter	struct yyy *p = NULL, s;
1237100384Speter
1238147654Sjhb	if (uap->zzz) {
1239147654Sjhb		error = copyin(uap->zzz, &s32, sizeof(s32));
1240100384Speter		if (error)
1241100384Speter			return (error);
1242100384Speter		/* translate in */
1243147654Sjhb		p = &s;
1244100384Speter	}
1245147654Sjhb	error = kern_xxx(td, p);
1246100384Speter	if (error)
1247100384Speter		return (error);
1248147654Sjhb	if (uap->zzz) {
1249100384Speter		/* translate out */
1250100384Speter		error = copyout(&s32, p32, sizeof(s32));
1251100384Speter	}
1252100384Speter	return (error);
1253100384Speter}
1254100384Speter
1255100384Speter#endif
1256