freebsd32_misc.c revision 147813
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 147813 2005-07-07 18:17:55Z 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
767147813Sjhbfreebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
768147813Sjhb{
769147813Sjhb	struct uio *auio;
770147813Sjhb	int error;
771147813Sjhb
772147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
773147813Sjhb	if (error)
774147813Sjhb		return (error);
775147813Sjhb	error = kern_preadv(td, uap->fd, auio, uap->offset);
776147813Sjhb	free(auio, M_IOV);
777147813Sjhb	return (error);
778147813Sjhb}
779147813Sjhb
780147813Sjhbint
781147813Sjhbfreebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
782147813Sjhb{
783147813Sjhb	struct uio *auio;
784147813Sjhb	int error;
785147813Sjhb
786147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
787147813Sjhb	if (error)
788147813Sjhb		return (error);
789147813Sjhb	error = kern_pwritev(td, uap->fd, auio, uap->offset);
790147813Sjhb	free(auio, M_IOV);
791147813Sjhb	return (error);
792147813Sjhb}
793147813Sjhb
794147813Sjhbint
795119333Speterfreebsd32_settimeofday(struct thread *td,
796119333Speter		       struct freebsd32_settimeofday_args *uap)
797100384Speter{
798144450Sjhb	struct timeval32 tv32;
799144450Sjhb	struct timeval tv, *tvp;
800144450Sjhb	struct timezone tz, *tzp;
801100384Speter	int error;
802100384Speter
803144450Sjhb	if (uap->tv) {
804144450Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
805100384Speter		if (error)
806100384Speter			return (error);
807144450Sjhb		CP(tv32, tv, tv_sec);
808144450Sjhb		CP(tv32, tv, tv_usec);
809144450Sjhb		tvp = &tv;
810144450Sjhb	} else
811144450Sjhb		tvp = NULL;
812144450Sjhb	if (uap->tzp) {
813144450Sjhb		error = copyin(uap->tzp, &tz, sizeof(tz));
814100384Speter		if (error)
815100384Speter			return (error);
816144450Sjhb		tzp = &tz;
817144450Sjhb	} else
818144450Sjhb		tzp = NULL;
819144450Sjhb	return (kern_settimeofday(td, tvp, tzp));
820100384Speter}
821100384Speter
822100384Speterint
823119333Speterfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
824100384Speter{
825142059Sjhb	struct timeval32 s32[2];
826142059Sjhb	struct timeval s[2], *sp;
827100384Speter	int error;
828100384Speter
829142059Sjhb	if (uap->tptr != NULL) {
830142059Sjhb		error = copyin(uap->tptr, s32, sizeof(s32));
831100384Speter		if (error)
832100384Speter			return (error);
833100384Speter		CP(s32[0], s[0], tv_sec);
834100384Speter		CP(s32[0], s[0], tv_usec);
835100384Speter		CP(s32[1], s[1], tv_sec);
836100384Speter		CP(s32[1], s[1], tv_usec);
837142059Sjhb		sp = s;
838142059Sjhb	} else
839142059Sjhb		sp = NULL;
840142059Sjhb	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
841100384Speter}
842100384Speter
843100384Speterint
844119333Speterfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
845100384Speter{
846144450Sjhb	struct timeval32 tv32;
847144450Sjhb	struct timeval delta, olddelta, *deltap;
848100384Speter	int error;
849100384Speter
850144450Sjhb	if (uap->delta) {
851144450Sjhb		error = copyin(uap->delta, &tv32, sizeof(tv32));
852100384Speter		if (error)
853100384Speter			return (error);
854144450Sjhb		CP(tv32, delta, tv_sec);
855144450Sjhb		CP(tv32, delta, tv_usec);
856144450Sjhb		deltap = &delta;
857144450Sjhb	} else
858144450Sjhb		deltap = NULL;
859144450Sjhb	error = kern_adjtime(td, deltap, &olddelta);
860144450Sjhb	if (uap->olddelta && error == 0) {
861144450Sjhb		CP(olddelta, tv32, tv_sec);
862144450Sjhb		CP(olddelta, tv32, tv_usec);
863144450Sjhb		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
864100384Speter	}
865100384Speter	return (error);
866100384Speter}
867100384Speter
868128597Smarcel#ifdef COMPAT_FREEBSD4
869100384Speterint
870128260Speterfreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
871100384Speter{
872142059Sjhb	struct statfs32 s32;
873142059Sjhb	struct statfs s;
874100384Speter	int error;
875100384Speter
876142059Sjhb	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
877100384Speter	if (error)
878100384Speter		return (error);
879142059Sjhb	copy_statfs(&s, &s32);
880142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
881100384Speter}
882128597Smarcel#endif
883100384Speter
884128597Smarcel#ifdef COMPAT_FREEBSD4
885100384Speterint
886128260Speterfreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
887100384Speter{
888142059Sjhb	struct statfs32 s32;
889142059Sjhb	struct statfs s;
890100384Speter	int error;
891100384Speter
892142059Sjhb	error = kern_fstatfs(td, uap->fd, &s);
893100384Speter	if (error)
894100384Speter		return (error);
895142059Sjhb	copy_statfs(&s, &s32);
896142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
897100384Speter}
898128597Smarcel#endif
899100384Speter
900128597Smarcel#ifdef COMPAT_FREEBSD4
901100384Speterint
902128260Speterfreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
903128260Speter{
904142059Sjhb	struct statfs32 s32;
905142059Sjhb	struct statfs s;
906142059Sjhb	fhandle_t fh;
907128260Speter	int error;
908128260Speter
909142059Sjhb	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
910142059Sjhb		return (error);
911142059Sjhb	error = kern_fhstatfs(td, fh, &s);
912128260Speter	if (error)
913128260Speter		return (error);
914142059Sjhb	copy_statfs(&s, &s32);
915142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
916128260Speter}
917128597Smarcel#endif
918128260Speter
919128260Speterint
920119333Speterfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
921100384Speter{
922100384Speter	/*
923100384Speter	 * Vector through to semsys if it is loaded.
924100384Speter	 */
925100384Speter	return sysent[169].sy_call(td, uap);
926100384Speter}
927100384Speter
928100384Speterint
929119333Speterfreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
930100384Speter{
931100384Speter	/*
932100384Speter	 * Vector through to msgsys if it is loaded.
933100384Speter	 */
934100384Speter	return sysent[170].sy_call(td, uap);
935100384Speter}
936100384Speter
937100384Speterint
938119333Speterfreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
939100384Speter{
940100384Speter	/*
941100384Speter	 * Vector through to shmsys if it is loaded.
942100384Speter	 */
943100384Speter	return sysent[171].sy_call(td, uap);
944100384Speter}
945100384Speter
946100384Speterint
947119333Speterfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
948100384Speter{
949100384Speter	struct pread_args ap;
950100384Speter
951107849Salfred	ap.fd = uap->fd;
952107849Salfred	ap.buf = uap->buf;
953107849Salfred	ap.nbyte = uap->nbyte;
954119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
955100384Speter	return (pread(td, &ap));
956100384Speter}
957100384Speter
958100384Speterint
959119333Speterfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
960100384Speter{
961100384Speter	struct pwrite_args ap;
962100384Speter
963107849Salfred	ap.fd = uap->fd;
964107849Salfred	ap.buf = uap->buf;
965107849Salfred	ap.nbyte = uap->nbyte;
966119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
967100384Speter	return (pwrite(td, &ap));
968100384Speter}
969100384Speter
970100384Speterint
971119333Speterfreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
972100384Speter{
973100384Speter	int error;
974100384Speter	struct lseek_args ap;
975100384Speter	off_t pos;
976100384Speter
977107849Salfred	ap.fd = uap->fd;
978119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
979107849Salfred	ap.whence = uap->whence;
980100384Speter	error = lseek(td, &ap);
981100384Speter	/* Expand the quad return into two parts for eax and edx */
982100384Speter	pos = *(off_t *)(td->td_retval);
983100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
984100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
985100384Speter	return error;
986100384Speter}
987100384Speter
988100384Speterint
989119333Speterfreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
990100384Speter{
991100384Speter	struct truncate_args ap;
992100384Speter
993107849Salfred	ap.path = uap->path;
994119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
995100384Speter	return (truncate(td, &ap));
996100384Speter}
997100384Speter
998100384Speterint
999119333Speterfreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1000100384Speter{
1001100384Speter	struct ftruncate_args ap;
1002100384Speter
1003107849Salfred	ap.fd = uap->fd;
1004119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1005100384Speter	return (ftruncate(td, &ap));
1006100384Speter}
1007100384Speter
1008104738Speter#ifdef COMPAT_FREEBSD4
1009100384Speterint
1010119333Speterfreebsd4_freebsd32_sendfile(struct thread *td,
1011119333Speter    struct freebsd4_freebsd32_sendfile_args *uap)
1012104738Speter{
1013104738Speter	struct freebsd4_sendfile_args ap;
1014104738Speter
1015107849Salfred	ap.fd = uap->fd;
1016107849Salfred	ap.s = uap->s;
1017119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1018107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1019107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1020107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1021107849Salfred	ap.flags = uap->flags;
1022104738Speter	return (freebsd4_sendfile(td, &ap));
1023104738Speter}
1024104738Speter#endif
1025104738Speter
1026104738Speterint
1027119333Speterfreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1028100384Speter{
1029100384Speter	struct sendfile_args ap;
1030100384Speter
1031107849Salfred	ap.fd = uap->fd;
1032107849Salfred	ap.s = uap->s;
1033119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1034107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1035107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1036107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1037107849Salfred	ap.flags = uap->flags;
1038100384Speter	return (sendfile(td, &ap));
1039100384Speter}
1040100384Speter
1041100384Speterstruct stat32 {
1042130640Sphk	dev_t	st_dev;
1043100384Speter	ino_t	st_ino;
1044100384Speter	mode_t	st_mode;
1045100384Speter	nlink_t	st_nlink;
1046100384Speter	uid_t	st_uid;
1047100384Speter	gid_t	st_gid;
1048130640Sphk	dev_t	st_rdev;
1049100384Speter	struct timespec32 st_atimespec;
1050100384Speter	struct timespec32 st_mtimespec;
1051100384Speter	struct timespec32 st_ctimespec;
1052100384Speter	off_t	st_size;
1053100384Speter	int64_t	st_blocks;
1054100384Speter	u_int32_t st_blksize;
1055100384Speter	u_int32_t st_flags;
1056100384Speter	u_int32_t st_gen;
1057121719Speter	struct timespec32 st_birthtimespec;
1058121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1059121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1060100384Speter};
1061100384Speter
1062121719Speter
1063121719SpeterCTASSERT(sizeof(struct stat32) == 96);
1064121719Speter
1065100384Speterstatic void
1066100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1067100384Speter{
1068100384Speter	CP(*in, *out, st_dev);
1069100384Speter	CP(*in, *out, st_ino);
1070100384Speter	CP(*in, *out, st_mode);
1071100384Speter	CP(*in, *out, st_nlink);
1072100384Speter	CP(*in, *out, st_uid);
1073100384Speter	CP(*in, *out, st_gid);
1074100384Speter	CP(*in, *out, st_rdev);
1075100384Speter	TS_CP(*in, *out, st_atimespec);
1076100384Speter	TS_CP(*in, *out, st_mtimespec);
1077100384Speter	TS_CP(*in, *out, st_ctimespec);
1078100384Speter	CP(*in, *out, st_size);
1079100384Speter	CP(*in, *out, st_blocks);
1080100384Speter	CP(*in, *out, st_blksize);
1081100384Speter	CP(*in, *out, st_flags);
1082100384Speter	CP(*in, *out, st_gen);
1083100384Speter}
1084100384Speter
1085100384Speterint
1086119333Speterfreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1087100384Speter{
1088123746Speter	struct stat sb;
1089123746Speter	struct stat32 sb32;
1090100384Speter	int error;
1091100384Speter
1092142059Sjhb	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1093100384Speter	if (error)
1094100384Speter		return (error);
1095123746Speter	copy_stat(&sb, &sb32);
1096123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1097100384Speter	return (error);
1098100384Speter}
1099100384Speter
1100100384Speterint
1101119333Speterfreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1102100384Speter{
1103123746Speter	struct stat ub;
1104123746Speter	struct stat32 ub32;
1105100384Speter	int error;
1106100384Speter
1107142059Sjhb	error = kern_fstat(td, uap->fd, &ub);
1108100384Speter	if (error)
1109100384Speter		return (error);
1110123746Speter	copy_stat(&ub, &ub32);
1111123746Speter	error = copyout(&ub32, uap->ub, sizeof(ub32));
1112100384Speter	return (error);
1113100384Speter}
1114100384Speter
1115100384Speterint
1116119333Speterfreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1117100384Speter{
1118123746Speter	struct stat sb;
1119123746Speter	struct stat32 sb32;
1120142059Sjhb	int error;
1121100384Speter
1122142059Sjhb	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1123100384Speter	if (error)
1124100384Speter		return (error);
1125123746Speter	copy_stat(&sb, &sb32);
1126123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1127100384Speter	return (error);
1128100384Speter}
1129100384Speter
1130100384Speter/*
1131100384Speter * MPSAFE
1132100384Speter */
1133100384Speterint
1134119333Speterfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1135100384Speter{
1136100384Speter	int error, name[CTL_MAXNAME];
1137100384Speter	size_t j, oldlen;
1138100384Speter
1139100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1140100384Speter		return (EINVAL);
1141136404Speter 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1142100384Speter 	if (error)
1143100384Speter		return (error);
1144100384Speter	mtx_lock(&Giant);
1145100384Speter	if (uap->oldlenp)
1146100384Speter		oldlen = fuword32(uap->oldlenp);
1147100384Speter	else
1148100384Speter		oldlen = 0;
1149100384Speter	error = userland_sysctl(td, name, uap->namelen,
1150100384Speter		uap->old, &oldlen, 1,
1151136404Speter		uap->new, uap->newlen, &j, SCTL_MASK32);
1152100384Speter	if (error && error != ENOMEM)
1153100384Speter		goto done2;
1154136404Speter	if (uap->oldlenp)
1155100384Speter		suword32(uap->oldlenp, j);
1156100384Speterdone2:
1157100384Speter	mtx_unlock(&Giant);
1158100384Speter	return (error);
1159100384Speter}
1160100384Speter
1161100384Speterstruct sigaction32 {
1162100384Speter	u_int32_t	sa_u;
1163100384Speter	int		sa_flags;
1164100384Speter	sigset_t	sa_mask;
1165100384Speter};
1166100384Speter
1167121719SpeterCTASSERT(sizeof(struct sigaction32) == 24);
1168121719Speter
1169100384Speterint
1170119333Speterfreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1171100384Speter{
1172113859Sjhb	struct sigaction32 s32;
1173113859Sjhb	struct sigaction sa, osa, *sap;
1174100384Speter	int error;
1175100384Speter
1176113859Sjhb	if (uap->act) {
1177113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
1178100384Speter		if (error)
1179100384Speter			return (error);
1180113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
1181113859Sjhb		CP(s32, sa, sa_flags);
1182113859Sjhb		CP(s32, sa, sa_mask);
1183113859Sjhb		sap = &sa;
1184113859Sjhb	} else
1185113859Sjhb		sap = NULL;
1186113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1187146583Sps	if (error == 0 && uap->oact != NULL) {
1188113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
1189113859Sjhb		CP(osa, s32, sa_flags);
1190113859Sjhb		CP(osa, s32, sa_mask);
1191113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
1192100384Speter	}
1193100384Speter	return (error);
1194100384Speter}
1195100384Speter
1196114987Speter#ifdef COMPAT_FREEBSD4
1197114987Speterint
1198119333Speterfreebsd4_freebsd32_sigaction(struct thread *td,
1199119333Speter			     struct freebsd4_freebsd32_sigaction_args *uap)
1200114987Speter{
1201114987Speter	struct sigaction32 s32;
1202114987Speter	struct sigaction sa, osa, *sap;
1203114987Speter	int error;
1204114987Speter
1205114987Speter	if (uap->act) {
1206114987Speter		error = copyin(uap->act, &s32, sizeof(s32));
1207114987Speter		if (error)
1208114987Speter			return (error);
1209114987Speter		sa.sa_handler = PTRIN(s32.sa_u);
1210114987Speter		CP(s32, sa, sa_flags);
1211114987Speter		CP(s32, sa, sa_mask);
1212114987Speter		sap = &sa;
1213114987Speter	} else
1214114987Speter		sap = NULL;
1215114987Speter	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1216146583Sps	if (error == 0 && uap->oact != NULL) {
1217114987Speter		s32.sa_u = PTROUT(osa.sa_handler);
1218114987Speter		CP(osa, s32, sa_flags);
1219114987Speter		CP(osa, s32, sa_mask);
1220114987Speter		error = copyout(&s32, uap->oact, sizeof(s32));
1221114987Speter	}
1222114987Speter	return (error);
1223114987Speter}
1224114987Speter#endif
1225114987Speter
1226140481Spsint
1227140481Spsfreebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1228140481Sps{
1229140481Sps	struct timespec32 rmt32, rqt32;
1230140481Sps	struct timespec rmt, rqt;
1231140481Sps	int error;
1232140481Sps
1233140481Sps	error = copyin(uap->rqtp, &rqt32, sizeof(rqt));
1234140481Sps	if (error)
1235140481Sps		return (error);
1236140481Sps
1237140481Sps	CP(rqt32, rqt, tv_sec);
1238140481Sps	CP(rqt32, rqt, tv_nsec);
1239140481Sps
1240140481Sps	if (uap->rmtp &&
1241140481Sps	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1242140481Sps		return (EFAULT);
1243140481Sps	error = kern_nanosleep(td, &rqt, &rmt);
1244140481Sps	if (error && uap->rmtp) {
1245140481Sps		int error2;
1246140481Sps
1247140481Sps		CP(rmt, rmt32, tv_sec);
1248140481Sps		CP(rmt, rmt32, tv_nsec);
1249140481Sps
1250140481Sps		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt));
1251140481Sps		if (error2)
1252140481Sps			error = error2;
1253140481Sps	}
1254140481Sps	return (error);
1255140481Sps}
1256140481Sps
1257100384Speter#if 0
1258100384Speter
1259100384Speterint
1260119333Speterfreebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1261100384Speter{
1262100384Speter	int error;
1263100384Speter	struct yyy32 *p32, s32;
1264100384Speter	struct yyy *p = NULL, s;
1265100384Speter
1266147654Sjhb	if (uap->zzz) {
1267147654Sjhb		error = copyin(uap->zzz, &s32, sizeof(s32));
1268100384Speter		if (error)
1269100384Speter			return (error);
1270100384Speter		/* translate in */
1271147654Sjhb		p = &s;
1272100384Speter	}
1273147654Sjhb	error = kern_xxx(td, p);
1274100384Speter	if (error)
1275100384Speter		return (error);
1276147654Sjhb	if (uap->zzz) {
1277100384Speter		/* translate out */
1278100384Speter		error = copyout(&s32, p32, sizeof(s32));
1279100384Speter	}
1280100384Speter	return (error);
1281100384Speter}
1282100384Speter
1283100384Speter#endif
1284