freebsd32_misc.c revision 113859
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 * $FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 113859 2003-04-22 18:23:49Z jhb $
27100384Speter */
28100384Speter
29104738Speter#include "opt_compat.h"
30104738Speter
31100384Speter#include <sys/param.h>
32100384Speter#include <sys/systm.h>
33100384Speter#include <sys/bus.h>
34100384Speter#include <sys/exec.h>
35100384Speter#include <sys/fcntl.h>
36100384Speter#include <sys/filedesc.h>
37100384Speter#include <sys/imgact.h>
38100384Speter#include <sys/kernel.h>
39100384Speter#include <sys/lock.h>
40100384Speter#include <sys/malloc.h>
41100384Speter#include <sys/file.h>		/* Must come after sys/malloc.h */
42100384Speter#include <sys/mman.h>
43100384Speter#include <sys/module.h>
44100384Speter#include <sys/mount.h>
45100384Speter#include <sys/mutex.h>
46100384Speter#include <sys/namei.h>
47100384Speter#include <sys/param.h>
48100384Speter#include <sys/proc.h>
49100384Speter#include <sys/reboot.h>
50100384Speter#include <sys/resource.h>
51100384Speter#include <sys/resourcevar.h>
52100384Speter#include <sys/selinfo.h>
53100384Speter#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
54100384Speter#include <sys/signal.h>
55100384Speter#include <sys/signalvar.h>
56100384Speter#include <sys/socket.h>
57100384Speter#include <sys/socketvar.h>
58100384Speter#include <sys/stat.h>
59113859Sjhb#include <sys/syscallsubr.h>
60100384Speter#include <sys/sysctl.h>
61100384Speter#include <sys/sysent.h>
62100384Speter#include <sys/sysproto.h>
63100384Speter#include <sys/systm.h>
64100384Speter#include <sys/unistd.h>
65100384Speter#include <sys/user.h>
66100384Speter#include <sys/utsname.h>
67100384Speter#include <sys/vnode.h>
68100384Speter
69100384Speter#include <vm/vm.h>
70100384Speter#include <vm/vm_kern.h>
71100384Speter#include <vm/vm_param.h>
72100384Speter#include <vm/pmap.h>
73100384Speter#include <vm/vm_map.h>
74100384Speter#include <vm/vm_object.h>
75100384Speter#include <vm/vm_extern.h>
76100384Speter
77100384Speter#include <ia64/ia32/ia32_util.h>
78100384Speter#include <ia64/ia32/ia32.h>
79100384Speter#include <ia64/ia32/ia32_proto.h>
80100384Speter
81100384Speterstatic const char ia32_emul_path[] = "/compat/ia32";
82100384Speter/*
83100384Speter * [ taken from the linux emulator ]
84100384Speter * Search an alternate path before passing pathname arguments on
85100384Speter * to system calls. Useful for keeping a separate 'emulation tree'.
86100384Speter *
87100384Speter * If cflag is set, we check if an attempt can be made to create
88100384Speter * the named file, i.e. we check if the directory it should
89100384Speter * be in exists.
90100384Speter */
91100384Speterint
92100384Speteria32_emul_find(td, sgp, prefix, path, pbuf, cflag)
93100384Speter	struct thread	*td;
94100384Speter	caddr_t		*sgp;		/* Pointer to stackgap memory */
95100384Speter	const char	*prefix;
96100384Speter	char		*path;
97100384Speter	char		**pbuf;
98100384Speter	int		cflag;
99100384Speter{
100100384Speter	int			error;
101100384Speter	size_t			len, sz;
102100384Speter	char			*buf, *cp, *ptr;
103100384Speter	struct ucred		*ucred;
104100384Speter	struct nameidata	nd;
105100384Speter	struct nameidata	ndroot;
106100384Speter	struct vattr		vat;
107100384Speter	struct vattr		vatroot;
108100384Speter
109111119Simp	buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
110100384Speter	*pbuf = path;
111100384Speter
112100384Speter	for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
113100384Speter		continue;
114100384Speter
115100384Speter	sz = MAXPATHLEN - (ptr - buf);
116100384Speter
117100384Speter	/*
118100384Speter	 * If sgp is not given then the path is already in kernel space
119100384Speter	 */
120100384Speter	if (sgp == NULL)
121100384Speter		error = copystr(path, ptr, sz, &len);
122100384Speter	else
123100384Speter		error = copyinstr(path, ptr, sz, &len);
124100384Speter
125100384Speter	if (error) {
126100384Speter		free(buf, M_TEMP);
127100384Speter		return error;
128100384Speter	}
129100384Speter
130100384Speter	if (*ptr != '/') {
131100384Speter		free(buf, M_TEMP);
132100384Speter		return EINVAL;
133100384Speter	}
134100384Speter
135100384Speter	/*
136100384Speter	 *  We know that there is a / somewhere in this pathname.
137100384Speter	 *  Search backwards for it, to find the file's parent dir
138100384Speter	 *  to see if it exists in the alternate tree. If it does,
139100384Speter	 *  and we want to create a file (cflag is set). We don't
140100384Speter	 *  need to worry about the root comparison in this case.
141100384Speter	 */
142100384Speter
143100384Speter	if (cflag) {
144100384Speter		for (cp = &ptr[len] - 1; *cp != '/'; cp--)
145100384Speter			;
146100384Speter		*cp = '\0';
147100384Speter
148100384Speter		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
149100384Speter
150100384Speter		if ((error = namei(&nd)) != 0) {
151100384Speter			free(buf, M_TEMP);
152100384Speter			return error;
153100384Speter		}
154100384Speter
155100384Speter		*cp = '/';
156100384Speter	} else {
157100384Speter		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
158100384Speter
159100384Speter		if ((error = namei(&nd)) != 0) {
160100384Speter			free(buf, M_TEMP);
161100384Speter			return error;
162100384Speter		}
163100384Speter
164100384Speter		/*
165100384Speter		 * We now compare the vnode of the ia32_root to the one
166100384Speter		 * vnode asked. If they resolve to be the same, then we
167100384Speter		 * ignore the match so that the real root gets used.
168100384Speter		 * This avoids the problem of traversing "../.." to find the
169100384Speter		 * root directory and never finding it, because "/" resolves
170100384Speter		 * to the emulation root directory. This is expensive :-(
171100384Speter		 */
172100384Speter		NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path,
173100384Speter		    td);
174100384Speter
175100384Speter		if ((error = namei(&ndroot)) != 0) {
176100384Speter			/* Cannot happen! */
177100384Speter			free(buf, M_TEMP);
178100384Speter			vrele(nd.ni_vp);
179100384Speter			return error;
180100384Speter		}
181100384Speter
182100384Speter		ucred = td->td_ucred;
183100384Speter		if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
184100384Speter			goto bad;
185100384Speter		}
186100384Speter
187100384Speter		if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
188100384Speter		    td)) != 0) {
189100384Speter			goto bad;
190100384Speter		}
191100384Speter
192100384Speter		if (vat.va_fsid == vatroot.va_fsid &&
193100384Speter		    vat.va_fileid == vatroot.va_fileid) {
194100384Speter			error = ENOENT;
195100384Speter			goto bad;
196100384Speter		}
197100384Speter
198100384Speter	}
199100384Speter	if (sgp == NULL)
200100384Speter		*pbuf = buf;
201100384Speter	else {
202100384Speter		sz = &ptr[len] - buf;
203100384Speter		*pbuf = stackgap_alloc(sgp, sz + 1);
204100384Speter		error = copyout(buf, *pbuf, sz);
205100384Speter		free(buf, M_TEMP);
206100384Speter	}
207100384Speter
208100384Speter	vrele(nd.ni_vp);
209100384Speter	if (!cflag)
210100384Speter		vrele(ndroot.ni_vp);
211100384Speter
212100384Speter	return error;
213100384Speter
214100384Speterbad:
215100384Speter	vrele(ndroot.ni_vp);
216100384Speter	vrele(nd.ni_vp);
217100384Speter	free(buf, M_TEMP);
218100384Speter	return error;
219100384Speter}
220100384Speter
221100384Speterint
222100384Speteria32_open(struct thread *td, struct ia32_open_args *uap)
223100384Speter{
224100384Speter	caddr_t sg;
225100384Speter
226100384Speter	sg = stackgap_init();
227100384Speter	CHECKALTEXIST(td, &sg, uap->path);
228100384Speter
229100384Speter	return open(td, (struct open_args *) uap);
230100384Speter}
231100384Speter
232100384Speterint
233100384Speteria32_wait4(struct thread *td, struct ia32_wait4_args *uap)
234100384Speter{
235100384Speter	int error;
236100384Speter	caddr_t sg;
237100384Speter	struct rusage32 *rusage32, ru32;
238100384Speter	struct rusage *rusage = NULL, ru;
239100384Speter
240107849Salfred	rusage32 = uap->rusage;
241100384Speter	if (rusage32) {
242100384Speter		sg = stackgap_init();
243100384Speter		rusage = stackgap_alloc(&sg, sizeof(struct rusage));
244107849Salfred		uap->rusage = (struct rusage32 *)rusage;
245100384Speter	}
246100384Speter	error = wait4(td, (struct wait_args *)uap);
247100384Speter	if (error)
248100384Speter		return (error);
249100384Speter	if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
250100384Speter		TV_CP(ru, ru32, ru_utime);
251100384Speter		TV_CP(ru, ru32, ru_stime);
252100384Speter		CP(ru, ru32, ru_maxrss);
253100384Speter		CP(ru, ru32, ru_ixrss);
254100384Speter		CP(ru, ru32, ru_idrss);
255100384Speter		CP(ru, ru32, ru_isrss);
256100384Speter		CP(ru, ru32, ru_minflt);
257100384Speter		CP(ru, ru32, ru_majflt);
258100384Speter		CP(ru, ru32, ru_nswap);
259100384Speter		CP(ru, ru32, ru_inblock);
260100384Speter		CP(ru, ru32, ru_oublock);
261100384Speter		CP(ru, ru32, ru_msgsnd);
262100384Speter		CP(ru, ru32, ru_msgrcv);
263100384Speter		CP(ru, ru32, ru_nsignals);
264100384Speter		CP(ru, ru32, ru_nvcsw);
265100384Speter		CP(ru, ru32, ru_nivcsw);
266100384Speter		error = copyout(&ru32, rusage32, sizeof(ru32));
267100384Speter	}
268100384Speter	return (error);
269100384Speter}
270100384Speter
271100384Speterstatic void
272100384Spetercopy_statfs(struct statfs *in, struct statfs32 *out)
273100384Speter{
274100384Speter	CP(*in, *out, f_bsize);
275100384Speter	CP(*in, *out, f_iosize);
276100384Speter	CP(*in, *out, f_blocks);
277100384Speter	CP(*in, *out, f_bfree);
278100384Speter	CP(*in, *out, f_bavail);
279100384Speter	CP(*in, *out, f_files);
280100384Speter	CP(*in, *out, f_ffree);
281100384Speter	CP(*in, *out, f_fsid);
282100384Speter	CP(*in, *out, f_owner);
283100384Speter	CP(*in, *out, f_type);
284100384Speter	CP(*in, *out, f_flags);
285100384Speter	CP(*in, *out, f_flags);
286100384Speter	CP(*in, *out, f_syncwrites);
287100384Speter	CP(*in, *out, f_asyncwrites);
288100384Speter	bcopy(in->f_fstypename,
289100384Speter	      out->f_fstypename, MFSNAMELEN);
290100384Speter	bcopy(in->f_mntonname,
291100384Speter	      out->f_mntonname, MNAMELEN);
292100384Speter	CP(*in, *out, f_syncreads);
293100384Speter	CP(*in, *out, f_asyncreads);
294100384Speter	bcopy(in->f_mntfromname,
295100384Speter	      out->f_mntfromname, MNAMELEN);
296100384Speter}
297100384Speter
298100384Speterint
299100384Speteria32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap)
300100384Speter{
301100384Speter	int error;
302100384Speter	caddr_t sg;
303100384Speter	struct statfs32 *sp32, stat32;
304100384Speter	struct statfs *sp = NULL, stat;
305100384Speter	int maxcount, count, i;
306100384Speter
307107849Salfred	sp32 = uap->buf;
308107849Salfred	maxcount = uap->bufsize / sizeof(struct statfs32);
309100384Speter
310100384Speter	if (sp32) {
311100384Speter		sg = stackgap_init();
312100384Speter		sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
313107849Salfred		uap->buf = (struct statfs32 *)sp;
314100384Speter	}
315100384Speter	error = getfsstat(td, (struct getfsstat_args *) uap);
316100384Speter	if (sp32 && !error) {
317100384Speter		count = td->td_retval[0];
318100384Speter		for (i = 0; i < count; i++) {
319100384Speter			error = copyin(&sp[i], &stat, sizeof(stat));
320100384Speter			if (error)
321100384Speter				return (error);
322100384Speter			copy_statfs(&stat, &stat32);
323100384Speter			error = copyout(&stat32, &sp32[i], sizeof(stat32));
324100384Speter			if (error)
325100384Speter				return (error);
326100384Speter		}
327100384Speter	}
328100384Speter	return (error);
329100384Speter}
330100384Speter
331100384Speterint
332100384Speteria32_access(struct thread *td, struct ia32_access_args *uap)
333100384Speter{
334100384Speter	caddr_t sg;
335100384Speter
336100384Speter	sg = stackgap_init();
337100384Speter	CHECKALTEXIST(td, &sg, uap->path);
338100384Speter
339100384Speter	return access(td, (struct access_args *)uap);
340100384Speter}
341100384Speter
342100384Speterint
343100384Speteria32_chflags(struct thread *td, struct ia32_chflags_args *uap)
344100384Speter{
345100384Speter	caddr_t sg;
346100384Speter
347100384Speter	sg = stackgap_init();
348100384Speter	CHECKALTEXIST(td, &sg, uap->path);
349100384Speter
350100384Speter	return chflags(td, (struct chflags_args *)uap);
351100384Speter}
352100384Speter
353100384Speterstruct sigaltstack32 {
354100384Speter	u_int32_t	ss_sp;
355100384Speter	u_int32_t	ss_size;
356100384Speter	int		ss_flags;
357100384Speter};
358100384Speter
359100384Speterint
360100384Speteria32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap)
361100384Speter{
362113859Sjhb	struct sigaltstack32 s32;
363113859Sjhb	struct sigaltstack ss, oss, *ssp;
364100384Speter	int error;
365100384Speter
366113859Sjhb	if (uap->ss != NULL) {
367113859Sjhb		error = copyin(uap->ss, &s32, sizeof(s32));
368100384Speter		if (error)
369100384Speter			return (error);
370113859Sjhb		PTRIN_CP(s32, ss, ss_sp);
371113859Sjhb		CP(s32, ss, ss_size);
372113859Sjhb		CP(s32, ss, ss_flags);
373113859Sjhb		ssp = &ss;
374113859Sjhb	} else
375113859Sjhb		ssp = NULL;
376113859Sjhb	error = kern_sigaltstack(td, ssp, &oss);
377113859Sjhb	if (error == 0 && uap->oss != NULL) {
378113859Sjhb		PTROUT_CP(oss, s32, ss_sp);
379113859Sjhb		CP(oss, s32, ss_size);
380113859Sjhb		CP(oss, s32, ss_flags);
381113859Sjhb		error = copyout(&s32, uap->oss, sizeof(s32));
382100384Speter	}
383100384Speter	return (error);
384100384Speter}
385100384Speter
386100384Speterint
387100384Speteria32_execve(struct thread *td, struct ia32_execve_args *uap)
388100384Speter{
389100384Speter	int error;
390100384Speter	caddr_t sg;
391100384Speter	struct execve_args ap;
392100384Speter	u_int32_t *p32, arg;
393100384Speter	char **p;
394100384Speter	int count;
395100384Speter
396100384Speter	sg = stackgap_init();
397107849Salfred	CHECKALTEXIST(td, &sg, uap->fname);
398107849Salfred	ap.fname = uap->fname;
399100384Speter
400107849Salfred	if (uap->argv) {
401100384Speter		count = 0;
402107849Salfred		p32 = uap->argv;
403100384Speter		do {
404100384Speter			error = copyin(p32++, &arg, sizeof(arg));
405100384Speter			if (error)
406100384Speter				return error;
407100384Speter			count++;
408100384Speter		} while (arg != 0);
409100384Speter		p = stackgap_alloc(&sg, count * sizeof(char *));
410107849Salfred		ap.argv = p;
411107849Salfred		p32 = uap->argv;
412100384Speter		do {
413100384Speter			error = copyin(p32++, &arg, sizeof(arg));
414100384Speter			if (error)
415100384Speter				return error;
416100384Speter			*p++ = PTRIN(arg);
417100384Speter		} while (arg != 0);
418100384Speter	}
419107849Salfred	if (uap->envv) {
420100384Speter		count = 0;
421107849Salfred		p32 = uap->envv;
422100384Speter		do {
423100384Speter			error = copyin(p32++, &arg, sizeof(arg));
424100384Speter			if (error)
425100384Speter				return error;
426100384Speter			count++;
427100384Speter		} while (arg != 0);
428100384Speter		p = stackgap_alloc(&sg, count * sizeof(char *));
429107849Salfred		ap.envv = p;
430107849Salfred		p32 = uap->envv;
431100384Speter		do {
432100384Speter			error = copyin(p32++, &arg, sizeof(arg));
433100384Speter			if (error)
434100384Speter				return error;
435100384Speter			*p++ = PTRIN(arg);
436100384Speter		} while (arg != 0);
437100384Speter	}
438100384Speter
439100384Speter	return execve(td, &ap);
440100384Speter}
441100384Speter
442100384Speterstatic int
443100384Speteria32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
444100384Speter		  int prot, int fd, off_t pos)
445100384Speter{
446100384Speter	vm_map_t map;
447100384Speter	vm_map_entry_t entry;
448100384Speter	int rv;
449100384Speter
450100384Speter	map = &td->td_proc->p_vmspace->vm_map;
451100384Speter	if (fd != -1)
452100384Speter		prot |= VM_PROT_WRITE;
453100384Speter
454100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
455100384Speter		if ((entry->protection & prot) != prot) {
456100384Speter			rv = vm_map_protect(map,
457100384Speter					    trunc_page(start),
458100384Speter					    round_page(end),
459100384Speter					    entry->protection | prot,
460100384Speter					    FALSE);
461100384Speter			if (rv != KERN_SUCCESS)
462100384Speter				return (EINVAL);
463100384Speter		}
464100384Speter	} else {
465100384Speter		vm_offset_t addr = trunc_page(start);
466100384Speter		rv = vm_map_find(map, 0, 0,
467100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
468100384Speter				 VM_PROT_ALL, 0);
469100384Speter		if (rv != KERN_SUCCESS)
470100384Speter			return (EINVAL);
471100384Speter	}
472100384Speter
473100384Speter	if (fd != -1) {
474100384Speter		struct pread_args r;
475107849Salfred		r.fd = fd;
476107849Salfred		r.buf = (void *) start;
477107849Salfred		r.nbyte = end - start;
478107849Salfred		r.offset = pos;
479100384Speter		return (pread(td, &r));
480100384Speter	} else {
481100384Speter		while (start < end) {
482100384Speter			subyte((void *) start, 0);
483100384Speter			start++;
484100384Speter		}
485100384Speter		return (0);
486100384Speter	}
487100384Speter}
488100384Speter
489100384Speterint
490100384Speteria32_mmap(struct thread *td, struct ia32_mmap_args *uap)
491100384Speter{
492100384Speter	struct mmap_args ap;
493107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
494107849Salfred	vm_size_t len	 = uap->len;
495107849Salfred	int prot	 = uap->prot;
496107849Salfred	int flags	 = uap->flags;
497107849Salfred	int fd		 = uap->fd;
498107849Salfred	off_t pos	 = (uap->poslo
499107849Salfred			    | ((off_t)uap->poshi << 32));
500100384Speter	vm_size_t pageoff;
501100384Speter	int error;
502100384Speter
503100384Speter	/*
504100384Speter	 * Attempt to handle page size hassles.
505100384Speter	 */
506100384Speter	pageoff = (pos & PAGE_MASK);
507100384Speter	if (flags & MAP_FIXED) {
508100384Speter		vm_offset_t start, end;
509100384Speter		start = addr;
510100384Speter		end = addr + len;
511100384Speter
512100384Speter		if (start != trunc_page(start)) {
513100384Speter			error = ia32_mmap_partial(td, start, round_page(start),
514100384Speter						  prot, fd, pos);
515100384Speter			if (fd != -1)
516100384Speter				pos += round_page(start) - start;
517100384Speter			start = round_page(start);
518100384Speter		}
519100384Speter		if (end != round_page(end)) {
520100384Speter			vm_offset_t t = trunc_page(end);
521100384Speter			error = ia32_mmap_partial(td, t, end,
522100384Speter						  prot, fd,
523100384Speter						  pos + t - start);
524100384Speter			end = trunc_page(end);
525100384Speter		}
526100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
527100384Speter			/*
528100384Speter			 * We can't map this region at all. The specified
529100384Speter			 * address doesn't have the same alignment as the file
530100384Speter			 * position. Fake the mapping by simply reading the
531100384Speter			 * entire region into memory. First we need to make
532100384Speter			 * sure the region exists.
533100384Speter			 */
534100384Speter			vm_map_t map;
535100384Speter			struct pread_args r;
536100384Speter			int rv;
537100384Speter
538100384Speter			prot |= VM_PROT_WRITE;
539100384Speter			map = &td->td_proc->p_vmspace->vm_map;
540100384Speter			rv = vm_map_remove(map, start, end);
541100384Speter			if (rv != KERN_SUCCESS)
542100384Speter				return (EINVAL);
543100384Speter			rv = vm_map_find(map, 0, 0,
544100384Speter					 &start, end - start, FALSE,
545100384Speter					 prot, VM_PROT_ALL, 0);
546100384Speter			if (rv != KERN_SUCCESS)
547100384Speter				return (EINVAL);
548107849Salfred			r.fd = fd;
549107849Salfred			r.buf = (void *) start;
550107849Salfred			r.nbyte = end - start;
551107849Salfred			r.offset = pos;
552100384Speter			error = pread(td, &r);
553100384Speter			if (error)
554100384Speter				return (error);
555100384Speter
556100384Speter			td->td_retval[0] = addr;
557100384Speter			return (0);
558100384Speter		}
559100384Speter		if (end == start) {
560100384Speter			/*
561100384Speter			 * After dealing with the ragged ends, there
562100384Speter			 * might be none left.
563100384Speter			 */
564100384Speter			td->td_retval[0] = addr;
565100384Speter			return (0);
566100384Speter		}
567100384Speter		addr = start;
568100384Speter		len = end - start;
569100384Speter	}
570100384Speter
571107849Salfred	ap.addr = (void *) addr;
572107849Salfred	ap.len = len;
573107849Salfred	ap.prot = prot;
574107849Salfred	ap.flags = flags;
575107849Salfred	ap.fd = fd;
576107849Salfred	ap.pos = pos;
577100384Speter
578100384Speter	return (mmap(td, &ap));
579100384Speter}
580100384Speter
581100384Speterstruct itimerval32 {
582100384Speter	struct timeval32 it_interval;
583100384Speter	struct timeval32 it_value;
584100384Speter};
585100384Speter
586100384Speterint
587100384Speteria32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
588100384Speter{
589100384Speter	int error;
590100384Speter	caddr_t sg;
591100384Speter	struct itimerval32 *p32, *op32, s32;
592100384Speter	struct itimerval *p = NULL, *op = NULL, s;
593100384Speter
594107849Salfred	p32 = uap->itv;
595100384Speter	if (p32) {
596100384Speter		sg = stackgap_init();
597100384Speter		p = stackgap_alloc(&sg, sizeof(struct itimerval));
598107849Salfred		uap->itv = (struct itimerval32 *)p;
599100384Speter		error = copyin(p32, &s32, sizeof(s32));
600100384Speter		if (error)
601100384Speter			return (error);
602100384Speter		TV_CP(s32, s, it_interval);
603100384Speter		TV_CP(s32, s, it_value);
604100384Speter		error = copyout(&s, p, sizeof(s));
605100384Speter		if (error)
606100384Speter			return (error);
607100384Speter	}
608107849Salfred	op32 = uap->oitv;
609100384Speter	if (op32) {
610100384Speter		sg = stackgap_init();
611100384Speter		op = stackgap_alloc(&sg, sizeof(struct itimerval));
612107849Salfred		uap->oitv = (struct itimerval32 *)op;
613100384Speter	}
614100384Speter	error = setitimer(td, (struct setitimer_args *) uap);
615100384Speter	if (error)
616100384Speter		return (error);
617100384Speter	if (op32) {
618100384Speter		error = copyin(op, &s, sizeof(s));
619100384Speter		if (error)
620100384Speter			return (error);
621100384Speter		TV_CP(s, s32, it_interval);
622100384Speter		TV_CP(s, s32, it_value);
623100384Speter		error = copyout(&s32, op32, sizeof(s32));
624100384Speter	}
625100384Speter	return (error);
626100384Speter}
627100384Speter
628100384Speterint
629100384Speteria32_select(struct thread *td, struct ia32_select_args *uap)
630100384Speter{
631100384Speter	int error;
632100384Speter	caddr_t sg;
633100384Speter	struct timeval32 *p32, s32;
634100384Speter	struct timeval *p = NULL, s;
635100384Speter
636107849Salfred	p32 = uap->tv;
637100384Speter	if (p32) {
638100384Speter		sg = stackgap_init();
639100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
640107849Salfred		uap->tv = (struct timeval32 *)p;
641100384Speter		error = copyin(p32, &s32, sizeof(s32));
642100384Speter		if (error)
643100384Speter			return (error);
644100384Speter		CP(s32, s, tv_sec);
645100384Speter		CP(s32, s, tv_usec);
646100384Speter		error = copyout(&s, p, sizeof(s));
647100384Speter		if (error)
648100384Speter			return (error);
649100384Speter	}
650100384Speter	/*
651100384Speter	 * XXX big-endian needs to convert the fd_sets too.
652100384Speter	 */
653100384Speter	return (select(td, (struct select_args *) uap));
654100384Speter}
655100384Speter
656100384Speterint
657100384Speteria32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
658100384Speter{
659100384Speter	int error;
660100384Speter	caddr_t sg;
661100384Speter	struct timeval32 *p32, s32;
662100384Speter	struct timeval *p = NULL, s;
663100384Speter
664107849Salfred	p32 = uap->tp;
665100384Speter	if (p32) {
666100384Speter		sg = stackgap_init();
667100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
668107849Salfred		uap->tp = (struct timeval32 *)p;
669100384Speter	}
670100384Speter	error = gettimeofday(td, (struct gettimeofday_args *) uap);
671100384Speter	if (error)
672100384Speter		return (error);
673100384Speter	if (p32) {
674100384Speter		error = copyin(p, &s, sizeof(s));
675100384Speter		if (error)
676100384Speter			return (error);
677100384Speter		CP(s, s32, tv_sec);
678100384Speter		CP(s, s32, tv_usec);
679100384Speter		error = copyout(&s32, p32, sizeof(s32));
680100384Speter		if (error)
681100384Speter			return (error);
682100384Speter	}
683100384Speter	return (error);
684100384Speter}
685100384Speter
686100384Speterint
687100384Speteria32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
688100384Speter{
689100384Speter	int error;
690100384Speter	caddr_t sg;
691100384Speter	struct rusage32 *p32, s32;
692100384Speter	struct rusage *p = NULL, s;
693100384Speter
694107849Salfred	p32 = uap->rusage;
695100384Speter	if (p32) {
696100384Speter		sg = stackgap_init();
697100384Speter		p = stackgap_alloc(&sg, sizeof(struct rusage));
698107849Salfred		uap->rusage = (struct rusage32 *)p;
699100384Speter	}
700100384Speter	error = getrusage(td, (struct getrusage_args *) uap);
701100384Speter	if (error)
702100384Speter		return (error);
703100384Speter	if (p32) {
704100384Speter		error = copyin(p, &s, sizeof(s));
705100384Speter		if (error)
706100384Speter			return (error);
707100384Speter		TV_CP(s, s32, ru_utime);
708100384Speter		TV_CP(s, s32, ru_stime);
709100384Speter		CP(s, s32, ru_maxrss);
710100384Speter		CP(s, s32, ru_ixrss);
711100384Speter		CP(s, s32, ru_idrss);
712100384Speter		CP(s, s32, ru_isrss);
713100384Speter		CP(s, s32, ru_minflt);
714100384Speter		CP(s, s32, ru_majflt);
715100384Speter		CP(s, s32, ru_nswap);
716100384Speter		CP(s, s32, ru_inblock);
717100384Speter		CP(s, s32, ru_oublock);
718100384Speter		CP(s, s32, ru_msgsnd);
719100384Speter		CP(s, s32, ru_msgrcv);
720100384Speter		CP(s, s32, ru_nsignals);
721100384Speter		CP(s, s32, ru_nvcsw);
722100384Speter		CP(s, s32, ru_nivcsw);
723100384Speter		error = copyout(&s32, p32, sizeof(s32));
724100384Speter	}
725100384Speter	return (error);
726100384Speter}
727100384Speter
728100384Speterstruct iovec32 {
729100384Speter	u_int32_t iov_base;
730100384Speter	int	iov_len;
731100384Speter};
732100384Speter#define	STACKGAPLEN	400
733100384Speter
734100384Speterint
735100384Speteria32_readv(struct thread *td, struct ia32_readv_args *uap)
736100384Speter{
737100384Speter	int error, osize, nsize, i;
738100384Speter	caddr_t sg;
739100384Speter	struct readv_args /* {
740100384Speter		syscallarg(int) fd;
741100384Speter		syscallarg(struct iovec *) iovp;
742100384Speter		syscallarg(u_int) iovcnt;
743100384Speter	} */ a;
744100384Speter	struct iovec32 *oio;
745100384Speter	struct iovec *nio;
746100384Speter
747100384Speter	sg = stackgap_init();
748100384Speter
749107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
750100384Speter		return (EINVAL);
751100384Speter
752107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
753107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
754100384Speter
755111119Simp	oio = malloc(osize, M_TEMP, M_WAITOK);
756111119Simp	nio = malloc(nsize, M_TEMP, M_WAITOK);
757100384Speter
758100384Speter	error = 0;
759107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
760100384Speter		goto punt;
761107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
762100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
763100384Speter		nio[i].iov_len = oio[i].iov_len;
764100384Speter	}
765100384Speter
766107849Salfred	a.fd = uap->fd;
767107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
768107849Salfred	a.iovcnt = uap->iovcnt;
769100384Speter
770107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
771100384Speter		goto punt;
772100384Speter	error = readv(td, &a);
773100384Speter
774100384Speterpunt:
775100384Speter	free(oio, M_TEMP);
776100384Speter	free(nio, M_TEMP);
777100384Speter	return (error);
778100384Speter}
779100384Speter
780100384Speterint
781100384Speteria32_writev(struct thread *td, struct ia32_writev_args *uap)
782100384Speter{
783100384Speter	int error, i, nsize, osize;
784100384Speter	caddr_t sg;
785100384Speter	struct writev_args /* {
786100384Speter		syscallarg(int) fd;
787100384Speter		syscallarg(struct iovec *) iovp;
788100384Speter		syscallarg(u_int) iovcnt;
789100384Speter	} */ a;
790100384Speter	struct iovec32 *oio;
791100384Speter	struct iovec *nio;
792100384Speter
793100384Speter	sg = stackgap_init();
794100384Speter
795107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
796100384Speter		return (EINVAL);
797100384Speter
798107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
799107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
800100384Speter
801111119Simp	oio = malloc(osize, M_TEMP, M_WAITOK);
802111119Simp	nio = malloc(nsize, M_TEMP, M_WAITOK);
803100384Speter
804100384Speter	error = 0;
805107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
806100384Speter		goto punt;
807107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
808100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
809100384Speter		nio[i].iov_len = oio[i].iov_len;
810100384Speter	}
811100384Speter
812107849Salfred	a.fd = uap->fd;
813107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
814107849Salfred	a.iovcnt = uap->iovcnt;
815100384Speter
816107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
817100384Speter		goto punt;
818100384Speter	error = writev(td, &a);
819100384Speter
820100384Speterpunt:
821100384Speter	free(oio, M_TEMP);
822100384Speter	free(nio, M_TEMP);
823100384Speter	return (error);
824100384Speter}
825100384Speter
826100384Speterint
827100384Speteria32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
828100384Speter{
829100384Speter	int error;
830100384Speter	caddr_t sg;
831100384Speter	struct timeval32 *p32, s32;
832100384Speter	struct timeval *p = NULL, s;
833100384Speter
834107849Salfred	p32 = uap->tv;
835100384Speter	if (p32) {
836100384Speter		sg = stackgap_init();
837100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
838107849Salfred		uap->tv = (struct timeval32 *)p;
839100384Speter		error = copyin(p32, &s32, sizeof(s32));
840100384Speter		if (error)
841100384Speter			return (error);
842100384Speter		CP(s32, s, tv_sec);
843100384Speter		CP(s32, s, tv_usec);
844100384Speter		error = copyout(&s, p, sizeof(s));
845100384Speter		if (error)
846100384Speter			return (error);
847100384Speter	}
848100384Speter	return (settimeofday(td, (struct settimeofday_args *) uap));
849100384Speter}
850100384Speter
851100384Speterint
852100384Speteria32_utimes(struct thread *td, struct ia32_utimes_args *uap)
853100384Speter{
854100384Speter	int error;
855100384Speter	caddr_t sg;
856100384Speter	struct timeval32 *p32, s32[2];
857100384Speter	struct timeval *p = NULL, s[2];
858100384Speter
859107849Salfred	p32 = uap->tptr;
860100384Speter	if (p32) {
861100384Speter		sg = stackgap_init();
862100384Speter		p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
863107849Salfred		uap->tptr = (struct timeval32 *)p;
864100384Speter		error = copyin(p32, s32, sizeof(s32));
865100384Speter		if (error)
866100384Speter			return (error);
867100384Speter		CP(s32[0], s[0], tv_sec);
868100384Speter		CP(s32[0], s[0], tv_usec);
869100384Speter		CP(s32[1], s[1], tv_sec);
870100384Speter		CP(s32[1], s[1], tv_usec);
871100384Speter		error = copyout(s, p, sizeof(s));
872100384Speter		if (error)
873100384Speter			return (error);
874100384Speter	}
875100384Speter	return (utimes(td, (struct utimes_args *) uap));
876100384Speter}
877100384Speter
878100384Speterint
879100384Speteria32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
880100384Speter{
881100384Speter	int error;
882100384Speter	caddr_t sg;
883100384Speter	struct timeval32 *p32, *op32, s32;
884100384Speter	struct timeval *p = NULL, *op = NULL, s;
885100384Speter
886107849Salfred	p32 = uap->delta;
887100384Speter	if (p32) {
888100384Speter		sg = stackgap_init();
889100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
890107849Salfred		uap->delta = (struct timeval32 *)p;
891100384Speter		error = copyin(p32, &s32, sizeof(s32));
892100384Speter		if (error)
893100384Speter			return (error);
894100384Speter		CP(s32, s, tv_sec);
895100384Speter		CP(s32, s, tv_usec);
896100384Speter		error = copyout(&s, p, sizeof(s));
897100384Speter		if (error)
898100384Speter			return (error);
899100384Speter	}
900107849Salfred	op32 = uap->olddelta;
901100384Speter	if (op32) {
902100384Speter		sg = stackgap_init();
903100384Speter		op = stackgap_alloc(&sg, sizeof(struct timeval));
904107849Salfred		uap->olddelta = (struct timeval32 *)op;
905100384Speter	}
906100384Speter	error = utimes(td, (struct utimes_args *) uap);
907100384Speter	if (error)
908100384Speter		return error;
909100384Speter	if (op32) {
910100384Speter		error = copyin(op, &s, sizeof(s));
911100384Speter		if (error)
912100384Speter			return (error);
913100384Speter		CP(s, s32, tv_sec);
914100384Speter		CP(s, s32, tv_usec);
915100384Speter		error = copyout(&s32, op32, sizeof(s32));
916100384Speter	}
917100384Speter	return (error);
918100384Speter}
919100384Speter
920100384Speterint
921100384Speteria32_statfs(struct thread *td, struct ia32_statfs_args *uap)
922100384Speter{
923100384Speter	int error;
924100384Speter	caddr_t sg;
925100384Speter	struct statfs32 *p32, s32;
926100384Speter	struct statfs *p = NULL, s;
927100384Speter
928107849Salfred	p32 = uap->buf;
929100384Speter	if (p32) {
930100384Speter		sg = stackgap_init();
931100384Speter		p = stackgap_alloc(&sg, sizeof(struct statfs));
932107849Salfred		uap->buf = (struct statfs32 *)p;
933100384Speter	}
934100384Speter	error = statfs(td, (struct statfs_args *) uap);
935100384Speter	if (error)
936100384Speter		return (error);
937100384Speter	if (p32) {
938100384Speter		error = copyin(p, &s, sizeof(s));
939100384Speter		if (error)
940100384Speter			return (error);
941100384Speter		copy_statfs(&s, &s32);
942100384Speter		error = copyout(&s32, p32, sizeof(s32));
943100384Speter	}
944100384Speter	return (error);
945100384Speter}
946100384Speter
947100384Speterint
948100384Speteria32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
949100384Speter{
950100384Speter	int error;
951100384Speter	caddr_t sg;
952100384Speter	struct statfs32 *p32, s32;
953100384Speter	struct statfs *p = NULL, s;
954100384Speter
955107849Salfred	p32 = uap->buf;
956100384Speter	if (p32) {
957100384Speter		sg = stackgap_init();
958100384Speter		p = stackgap_alloc(&sg, sizeof(struct statfs));
959107849Salfred		uap->buf = (struct statfs32 *)p;
960100384Speter	}
961100384Speter	error = fstatfs(td, (struct fstatfs_args *) uap);
962100384Speter	if (error)
963100384Speter		return (error);
964100384Speter	if (p32) {
965100384Speter		error = copyin(p, &s, sizeof(s));
966100384Speter		if (error)
967100384Speter			return (error);
968100384Speter		copy_statfs(&s, &s32);
969100384Speter		error = copyout(&s32, p32, sizeof(s32));
970100384Speter	}
971100384Speter	return (error);
972100384Speter}
973100384Speter
974100384Speterint
975100384Speteria32_semsys(struct thread *td, struct ia32_semsys_args *uap)
976100384Speter{
977100384Speter	/*
978100384Speter	 * Vector through to semsys if it is loaded.
979100384Speter	 */
980100384Speter	return sysent[169].sy_call(td, uap);
981100384Speter}
982100384Speter
983100384Speterint
984100384Speteria32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
985100384Speter{
986100384Speter	/*
987100384Speter	 * Vector through to msgsys if it is loaded.
988100384Speter	 */
989100384Speter	return sysent[170].sy_call(td, uap);
990100384Speter}
991100384Speter
992100384Speterint
993100384Speteria32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
994100384Speter{
995100384Speter	/*
996100384Speter	 * Vector through to shmsys if it is loaded.
997100384Speter	 */
998100384Speter	return sysent[171].sy_call(td, uap);
999100384Speter}
1000100384Speter
1001100384Speterint
1002100384Speteria32_pread(struct thread *td, struct ia32_pread_args *uap)
1003100384Speter{
1004100384Speter	struct pread_args ap;
1005100384Speter
1006107849Salfred	ap.fd = uap->fd;
1007107849Salfred	ap.buf = uap->buf;
1008107849Salfred	ap.nbyte = uap->nbyte;
1009107849Salfred	ap.offset = (uap->offsetlo
1010107849Salfred			      | ((off_t)uap->offsethi << 32));
1011100384Speter	return (pread(td, &ap));
1012100384Speter}
1013100384Speter
1014100384Speterint
1015100384Speteria32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
1016100384Speter{
1017100384Speter	struct pwrite_args ap;
1018100384Speter
1019107849Salfred	ap.fd = uap->fd;
1020107849Salfred	ap.buf = uap->buf;
1021107849Salfred	ap.nbyte = uap->nbyte;
1022107849Salfred	ap.offset = (uap->offsetlo
1023107849Salfred			      | ((off_t)uap->offsethi << 32));
1024100384Speter	return (pwrite(td, &ap));
1025100384Speter}
1026100384Speter
1027100384Speterint
1028100384Speteria32_lseek(struct thread *td, struct ia32_lseek_args *uap)
1029100384Speter{
1030100384Speter	int error;
1031100384Speter	struct lseek_args ap;
1032100384Speter	off_t pos;
1033100384Speter
1034107849Salfred	ap.fd = uap->fd;
1035107849Salfred	ap.offset = (uap->offsetlo
1036107849Salfred			      | ((off_t)uap->offsethi << 32));
1037107849Salfred	ap.whence = uap->whence;
1038100384Speter	error = lseek(td, &ap);
1039100384Speter	/* Expand the quad return into two parts for eax and edx */
1040100384Speter	pos = *(off_t *)(td->td_retval);
1041100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1042100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
1043100384Speter	return error;
1044100384Speter}
1045100384Speter
1046100384Speterint
1047100384Speteria32_truncate(struct thread *td, struct ia32_truncate_args *uap)
1048100384Speter{
1049100384Speter	struct truncate_args ap;
1050100384Speter
1051107849Salfred	ap.path = uap->path;
1052107849Salfred	ap.length = (uap->lengthlo
1053107849Salfred			      | ((off_t)uap->lengthhi << 32));
1054100384Speter	return (truncate(td, &ap));
1055100384Speter}
1056100384Speter
1057100384Speterint
1058100384Speteria32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
1059100384Speter{
1060100384Speter	struct ftruncate_args ap;
1061100384Speter
1062107849Salfred	ap.fd = uap->fd;
1063107849Salfred	ap.length = (uap->lengthlo
1064107849Salfred			      | ((off_t)uap->lengthhi << 32));
1065100384Speter	return (ftruncate(td, &ap));
1066100384Speter}
1067100384Speter
1068104738Speter#ifdef COMPAT_FREEBSD4
1069100384Speterint
1070104738Speterfreebsd4_ia32_sendfile(struct thread *td,
1071104738Speter    struct freebsd4_ia32_sendfile_args *uap)
1072104738Speter{
1073104738Speter	struct freebsd4_sendfile_args ap;
1074104738Speter
1075107849Salfred	ap.fd = uap->fd;
1076107849Salfred	ap.s = uap->s;
1077107849Salfred	ap.offset = (uap->offsetlo
1078107849Salfred			      | ((off_t)uap->offsethi << 32));
1079107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1080107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1081107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1082107849Salfred	ap.flags = uap->flags;
1083104738Speter	return (freebsd4_sendfile(td, &ap));
1084104738Speter}
1085104738Speter#endif
1086104738Speter
1087104738Speterint
1088100384Speteria32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
1089100384Speter{
1090100384Speter	struct sendfile_args ap;
1091100384Speter
1092107849Salfred	ap.fd = uap->fd;
1093107849Salfred	ap.s = uap->s;
1094107849Salfred	ap.offset = (uap->offsetlo
1095107849Salfred			      | ((off_t)uap->offsethi << 32));
1096107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1097107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1098107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1099107849Salfred	ap.flags = uap->flags;
1100100384Speter	return (sendfile(td, &ap));
1101100384Speter}
1102100384Speter
1103100384Speterstruct stat32 {
1104100384Speter	udev_t	st_dev;
1105100384Speter	ino_t	st_ino;
1106100384Speter	mode_t	st_mode;
1107100384Speter	nlink_t	st_nlink;
1108100384Speter	uid_t	st_uid;
1109100384Speter	gid_t	st_gid;
1110100384Speter	udev_t	st_rdev;
1111100384Speter	struct timespec32 st_atimespec;
1112100384Speter	struct timespec32 st_mtimespec;
1113100384Speter	struct timespec32 st_ctimespec;
1114100384Speter	off_t	st_size;
1115100384Speter	int64_t	st_blocks;
1116100384Speter	u_int32_t st_blksize;
1117100384Speter	u_int32_t st_flags;
1118100384Speter	u_int32_t st_gen;
1119100384Speter};
1120100384Speter
1121100384Speterstatic void
1122100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1123100384Speter{
1124100384Speter	CP(*in, *out, st_dev);
1125100384Speter	CP(*in, *out, st_ino);
1126100384Speter	CP(*in, *out, st_mode);
1127100384Speter	CP(*in, *out, st_nlink);
1128100384Speter	CP(*in, *out, st_uid);
1129100384Speter	CP(*in, *out, st_gid);
1130100384Speter	CP(*in, *out, st_rdev);
1131100384Speter	TS_CP(*in, *out, st_atimespec);
1132100384Speter	TS_CP(*in, *out, st_mtimespec);
1133100384Speter	TS_CP(*in, *out, st_ctimespec);
1134100384Speter	CP(*in, *out, st_size);
1135100384Speter	CP(*in, *out, st_blocks);
1136100384Speter	CP(*in, *out, st_blksize);
1137100384Speter	CP(*in, *out, st_flags);
1138100384Speter	CP(*in, *out, st_gen);
1139100384Speter}
1140100384Speter
1141100384Speterint
1142100384Speteria32_stat(struct thread *td, struct ia32_stat_args *uap)
1143100384Speter{
1144100384Speter	int error;
1145100384Speter	caddr_t sg;
1146100384Speter	struct stat32 *p32, s32;
1147100384Speter	struct stat *p = NULL, s;
1148100384Speter
1149107849Salfred	p32 = uap->ub;
1150100384Speter	if (p32) {
1151100384Speter		sg = stackgap_init();
1152100384Speter		p = stackgap_alloc(&sg, sizeof(struct stat));
1153107849Salfred		uap->ub = (struct stat32 *)p;
1154100384Speter	}
1155100384Speter	error = stat(td, (struct stat_args *) uap);
1156100384Speter	if (error)
1157100384Speter		return (error);
1158100384Speter	if (p32) {
1159100384Speter		error = copyin(p, &s, sizeof(s));
1160100384Speter		if (error)
1161100384Speter			return (error);
1162100384Speter		copy_stat(&s, &s32);
1163100384Speter		error = copyout(&s32, p32, sizeof(s32));
1164100384Speter	}
1165100384Speter	return (error);
1166100384Speter}
1167100384Speter
1168100384Speterint
1169100384Speteria32_fstat(struct thread *td, struct ia32_fstat_args *uap)
1170100384Speter{
1171100384Speter	int error;
1172100384Speter	caddr_t sg;
1173100384Speter	struct stat32 *p32, s32;
1174100384Speter	struct stat *p = NULL, s;
1175100384Speter
1176107849Salfred	p32 = uap->ub;
1177100384Speter	if (p32) {
1178100384Speter		sg = stackgap_init();
1179100384Speter		p = stackgap_alloc(&sg, sizeof(struct stat));
1180107849Salfred		uap->ub = (struct stat32 *)p;
1181100384Speter	}
1182100384Speter	error = fstat(td, (struct fstat_args *) uap);
1183100384Speter	if (error)
1184100384Speter		return (error);
1185100384Speter	if (p32) {
1186100384Speter		error = copyin(p, &s, sizeof(s));
1187100384Speter		if (error)
1188100384Speter			return (error);
1189100384Speter		copy_stat(&s, &s32);
1190100384Speter		error = copyout(&s32, p32, sizeof(s32));
1191100384Speter	}
1192100384Speter	return (error);
1193100384Speter}
1194100384Speter
1195100384Speterint
1196100384Speteria32_lstat(struct thread *td, struct ia32_lstat_args *uap)
1197100384Speter{
1198100384Speter	int error;
1199100384Speter	caddr_t sg;
1200100384Speter	struct stat32 *p32, s32;
1201100384Speter	struct stat *p = NULL, s;
1202100384Speter
1203107849Salfred	p32 = uap->ub;
1204100384Speter	if (p32) {
1205100384Speter		sg = stackgap_init();
1206100384Speter		p = stackgap_alloc(&sg, sizeof(struct stat));
1207107849Salfred		uap->ub = (struct stat32 *)p;
1208100384Speter	}
1209100384Speter	error = lstat(td, (struct lstat_args *) uap);
1210100384Speter	if (error)
1211100384Speter		return (error);
1212100384Speter	if (p32) {
1213100384Speter		error = copyin(p, &s, sizeof(s));
1214100384Speter		if (error)
1215100384Speter			return (error);
1216100384Speter		copy_stat(&s, &s32);
1217100384Speter		error = copyout(&s32, p32, sizeof(s32));
1218100384Speter	}
1219100384Speter	return (error);
1220100384Speter}
1221100384Speter
1222100384Speter/*
1223100384Speter * MPSAFE
1224100384Speter */
1225100384Speterint
1226100384Speteria32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
1227100384Speter{
1228100384Speter	int error, name[CTL_MAXNAME];
1229100384Speter	size_t j, oldlen;
1230100384Speter
1231100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1232100384Speter		return (EINVAL);
1233100384Speter
1234100384Speter 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1235100384Speter 	if (error)
1236100384Speter		return (error);
1237100384Speter
1238100384Speter	mtx_lock(&Giant);
1239100384Speter
1240100384Speter	if (uap->oldlenp)
1241100384Speter		oldlen = fuword32(uap->oldlenp);
1242100384Speter	else
1243100384Speter		oldlen = 0;
1244100384Speter	error = userland_sysctl(td, name, uap->namelen,
1245100384Speter		uap->old, &oldlen, 1,
1246100384Speter		uap->new, uap->newlen, &j);
1247100384Speter	if (error && error != ENOMEM)
1248100384Speter		goto done2;
1249100384Speter	if (uap->oldlenp) {
1250100384Speter		suword32(uap->oldlenp, j);
1251100384Speter	}
1252100384Speterdone2:
1253100384Speter	mtx_unlock(&Giant);
1254100384Speter	return (error);
1255100384Speter}
1256100384Speter
1257100384Speterstruct sigaction32 {
1258100384Speter	u_int32_t	sa_u;
1259100384Speter	int		sa_flags;
1260100384Speter	sigset_t	sa_mask;
1261100384Speter};
1262100384Speter
1263100384Speterint
1264100384Speteria32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
1265100384Speter{
1266113859Sjhb	struct sigaction32 s32;
1267113859Sjhb	struct sigaction sa, osa, *sap;
1268100384Speter	int error;
1269100384Speter
1270113859Sjhb	if (uap->act) {
1271113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
1272100384Speter		if (error)
1273100384Speter			return (error);
1274113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
1275113859Sjhb		CP(s32, sa, sa_flags);
1276113859Sjhb		CP(s32, sa, sa_mask);
1277113859Sjhb		sap = &sa;
1278113859Sjhb	} else
1279113859Sjhb		sap = NULL;
1280113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1281113859Sjhb	if (error != 0 && uap->oact != NULL) {
1282113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
1283113859Sjhb		CP(osa, s32, sa_flags);
1284113859Sjhb		CP(osa, s32, sa_mask);
1285113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
1286100384Speter	}
1287100384Speter	return (error);
1288100384Speter}
1289100384Speter
1290100384Speter#if 0
1291100384Speter
1292100384Speterint
1293100384Speteria32_xxx(struct thread *td, struct ia32_xxx_args *uap)
1294100384Speter{
1295100384Speter	int error;
1296100384Speter	caddr_t sg;
1297100384Speter	struct yyy32 *p32, s32;
1298100384Speter	struct yyy *p = NULL, s;
1299100384Speter
1300107849Salfred	p32 = uap->zzz;
1301100384Speter	if (p32) {
1302100384Speter		sg = stackgap_init();
1303100384Speter		p = stackgap_alloc(&sg, sizeof(struct yyy));
1304107849Salfred		uap->zzz = (struct yyy32 *)p;
1305100384Speter		error = copyin(p32, &s32, sizeof(s32));
1306100384Speter		if (error)
1307100384Speter			return (error);
1308100384Speter		/* translate in */
1309100384Speter		error = copyout(&s, p, sizeof(s));
1310100384Speter		if (error)
1311100384Speter			return (error);
1312100384Speter	}
1313100384Speter	error = xxx(td, (struct xxx_args *) uap);
1314100384Speter	if (error)
1315100384Speter		return (error);
1316100384Speter	if (p32) {
1317100384Speter		error = copyin(p, &s, sizeof(s));
1318100384Speter		if (error)
1319100384Speter			return (error);
1320100384Speter		/* translate out */
1321100384Speter		error = copyout(&s32, p32, sizeof(s32));
1322100384Speter	}
1323100384Speter	return (error);
1324100384Speter}
1325100384Speter
1326100384Speter#endif
1327