freebsd32_misc.c revision 150883
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 150883 2005-10-03 18:34:17Z 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>
62150883Sjhb#include <sys/syscall.h>
63113859Sjhb#include <sys/syscallsubr.h>
64100384Speter#include <sys/sysctl.h>
65100384Speter#include <sys/sysent.h>
66100384Speter#include <sys/sysproto.h>
67100384Speter#include <sys/systm.h>
68100384Speter#include <sys/unistd.h>
69100384Speter#include <sys/vnode.h>
70127140Sjhb#include <sys/wait.h>
71100384Speter
72100384Speter#include <vm/vm.h>
73100384Speter#include <vm/vm_kern.h>
74100384Speter#include <vm/vm_param.h>
75100384Speter#include <vm/pmap.h>
76100384Speter#include <vm/vm_map.h>
77100384Speter#include <vm/vm_object.h>
78100384Speter#include <vm/vm_extern.h>
79100384Speter
80119333Speter#include <compat/freebsd32/freebsd32_util.h>
81119333Speter#include <compat/freebsd32/freebsd32.h>
82119333Speter#include <compat/freebsd32/freebsd32_proto.h>
83100384Speter
84121719SpeterCTASSERT(sizeof(struct timeval32) == 8);
85121719SpeterCTASSERT(sizeof(struct timespec32) == 8);
86121719SpeterCTASSERT(sizeof(struct statfs32) == 256);
87121719SpeterCTASSERT(sizeof(struct rusage32) == 72);
88121719Speter
89100384Speterint
90119333Speterfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
91100384Speter{
92127140Sjhb	int error, status;
93127140Sjhb	struct rusage32 ru32;
94136152Sjhb	struct rusage ru, *rup;
95100384Speter
96136152Sjhb	if (uap->rusage != NULL)
97136152Sjhb		rup = &ru;
98136152Sjhb	else
99136152Sjhb		rup = NULL;
100136152Sjhb	error = kern_wait(td, uap->pid, &status, uap->options, rup);
101100384Speter	if (error)
102100384Speter		return (error);
103127140Sjhb	if (uap->status != NULL)
104127140Sjhb		error = copyout(&status, uap->status, sizeof(status));
105127140Sjhb	if (uap->rusage != NULL && error == 0) {
106100384Speter		TV_CP(ru, ru32, ru_utime);
107100384Speter		TV_CP(ru, ru32, ru_stime);
108100384Speter		CP(ru, ru32, ru_maxrss);
109100384Speter		CP(ru, ru32, ru_ixrss);
110100384Speter		CP(ru, ru32, ru_idrss);
111100384Speter		CP(ru, ru32, ru_isrss);
112100384Speter		CP(ru, ru32, ru_minflt);
113100384Speter		CP(ru, ru32, ru_majflt);
114100384Speter		CP(ru, ru32, ru_nswap);
115100384Speter		CP(ru, ru32, ru_inblock);
116100384Speter		CP(ru, ru32, ru_oublock);
117100384Speter		CP(ru, ru32, ru_msgsnd);
118100384Speter		CP(ru, ru32, ru_msgrcv);
119100384Speter		CP(ru, ru32, ru_nsignals);
120100384Speter		CP(ru, ru32, ru_nvcsw);
121100384Speter		CP(ru, ru32, ru_nivcsw);
122127140Sjhb		error = copyout(&ru32, uap->rusage, sizeof(ru32));
123100384Speter	}
124100384Speter	return (error);
125100384Speter}
126100384Speter
127128597Smarcel#ifdef COMPAT_FREEBSD4
128100384Speterstatic void
129100384Spetercopy_statfs(struct statfs *in, struct statfs32 *out)
130100384Speter{
131100384Speter	CP(*in, *out, f_bsize);
132100384Speter	CP(*in, *out, f_iosize);
133100384Speter	CP(*in, *out, f_blocks);
134100384Speter	CP(*in, *out, f_bfree);
135100384Speter	CP(*in, *out, f_bavail);
136100384Speter	CP(*in, *out, f_files);
137100384Speter	CP(*in, *out, f_ffree);
138100384Speter	CP(*in, *out, f_fsid);
139100384Speter	CP(*in, *out, f_owner);
140100384Speter	CP(*in, *out, f_type);
141100384Speter	CP(*in, *out, f_flags);
142100384Speter	CP(*in, *out, f_flags);
143100384Speter	CP(*in, *out, f_syncwrites);
144100384Speter	CP(*in, *out, f_asyncwrites);
145100384Speter	bcopy(in->f_fstypename,
146100384Speter	      out->f_fstypename, MFSNAMELEN);
147100384Speter	bcopy(in->f_mntonname,
148128260Speter	      out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
149100384Speter	CP(*in, *out, f_syncreads);
150100384Speter	CP(*in, *out, f_asyncreads);
151100384Speter	bcopy(in->f_mntfromname,
152128260Speter	      out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
153100384Speter}
154128597Smarcel#endif
155100384Speter
156128597Smarcel#ifdef COMPAT_FREEBSD4
157100384Speterint
158128260Speterfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
159100384Speter{
160147178Spjd	struct statfs *buf, *sp;
161147178Spjd	struct statfs32 stat32;
162147178Spjd	size_t count, size;
163100384Speter	int error;
164100384Speter
165147178Spjd	count = uap->bufsize / sizeof(struct statfs32);
166147178Spjd	size = count * sizeof(struct statfs);
167147302Spjd	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
168147302Spjd	if (size > 0) {
169100384Speter		count = td->td_retval[0];
170147178Spjd		sp = buf;
171147178Spjd		while (count > 0 && error == 0) {
172147178Spjd			copy_statfs(sp, &stat32);
173147178Spjd			error = copyout(&stat32, uap->buf, sizeof(stat32));
174147178Spjd			sp++;
175147178Spjd			uap->buf++;
176147178Spjd			count--;
177100384Speter		}
178147178Spjd		free(buf, M_TEMP);
179100384Speter	}
180100384Speter	return (error);
181100384Speter}
182128597Smarcel#endif
183100384Speter
184100384Speterstruct sigaltstack32 {
185100384Speter	u_int32_t	ss_sp;
186100384Speter	u_int32_t	ss_size;
187100384Speter	int		ss_flags;
188100384Speter};
189100384Speter
190121719SpeterCTASSERT(sizeof(struct sigaltstack32) == 12);
191121719Speter
192100384Speterint
193119333Speterfreebsd32_sigaltstack(struct thread *td,
194119333Speter		      struct freebsd32_sigaltstack_args *uap)
195100384Speter{
196113859Sjhb	struct sigaltstack32 s32;
197113859Sjhb	struct sigaltstack ss, oss, *ssp;
198100384Speter	int error;
199100384Speter
200113859Sjhb	if (uap->ss != NULL) {
201113859Sjhb		error = copyin(uap->ss, &s32, sizeof(s32));
202100384Speter		if (error)
203100384Speter			return (error);
204113859Sjhb		PTRIN_CP(s32, ss, ss_sp);
205113859Sjhb		CP(s32, ss, ss_size);
206113859Sjhb		CP(s32, ss, ss_flags);
207113859Sjhb		ssp = &ss;
208113859Sjhb	} else
209113859Sjhb		ssp = NULL;
210113859Sjhb	error = kern_sigaltstack(td, ssp, &oss);
211113859Sjhb	if (error == 0 && uap->oss != NULL) {
212113859Sjhb		PTROUT_CP(oss, s32, ss_sp);
213113859Sjhb		CP(oss, s32, ss_size);
214113859Sjhb		CP(oss, s32, ss_flags);
215113859Sjhb		error = copyout(&s32, uap->oss, sizeof(s32));
216100384Speter	}
217100384Speter	return (error);
218100384Speter}
219100384Speter
220142059Sjhb/*
221142059Sjhb * Custom version of exec_copyin_args() so that we can translate
222142059Sjhb * the pointers.
223142059Sjhb */
224142059Sjhbstatic int
225142059Sjhbfreebsd32_exec_copyin_args(struct image_args *args, char *fname,
226142059Sjhb    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
227100384Speter{
228142059Sjhb	char *argp, *envp;
229142059Sjhb	u_int32_t *p32, arg;
230142059Sjhb	size_t length;
231100384Speter	int error;
232100384Speter
233142059Sjhb	bzero(args, sizeof(*args));
234142059Sjhb	if (argv == NULL)
235142059Sjhb		return (EFAULT);
236100384Speter
237142059Sjhb	/*
238142059Sjhb	 * Allocate temporary demand zeroed space for argument and
239142059Sjhb	 *	environment strings
240142059Sjhb	 */
241147588Sjhb	args->buf = (char *) kmem_alloc_wait(exec_map,
242147588Sjhb	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
243142059Sjhb	if (args->buf == NULL)
244142059Sjhb		return (ENOMEM);
245142059Sjhb	args->begin_argv = args->buf;
246142059Sjhb	args->endp = args->begin_argv;
247142059Sjhb	args->stringspace = ARG_MAX;
248142059Sjhb
249142059Sjhb	args->fname = args->buf + ARG_MAX;
250142059Sjhb
251142059Sjhb	/*
252142059Sjhb	 * Copy the file name.
253142059Sjhb	 */
254142059Sjhb	error = (segflg == UIO_SYSSPACE) ?
255142059Sjhb	    copystr(fname, args->fname, PATH_MAX, &length) :
256142059Sjhb	    copyinstr(fname, args->fname, PATH_MAX, &length);
257142059Sjhb	if (error != 0)
258142059Sjhb		return (error);
259142059Sjhb
260142059Sjhb	/*
261142059Sjhb	 * extract arguments first
262142059Sjhb	 */
263142059Sjhb	p32 = argv;
264142059Sjhb	for (;;) {
265142059Sjhb		error = copyin(p32++, &arg, sizeof(arg));
266142059Sjhb		if (error)
267142059Sjhb			return (error);
268142059Sjhb		if (arg == 0)
269142059Sjhb			break;
270142059Sjhb		argp = PTRIN(arg);
271142059Sjhb		error = copyinstr(argp, args->endp, args->stringspace, &length);
272142059Sjhb		if (error) {
273142059Sjhb			if (error == ENAMETOOLONG)
274142059Sjhb				return (E2BIG);
275142059Sjhb			else
276142059Sjhb				return (error);
277142059Sjhb		}
278142059Sjhb		args->stringspace -= length;
279142059Sjhb		args->endp += length;
280142059Sjhb		args->argc++;
281100384Speter	}
282142059Sjhb
283142059Sjhb	args->begin_envv = args->endp;
284142059Sjhb
285142059Sjhb	/*
286142059Sjhb	 * extract environment strings
287142059Sjhb	 */
288142059Sjhb	if (envv) {
289142059Sjhb		p32 = envv;
290142059Sjhb		for (;;) {
291100384Speter			error = copyin(p32++, &arg, sizeof(arg));
292100384Speter			if (error)
293142059Sjhb				return (error);
294142059Sjhb			if (arg == 0)
295142059Sjhb				break;
296142059Sjhb			envp = PTRIN(arg);
297142059Sjhb			error = copyinstr(envp, args->endp, args->stringspace,
298142059Sjhb			    &length);
299142059Sjhb			if (error) {
300142059Sjhb				if (error == ENAMETOOLONG)
301142059Sjhb					return (E2BIG);
302142059Sjhb				else
303142059Sjhb					return (error);
304142059Sjhb			}
305142059Sjhb			args->stringspace -= length;
306142059Sjhb			args->endp += length;
307142059Sjhb			args->envc++;
308142059Sjhb		}
309100384Speter	}
310100384Speter
311142059Sjhb	return (0);
312100384Speter}
313100384Speter
314142059Sjhbint
315142059Sjhbfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
316142059Sjhb{
317142059Sjhb	struct image_args eargs;
318142059Sjhb	int error;
319142059Sjhb
320142059Sjhb	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
321142059Sjhb	    uap->argv, uap->envv);
322142059Sjhb	if (error == 0)
323142059Sjhb		error = kern_execve(td, &eargs, NULL);
324142059Sjhb	exec_free_args(&eargs);
325142059Sjhb	return (error);
326142059Sjhb}
327142059Sjhb
328114987Speter#ifdef __ia64__
329100384Speterstatic int
330119333Speterfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
331119333Speter		       int prot, int fd, off_t pos)
332100384Speter{
333100384Speter	vm_map_t map;
334100384Speter	vm_map_entry_t entry;
335100384Speter	int rv;
336100384Speter
337100384Speter	map = &td->td_proc->p_vmspace->vm_map;
338100384Speter	if (fd != -1)
339100384Speter		prot |= VM_PROT_WRITE;
340100384Speter
341100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
342100384Speter		if ((entry->protection & prot) != prot) {
343100384Speter			rv = vm_map_protect(map,
344100384Speter					    trunc_page(start),
345100384Speter					    round_page(end),
346100384Speter					    entry->protection | prot,
347100384Speter					    FALSE);
348100384Speter			if (rv != KERN_SUCCESS)
349100384Speter				return (EINVAL);
350100384Speter		}
351100384Speter	} else {
352100384Speter		vm_offset_t addr = trunc_page(start);
353100384Speter		rv = vm_map_find(map, 0, 0,
354100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
355100384Speter				 VM_PROT_ALL, 0);
356100384Speter		if (rv != KERN_SUCCESS)
357100384Speter			return (EINVAL);
358100384Speter	}
359100384Speter
360100384Speter	if (fd != -1) {
361100384Speter		struct pread_args r;
362107849Salfred		r.fd = fd;
363107849Salfred		r.buf = (void *) start;
364107849Salfred		r.nbyte = end - start;
365107849Salfred		r.offset = pos;
366100384Speter		return (pread(td, &r));
367100384Speter	} else {
368100384Speter		while (start < end) {
369100384Speter			subyte((void *) start, 0);
370100384Speter			start++;
371100384Speter		}
372100384Speter		return (0);
373100384Speter	}
374100384Speter}
375114987Speter#endif
376100384Speter
377100384Speterint
378119333Speterfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
379100384Speter{
380100384Speter	struct mmap_args ap;
381107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
382107849Salfred	vm_size_t len	 = uap->len;
383107849Salfred	int prot	 = uap->prot;
384107849Salfred	int flags	 = uap->flags;
385107849Salfred	int fd		 = uap->fd;
386107849Salfred	off_t pos	 = (uap->poslo
387107849Salfred			    | ((off_t)uap->poshi << 32));
388114987Speter#ifdef __ia64__
389100384Speter	vm_size_t pageoff;
390100384Speter	int error;
391100384Speter
392100384Speter	/*
393100384Speter	 * Attempt to handle page size hassles.
394100384Speter	 */
395100384Speter	pageoff = (pos & PAGE_MASK);
396100384Speter	if (flags & MAP_FIXED) {
397100384Speter		vm_offset_t start, end;
398100384Speter		start = addr;
399100384Speter		end = addr + len;
400100384Speter
401147964Sjhb		mtx_lock(&Giant);
402100384Speter		if (start != trunc_page(start)) {
403119333Speter			error = freebsd32_mmap_partial(td, start,
404119333Speter						       round_page(start), prot,
405119333Speter						       fd, pos);
406100384Speter			if (fd != -1)
407100384Speter				pos += round_page(start) - start;
408100384Speter			start = round_page(start);
409100384Speter		}
410100384Speter		if (end != round_page(end)) {
411100384Speter			vm_offset_t t = trunc_page(end);
412119333Speter			error = freebsd32_mmap_partial(td, t, end,
413100384Speter						  prot, fd,
414100384Speter						  pos + t - start);
415100384Speter			end = trunc_page(end);
416100384Speter		}
417100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
418100384Speter			/*
419100384Speter			 * We can't map this region at all. The specified
420100384Speter			 * address doesn't have the same alignment as the file
421100384Speter			 * position. Fake the mapping by simply reading the
422100384Speter			 * entire region into memory. First we need to make
423100384Speter			 * sure the region exists.
424100384Speter			 */
425100384Speter			vm_map_t map;
426100384Speter			struct pread_args r;
427100384Speter			int rv;
428100384Speter
429100384Speter			prot |= VM_PROT_WRITE;
430100384Speter			map = &td->td_proc->p_vmspace->vm_map;
431100384Speter			rv = vm_map_remove(map, start, end);
432147964Sjhb			if (rv != KERN_SUCCESS) {
433147964Sjhb				mtx_unlock(&Giant);
434100384Speter				return (EINVAL);
435147964Sjhb			}
436100384Speter			rv = vm_map_find(map, 0, 0,
437100384Speter					 &start, end - start, FALSE,
438100384Speter					 prot, VM_PROT_ALL, 0);
439147964Sjhb			mtx_unlock(&Giant);
440100384Speter			if (rv != KERN_SUCCESS)
441100384Speter				return (EINVAL);
442107849Salfred			r.fd = fd;
443107849Salfred			r.buf = (void *) start;
444107849Salfred			r.nbyte = end - start;
445107849Salfred			r.offset = pos;
446100384Speter			error = pread(td, &r);
447100384Speter			if (error)
448100384Speter				return (error);
449100384Speter
450100384Speter			td->td_retval[0] = addr;
451100384Speter			return (0);
452100384Speter		}
453147964Sjhb		mtx_unlock(&Giant);
454100384Speter		if (end == start) {
455100384Speter			/*
456100384Speter			 * After dealing with the ragged ends, there
457100384Speter			 * might be none left.
458100384Speter			 */
459100384Speter			td->td_retval[0] = addr;
460100384Speter			return (0);
461100384Speter		}
462100384Speter		addr = start;
463100384Speter		len = end - start;
464100384Speter	}
465114987Speter#endif
466100384Speter
467107849Salfred	ap.addr = (void *) addr;
468107849Salfred	ap.len = len;
469107849Salfred	ap.prot = prot;
470107849Salfred	ap.flags = flags;
471107849Salfred	ap.fd = fd;
472107849Salfred	ap.pos = pos;
473100384Speter
474100384Speter	return (mmap(td, &ap));
475100384Speter}
476100384Speter
477100384Speterstruct itimerval32 {
478100384Speter	struct timeval32 it_interval;
479100384Speter	struct timeval32 it_value;
480100384Speter};
481100384Speter
482121719SpeterCTASSERT(sizeof(struct itimerval32) == 16);
483121719Speter
484100384Speterint
485119333Speterfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
486100384Speter{
487142059Sjhb	struct itimerval itv, oitv, *itvp;
488142059Sjhb	struct itimerval32 i32;
489100384Speter	int error;
490100384Speter
491142059Sjhb	if (uap->itv != NULL) {
492142059Sjhb		error = copyin(uap->itv, &i32, sizeof(i32));
493100384Speter		if (error)
494100384Speter			return (error);
495142059Sjhb		TV_CP(i32, itv, it_interval);
496142059Sjhb		TV_CP(i32, itv, it_value);
497142059Sjhb		itvp = &itv;
498142059Sjhb	} else
499142059Sjhb		itvp = NULL;
500142059Sjhb	error = kern_setitimer(td, uap->which, itvp, &oitv);
501142059Sjhb	if (error || uap->oitv == NULL)
502100384Speter		return (error);
503142059Sjhb	TV_CP(oitv, i32, it_interval);
504142059Sjhb	TV_CP(oitv, i32, it_value);
505142059Sjhb	return (copyout(&i32, uap->oitv, sizeof(i32)));
506100384Speter}
507100384Speter
508100384Speterint
509125171Speterfreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
510125171Speter{
511142059Sjhb	struct itimerval itv;
512142059Sjhb	struct itimerval32 i32;
513125171Speter	int error;
514125171Speter
515142059Sjhb	error = kern_getitimer(td, uap->which, &itv);
516142059Sjhb	if (error || uap->itv == NULL)
517125171Speter		return (error);
518142059Sjhb	TV_CP(itv, i32, it_interval);
519142059Sjhb	TV_CP(itv, i32, it_value);
520142059Sjhb	return (copyout(&i32, uap->itv, sizeof(i32)));
521125171Speter}
522125171Speter
523125171Speterint
524119333Speterfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
525100384Speter{
526142059Sjhb	struct timeval32 tv32;
527142059Sjhb	struct timeval tv, *tvp;
528100384Speter	int error;
529100384Speter
530142059Sjhb	if (uap->tv != NULL) {
531142059Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
532100384Speter		if (error)
533100384Speter			return (error);
534142059Sjhb		CP(tv32, tv, tv_sec);
535142059Sjhb		CP(tv32, tv, tv_usec);
536142059Sjhb		tvp = &tv;
537142059Sjhb	} else
538142059Sjhb		tvp = NULL;
539100384Speter	/*
540100384Speter	 * XXX big-endian needs to convert the fd_sets too.
541142059Sjhb	 * XXX Do pointers need PTRIN()?
542100384Speter	 */
543142059Sjhb	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
544100384Speter}
545100384Speter
546114987Speterstruct kevent32 {
547114987Speter	u_int32_t	ident;		/* identifier for this event */
548114987Speter	short		filter;		/* filter for event */
549114987Speter	u_short		flags;
550114987Speter	u_int		fflags;
551114987Speter	int32_t		data;
552114987Speter	u_int32_t	udata;		/* opaque user data identifier */
553114987Speter};
554114987Speter
555121719SpeterCTASSERT(sizeof(struct kevent32) == 20);
556146950Spsstatic int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
557146950Spsstatic int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
558121719Speter
559146950Sps/*
560146950Sps * Copy 'count' items into the destination list pointed to by uap->eventlist.
561146950Sps */
562146950Spsstatic int
563146950Spsfreebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
564146950Sps{
565146950Sps	struct freebsd32_kevent_args *uap;
566146950Sps	struct kevent32	ks32[KQ_NEVENTS];
567146950Sps	int i, error = 0;
568146950Sps
569146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
570146950Sps	uap = (struct freebsd32_kevent_args *)arg;
571146950Sps
572146950Sps	for (i = 0; i < count; i++) {
573146950Sps		CP(kevp[i], ks32[i], ident);
574146950Sps		CP(kevp[i], ks32[i], filter);
575146950Sps		CP(kevp[i], ks32[i], flags);
576146950Sps		CP(kevp[i], ks32[i], fflags);
577146950Sps		CP(kevp[i], ks32[i], data);
578146950Sps		PTROUT_CP(kevp[i], ks32[i], udata);
579146950Sps	}
580146950Sps	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
581146950Sps	if (error == 0)
582146950Sps		uap->eventlist += count;
583146950Sps	return (error);
584146950Sps}
585146950Sps
586146950Sps/*
587146950Sps * Copy 'count' items from the list pointed to by uap->changelist.
588146950Sps */
589146950Spsstatic int
590146950Spsfreebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
591146950Sps{
592146950Sps	struct freebsd32_kevent_args *uap;
593146950Sps	struct kevent32	ks32[KQ_NEVENTS];
594146950Sps	int i, error = 0;
595146950Sps
596146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
597146950Sps	uap = (struct freebsd32_kevent_args *)arg;
598146950Sps
599146950Sps	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
600146950Sps	if (error)
601146950Sps		goto done;
602146950Sps	uap->changelist += count;
603146950Sps
604146950Sps	for (i = 0; i < count; i++) {
605146950Sps		CP(ks32[i], kevp[i], ident);
606146950Sps		CP(ks32[i], kevp[i], filter);
607146950Sps		CP(ks32[i], kevp[i], flags);
608146950Sps		CP(ks32[i], kevp[i], fflags);
609146950Sps		CP(ks32[i], kevp[i], data);
610146950Sps		PTRIN_CP(ks32[i], kevp[i], udata);
611146950Sps	}
612146950Spsdone:
613146950Sps	return (error);
614146950Sps}
615146950Sps
616100384Speterint
617119333Speterfreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
618114987Speter{
619114987Speter	struct timespec32 ts32;
620142934Sps	struct timespec ts, *tsp;
621146950Sps	struct kevent_copyops k_ops = { uap,
622146950Sps					freebsd32_kevent_copyout,
623146950Sps					freebsd32_kevent_copyin};
624146950Sps	int error;
625114987Speter
626114987Speter
627114987Speter	if (uap->timeout) {
628114987Speter		error = copyin(uap->timeout, &ts32, sizeof(ts32));
629114987Speter		if (error)
630114987Speter			return (error);
631114987Speter		CP(ts32, ts, tv_sec);
632114987Speter		CP(ts32, ts, tv_nsec);
633142934Sps		tsp = &ts;
634142934Sps	} else
635142934Sps		tsp = NULL;
636146950Sps	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
637146950Sps	    &k_ops, tsp);
638142934Sps	return (error);
639114987Speter}
640114987Speter
641114987Speterint
642119333Speterfreebsd32_gettimeofday(struct thread *td,
643119333Speter		       struct freebsd32_gettimeofday_args *uap)
644100384Speter{
645123425Speter	struct timeval atv;
646123425Speter	struct timeval32 atv32;
647123425Speter	struct timezone rtz;
648123425Speter	int error = 0;
649100384Speter
650123425Speter	if (uap->tp) {
651123425Speter		microtime(&atv);
652123425Speter		CP(atv, atv32, tv_sec);
653123425Speter		CP(atv, atv32, tv_usec);
654123425Speter		error = copyout(&atv32, uap->tp, sizeof (atv32));
655100384Speter	}
656123425Speter	if (error == 0 && uap->tzp != NULL) {
657123425Speter		rtz.tz_minuteswest = tz_minuteswest;
658123425Speter		rtz.tz_dsttime = tz_dsttime;
659123425Speter		error = copyout(&rtz, uap->tzp, sizeof (rtz));
660100384Speter	}
661100384Speter	return (error);
662100384Speter}
663100384Speter
664100384Speterint
665119333Speterfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
666100384Speter{
667136152Sjhb	struct rusage32 s32;
668136152Sjhb	struct rusage s;
669100384Speter	int error;
670100384Speter
671136152Sjhb	error = kern_getrusage(td, uap->who, &s);
672100384Speter	if (error)
673100384Speter		return (error);
674136152Sjhb	if (uap->rusage != NULL) {
675100384Speter		TV_CP(s, s32, ru_utime);
676100384Speter		TV_CP(s, s32, ru_stime);
677100384Speter		CP(s, s32, ru_maxrss);
678100384Speter		CP(s, s32, ru_ixrss);
679100384Speter		CP(s, s32, ru_idrss);
680100384Speter		CP(s, s32, ru_isrss);
681100384Speter		CP(s, s32, ru_minflt);
682100384Speter		CP(s, s32, ru_majflt);
683100384Speter		CP(s, s32, ru_nswap);
684100384Speter		CP(s, s32, ru_inblock);
685100384Speter		CP(s, s32, ru_oublock);
686100384Speter		CP(s, s32, ru_msgsnd);
687100384Speter		CP(s, s32, ru_msgrcv);
688100384Speter		CP(s, s32, ru_nsignals);
689100384Speter		CP(s, s32, ru_nvcsw);
690100384Speter		CP(s, s32, ru_nivcsw);
691136152Sjhb		error = copyout(&s32, uap->rusage, sizeof(s32));
692100384Speter	}
693100384Speter	return (error);
694100384Speter}
695100384Speter
696100384Speterstruct iovec32 {
697100384Speter	u_int32_t iov_base;
698100384Speter	int	iov_len;
699100384Speter};
700100384Speter
701121719SpeterCTASSERT(sizeof(struct iovec32) == 8);
702121719Speter
703144450Sjhbstatic int
704144450Sjhbfreebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
705100384Speter{
706144450Sjhb	struct iovec32 iov32;
707144450Sjhb	struct iovec *iov;
708144450Sjhb	struct uio *uio;
709144450Sjhb	u_int iovlen;
710144450Sjhb	int error, i;
711100384Speter
712144450Sjhb	*uiop = NULL;
713144450Sjhb	if (iovcnt > UIO_MAXIOV)
714100384Speter		return (EINVAL);
715144450Sjhb	iovlen = iovcnt * sizeof(struct iovec);
716144450Sjhb	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
717144450Sjhb	iov = (struct iovec *)(uio + 1);
718144450Sjhb	for (i = 0; i < iovcnt; i++) {
719144450Sjhb		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
720144450Sjhb		if (error) {
721144450Sjhb			free(uio, M_IOV);
722144450Sjhb			return (error);
723144450Sjhb		}
724144450Sjhb		iov[i].iov_base = PTRIN(iov32.iov_base);
725144450Sjhb		iov[i].iov_len = iov32.iov_len;
726100384Speter	}
727144450Sjhb	uio->uio_iov = iov;
728144450Sjhb	uio->uio_iovcnt = iovcnt;
729144450Sjhb	uio->uio_segflg = UIO_USERSPACE;
730144450Sjhb	uio->uio_offset = -1;
731144450Sjhb	uio->uio_resid = 0;
732144450Sjhb	for (i = 0; i < iovcnt; i++) {
733144450Sjhb		if (iov->iov_len > INT_MAX - uio->uio_resid) {
734144450Sjhb			free(uio, M_IOV);
735144450Sjhb			return (EINVAL);
736144450Sjhb		}
737144450Sjhb		uio->uio_resid += iov->iov_len;
738144450Sjhb		iov++;
739144450Sjhb	}
740144450Sjhb	*uiop = uio;
741144450Sjhb	return (0);
742144450Sjhb}
743100384Speter
744144450Sjhbint
745144450Sjhbfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
746144450Sjhb{
747144450Sjhb	struct uio *auio;
748144450Sjhb	int error;
749100384Speter
750144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
751144450Sjhb	if (error)
752144450Sjhb		return (error);
753144450Sjhb	error = kern_readv(td, uap->fd, auio);
754144450Sjhb	free(auio, M_IOV);
755100384Speter	return (error);
756100384Speter}
757100384Speter
758100384Speterint
759119333Speterfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
760100384Speter{
761144450Sjhb	struct uio *auio;
762144450Sjhb	int error;
763100384Speter
764144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
765144450Sjhb	if (error)
766144450Sjhb		return (error);
767144450Sjhb	error = kern_writev(td, uap->fd, auio);
768144450Sjhb	free(auio, M_IOV);
769100384Speter	return (error);
770100384Speter}
771100384Speter
772100384Speterint
773147813Sjhbfreebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
774147813Sjhb{
775147813Sjhb	struct uio *auio;
776147813Sjhb	int error;
777147813Sjhb
778147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
779147813Sjhb	if (error)
780147813Sjhb		return (error);
781147813Sjhb	error = kern_preadv(td, uap->fd, auio, uap->offset);
782147813Sjhb	free(auio, M_IOV);
783147813Sjhb	return (error);
784147813Sjhb}
785147813Sjhb
786147813Sjhbint
787147813Sjhbfreebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
788147813Sjhb{
789147813Sjhb	struct uio *auio;
790147813Sjhb	int error;
791147813Sjhb
792147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
793147813Sjhb	if (error)
794147813Sjhb		return (error);
795147813Sjhb	error = kern_pwritev(td, uap->fd, auio, uap->offset);
796147813Sjhb	free(auio, M_IOV);
797147813Sjhb	return (error);
798147813Sjhb}
799147813Sjhb
800147813Sjhbint
801119333Speterfreebsd32_settimeofday(struct thread *td,
802119333Speter		       struct freebsd32_settimeofday_args *uap)
803100384Speter{
804144450Sjhb	struct timeval32 tv32;
805144450Sjhb	struct timeval tv, *tvp;
806144450Sjhb	struct timezone tz, *tzp;
807100384Speter	int error;
808100384Speter
809144450Sjhb	if (uap->tv) {
810144450Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
811100384Speter		if (error)
812100384Speter			return (error);
813144450Sjhb		CP(tv32, tv, tv_sec);
814144450Sjhb		CP(tv32, tv, tv_usec);
815144450Sjhb		tvp = &tv;
816144450Sjhb	} else
817144450Sjhb		tvp = NULL;
818144450Sjhb	if (uap->tzp) {
819144450Sjhb		error = copyin(uap->tzp, &tz, sizeof(tz));
820100384Speter		if (error)
821100384Speter			return (error);
822144450Sjhb		tzp = &tz;
823144450Sjhb	} else
824144450Sjhb		tzp = NULL;
825144450Sjhb	return (kern_settimeofday(td, tvp, tzp));
826100384Speter}
827100384Speter
828100384Speterint
829119333Speterfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
830100384Speter{
831142059Sjhb	struct timeval32 s32[2];
832142059Sjhb	struct timeval s[2], *sp;
833100384Speter	int error;
834100384Speter
835142059Sjhb	if (uap->tptr != NULL) {
836142059Sjhb		error = copyin(uap->tptr, s32, sizeof(s32));
837100384Speter		if (error)
838100384Speter			return (error);
839100384Speter		CP(s32[0], s[0], tv_sec);
840100384Speter		CP(s32[0], s[0], tv_usec);
841100384Speter		CP(s32[1], s[1], tv_sec);
842100384Speter		CP(s32[1], s[1], tv_usec);
843142059Sjhb		sp = s;
844142059Sjhb	} else
845142059Sjhb		sp = NULL;
846142059Sjhb	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
847100384Speter}
848100384Speter
849100384Speterint
850119333Speterfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
851100384Speter{
852144450Sjhb	struct timeval32 tv32;
853144450Sjhb	struct timeval delta, olddelta, *deltap;
854100384Speter	int error;
855100384Speter
856144450Sjhb	if (uap->delta) {
857144450Sjhb		error = copyin(uap->delta, &tv32, sizeof(tv32));
858100384Speter		if (error)
859100384Speter			return (error);
860144450Sjhb		CP(tv32, delta, tv_sec);
861144450Sjhb		CP(tv32, delta, tv_usec);
862144450Sjhb		deltap = &delta;
863144450Sjhb	} else
864144450Sjhb		deltap = NULL;
865144450Sjhb	error = kern_adjtime(td, deltap, &olddelta);
866144450Sjhb	if (uap->olddelta && error == 0) {
867144450Sjhb		CP(olddelta, tv32, tv_sec);
868144450Sjhb		CP(olddelta, tv32, tv_usec);
869144450Sjhb		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
870100384Speter	}
871100384Speter	return (error);
872100384Speter}
873100384Speter
874128597Smarcel#ifdef COMPAT_FREEBSD4
875100384Speterint
876128260Speterfreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
877100384Speter{
878142059Sjhb	struct statfs32 s32;
879142059Sjhb	struct statfs s;
880100384Speter	int error;
881100384Speter
882142059Sjhb	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
883100384Speter	if (error)
884100384Speter		return (error);
885142059Sjhb	copy_statfs(&s, &s32);
886142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
887100384Speter}
888128597Smarcel#endif
889100384Speter
890128597Smarcel#ifdef COMPAT_FREEBSD4
891100384Speterint
892128260Speterfreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
893100384Speter{
894142059Sjhb	struct statfs32 s32;
895142059Sjhb	struct statfs s;
896100384Speter	int error;
897100384Speter
898142059Sjhb	error = kern_fstatfs(td, uap->fd, &s);
899100384Speter	if (error)
900100384Speter		return (error);
901142059Sjhb	copy_statfs(&s, &s32);
902142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
903100384Speter}
904128597Smarcel#endif
905100384Speter
906128597Smarcel#ifdef COMPAT_FREEBSD4
907100384Speterint
908128260Speterfreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
909128260Speter{
910142059Sjhb	struct statfs32 s32;
911142059Sjhb	struct statfs s;
912142059Sjhb	fhandle_t fh;
913128260Speter	int error;
914128260Speter
915142059Sjhb	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
916142059Sjhb		return (error);
917142059Sjhb	error = kern_fhstatfs(td, fh, &s);
918128260Speter	if (error)
919128260Speter		return (error);
920142059Sjhb	copy_statfs(&s, &s32);
921142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
922128260Speter}
923128597Smarcel#endif
924128260Speter
925128260Speterint
926119333Speterfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
927100384Speter{
928100384Speter	/*
929100384Speter	 * Vector through to semsys if it is loaded.
930100384Speter	 */
931150883Sjhb	return sysent[SYS_semsys].sy_call(td, uap);
932100384Speter}
933100384Speter
934100384Speterint
935119333Speterfreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
936100384Speter{
937100384Speter	/*
938100384Speter	 * Vector through to msgsys if it is loaded.
939100384Speter	 */
940150883Sjhb	return sysent[SYS_msgsys].sy_call(td, uap);
941100384Speter}
942100384Speter
943100384Speterint
944119333Speterfreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
945100384Speter{
946100384Speter	/*
947100384Speter	 * Vector through to shmsys if it is loaded.
948100384Speter	 */
949150883Sjhb	return sysent[SYS_shmsys].sy_call(td, uap);
950100384Speter}
951100384Speter
952100384Speterint
953119333Speterfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
954100384Speter{
955100384Speter	struct pread_args ap;
956100384Speter
957107849Salfred	ap.fd = uap->fd;
958107849Salfred	ap.buf = uap->buf;
959107849Salfred	ap.nbyte = uap->nbyte;
960119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
961100384Speter	return (pread(td, &ap));
962100384Speter}
963100384Speter
964100384Speterint
965119333Speterfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
966100384Speter{
967100384Speter	struct pwrite_args ap;
968100384Speter
969107849Salfred	ap.fd = uap->fd;
970107849Salfred	ap.buf = uap->buf;
971107849Salfred	ap.nbyte = uap->nbyte;
972119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
973100384Speter	return (pwrite(td, &ap));
974100384Speter}
975100384Speter
976100384Speterint
977119333Speterfreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
978100384Speter{
979100384Speter	int error;
980100384Speter	struct lseek_args ap;
981100384Speter	off_t pos;
982100384Speter
983107849Salfred	ap.fd = uap->fd;
984119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
985107849Salfred	ap.whence = uap->whence;
986100384Speter	error = lseek(td, &ap);
987100384Speter	/* Expand the quad return into two parts for eax and edx */
988100384Speter	pos = *(off_t *)(td->td_retval);
989100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
990100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
991100384Speter	return error;
992100384Speter}
993100384Speter
994100384Speterint
995119333Speterfreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
996100384Speter{
997100384Speter	struct truncate_args ap;
998100384Speter
999107849Salfred	ap.path = uap->path;
1000119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1001100384Speter	return (truncate(td, &ap));
1002100384Speter}
1003100384Speter
1004100384Speterint
1005119333Speterfreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1006100384Speter{
1007100384Speter	struct ftruncate_args ap;
1008100384Speter
1009107849Salfred	ap.fd = uap->fd;
1010119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1011100384Speter	return (ftruncate(td, &ap));
1012100384Speter}
1013100384Speter
1014104738Speter#ifdef COMPAT_FREEBSD4
1015100384Speterint
1016119333Speterfreebsd4_freebsd32_sendfile(struct thread *td,
1017119333Speter    struct freebsd4_freebsd32_sendfile_args *uap)
1018104738Speter{
1019104738Speter	struct freebsd4_sendfile_args ap;
1020104738Speter
1021107849Salfred	ap.fd = uap->fd;
1022107849Salfred	ap.s = uap->s;
1023119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1024107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1025107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1026107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1027107849Salfred	ap.flags = uap->flags;
1028104738Speter	return (freebsd4_sendfile(td, &ap));
1029104738Speter}
1030104738Speter#endif
1031104738Speter
1032104738Speterint
1033119333Speterfreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1034100384Speter{
1035100384Speter	struct sendfile_args ap;
1036100384Speter
1037107849Salfred	ap.fd = uap->fd;
1038107849Salfred	ap.s = uap->s;
1039119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1040107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1041107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1042107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1043107849Salfred	ap.flags = uap->flags;
1044100384Speter	return (sendfile(td, &ap));
1045100384Speter}
1046100384Speter
1047100384Speterstruct stat32 {
1048130640Sphk	dev_t	st_dev;
1049100384Speter	ino_t	st_ino;
1050100384Speter	mode_t	st_mode;
1051100384Speter	nlink_t	st_nlink;
1052100384Speter	uid_t	st_uid;
1053100384Speter	gid_t	st_gid;
1054130640Sphk	dev_t	st_rdev;
1055100384Speter	struct timespec32 st_atimespec;
1056100384Speter	struct timespec32 st_mtimespec;
1057100384Speter	struct timespec32 st_ctimespec;
1058100384Speter	off_t	st_size;
1059100384Speter	int64_t	st_blocks;
1060100384Speter	u_int32_t st_blksize;
1061100384Speter	u_int32_t st_flags;
1062100384Speter	u_int32_t st_gen;
1063121719Speter	struct timespec32 st_birthtimespec;
1064121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1065121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1066100384Speter};
1067100384Speter
1068121719Speter
1069121719SpeterCTASSERT(sizeof(struct stat32) == 96);
1070121719Speter
1071100384Speterstatic void
1072100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1073100384Speter{
1074100384Speter	CP(*in, *out, st_dev);
1075100384Speter	CP(*in, *out, st_ino);
1076100384Speter	CP(*in, *out, st_mode);
1077100384Speter	CP(*in, *out, st_nlink);
1078100384Speter	CP(*in, *out, st_uid);
1079100384Speter	CP(*in, *out, st_gid);
1080100384Speter	CP(*in, *out, st_rdev);
1081100384Speter	TS_CP(*in, *out, st_atimespec);
1082100384Speter	TS_CP(*in, *out, st_mtimespec);
1083100384Speter	TS_CP(*in, *out, st_ctimespec);
1084100384Speter	CP(*in, *out, st_size);
1085100384Speter	CP(*in, *out, st_blocks);
1086100384Speter	CP(*in, *out, st_blksize);
1087100384Speter	CP(*in, *out, st_flags);
1088100384Speter	CP(*in, *out, st_gen);
1089100384Speter}
1090100384Speter
1091100384Speterint
1092119333Speterfreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1093100384Speter{
1094123746Speter	struct stat sb;
1095123746Speter	struct stat32 sb32;
1096100384Speter	int error;
1097100384Speter
1098142059Sjhb	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1099100384Speter	if (error)
1100100384Speter		return (error);
1101123746Speter	copy_stat(&sb, &sb32);
1102123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1103100384Speter	return (error);
1104100384Speter}
1105100384Speter
1106100384Speterint
1107119333Speterfreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1108100384Speter{
1109123746Speter	struct stat ub;
1110123746Speter	struct stat32 ub32;
1111100384Speter	int error;
1112100384Speter
1113142059Sjhb	error = kern_fstat(td, uap->fd, &ub);
1114100384Speter	if (error)
1115100384Speter		return (error);
1116123746Speter	copy_stat(&ub, &ub32);
1117123746Speter	error = copyout(&ub32, uap->ub, sizeof(ub32));
1118100384Speter	return (error);
1119100384Speter}
1120100384Speter
1121100384Speterint
1122119333Speterfreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1123100384Speter{
1124123746Speter	struct stat sb;
1125123746Speter	struct stat32 sb32;
1126142059Sjhb	int error;
1127100384Speter
1128142059Sjhb	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1129100384Speter	if (error)
1130100384Speter		return (error);
1131123746Speter	copy_stat(&sb, &sb32);
1132123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1133100384Speter	return (error);
1134100384Speter}
1135100384Speter
1136100384Speter/*
1137100384Speter * MPSAFE
1138100384Speter */
1139100384Speterint
1140119333Speterfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1141100384Speter{
1142100384Speter	int error, name[CTL_MAXNAME];
1143100384Speter	size_t j, oldlen;
1144100384Speter
1145100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1146100384Speter		return (EINVAL);
1147136404Speter 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1148100384Speter 	if (error)
1149100384Speter		return (error);
1150100384Speter	mtx_lock(&Giant);
1151100384Speter	if (uap->oldlenp)
1152100384Speter		oldlen = fuword32(uap->oldlenp);
1153100384Speter	else
1154100384Speter		oldlen = 0;
1155100384Speter	error = userland_sysctl(td, name, uap->namelen,
1156100384Speter		uap->old, &oldlen, 1,
1157136404Speter		uap->new, uap->newlen, &j, SCTL_MASK32);
1158100384Speter	if (error && error != ENOMEM)
1159100384Speter		goto done2;
1160136404Speter	if (uap->oldlenp)
1161100384Speter		suword32(uap->oldlenp, j);
1162100384Speterdone2:
1163100384Speter	mtx_unlock(&Giant);
1164100384Speter	return (error);
1165100384Speter}
1166100384Speter
1167100384Speterstruct sigaction32 {
1168100384Speter	u_int32_t	sa_u;
1169100384Speter	int		sa_flags;
1170100384Speter	sigset_t	sa_mask;
1171100384Speter};
1172100384Speter
1173121719SpeterCTASSERT(sizeof(struct sigaction32) == 24);
1174121719Speter
1175100384Speterint
1176119333Speterfreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1177100384Speter{
1178113859Sjhb	struct sigaction32 s32;
1179113859Sjhb	struct sigaction sa, osa, *sap;
1180100384Speter	int error;
1181100384Speter
1182113859Sjhb	if (uap->act) {
1183113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
1184100384Speter		if (error)
1185100384Speter			return (error);
1186113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
1187113859Sjhb		CP(s32, sa, sa_flags);
1188113859Sjhb		CP(s32, sa, sa_mask);
1189113859Sjhb		sap = &sa;
1190113859Sjhb	} else
1191113859Sjhb		sap = NULL;
1192113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1193146583Sps	if (error == 0 && uap->oact != NULL) {
1194113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
1195113859Sjhb		CP(osa, s32, sa_flags);
1196113859Sjhb		CP(osa, s32, sa_mask);
1197113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
1198100384Speter	}
1199100384Speter	return (error);
1200100384Speter}
1201100384Speter
1202114987Speter#ifdef COMPAT_FREEBSD4
1203114987Speterint
1204119333Speterfreebsd4_freebsd32_sigaction(struct thread *td,
1205119333Speter			     struct freebsd4_freebsd32_sigaction_args *uap)
1206114987Speter{
1207114987Speter	struct sigaction32 s32;
1208114987Speter	struct sigaction sa, osa, *sap;
1209114987Speter	int error;
1210114987Speter
1211114987Speter	if (uap->act) {
1212114987Speter		error = copyin(uap->act, &s32, sizeof(s32));
1213114987Speter		if (error)
1214114987Speter			return (error);
1215114987Speter		sa.sa_handler = PTRIN(s32.sa_u);
1216114987Speter		CP(s32, sa, sa_flags);
1217114987Speter		CP(s32, sa, sa_mask);
1218114987Speter		sap = &sa;
1219114987Speter	} else
1220114987Speter		sap = NULL;
1221114987Speter	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1222146583Sps	if (error == 0 && uap->oact != NULL) {
1223114987Speter		s32.sa_u = PTROUT(osa.sa_handler);
1224114987Speter		CP(osa, s32, sa_flags);
1225114987Speter		CP(osa, s32, sa_mask);
1226114987Speter		error = copyout(&s32, uap->oact, sizeof(s32));
1227114987Speter	}
1228114987Speter	return (error);
1229114987Speter}
1230114987Speter#endif
1231114987Speter
1232140481Spsint
1233140481Spsfreebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1234140481Sps{
1235140481Sps	struct timespec32 rmt32, rqt32;
1236140481Sps	struct timespec rmt, rqt;
1237140481Sps	int error;
1238140481Sps
1239140481Sps	error = copyin(uap->rqtp, &rqt32, sizeof(rqt));
1240140481Sps	if (error)
1241140481Sps		return (error);
1242140481Sps
1243140481Sps	CP(rqt32, rqt, tv_sec);
1244140481Sps	CP(rqt32, rqt, tv_nsec);
1245140481Sps
1246140481Sps	if (uap->rmtp &&
1247140481Sps	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1248140481Sps		return (EFAULT);
1249140481Sps	error = kern_nanosleep(td, &rqt, &rmt);
1250140481Sps	if (error && uap->rmtp) {
1251140481Sps		int error2;
1252140481Sps
1253140481Sps		CP(rmt, rmt32, tv_sec);
1254140481Sps		CP(rmt, rmt32, tv_nsec);
1255140481Sps
1256140481Sps		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt));
1257140481Sps		if (error2)
1258140481Sps			error = error2;
1259140481Sps	}
1260140481Sps	return (error);
1261140481Sps}
1262140481Sps
1263100384Speter#if 0
1264100384Speter
1265100384Speterint
1266119333Speterfreebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1267100384Speter{
1268100384Speter	int error;
1269100384Speter	struct yyy32 *p32, s32;
1270100384Speter	struct yyy *p = NULL, s;
1271100384Speter
1272147654Sjhb	if (uap->zzz) {
1273147654Sjhb		error = copyin(uap->zzz, &s32, sizeof(s32));
1274100384Speter		if (error)
1275100384Speter			return (error);
1276100384Speter		/* translate in */
1277147654Sjhb		p = &s;
1278100384Speter	}
1279147654Sjhb	error = kern_xxx(td, p);
1280100384Speter	if (error)
1281100384Speter		return (error);
1282147654Sjhb	if (uap->zzz) {
1283100384Speter		/* translate out */
1284100384Speter		error = copyout(&s32, p32, sizeof(s32));
1285100384Speter	}
1286100384Speter	return (error);
1287100384Speter}
1288100384Speter
1289100384Speter#endif
1290