freebsd32_misc.c revision 107849
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 107849 2002-12-14 01:56:26Z alfred $
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/dkstat.h>
35100384Speter#include <sys/exec.h>
36100384Speter#include <sys/fcntl.h>
37100384Speter#include <sys/filedesc.h>
38100384Speter#include <sys/imgact.h>
39100384Speter#include <sys/kernel.h>
40100384Speter#include <sys/lock.h>
41100384Speter#include <sys/malloc.h>
42100384Speter#include <sys/file.h>		/* Must come after sys/malloc.h */
43100384Speter#include <sys/mman.h>
44100384Speter#include <sys/module.h>
45100384Speter#include <sys/mount.h>
46100384Speter#include <sys/mutex.h>
47100384Speter#include <sys/namei.h>
48100384Speter#include <sys/param.h>
49100384Speter#include <sys/proc.h>
50100384Speter#include <sys/reboot.h>
51100384Speter#include <sys/resource.h>
52100384Speter#include <sys/resourcevar.h>
53100384Speter#include <sys/selinfo.h>
54100384Speter#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
55100384Speter#include <sys/signal.h>
56100384Speter#include <sys/signalvar.h>
57100384Speter#include <sys/socket.h>
58100384Speter#include <sys/socketvar.h>
59100384Speter#include <sys/stat.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
109100384Speter	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{
362100384Speter	int error;
363100384Speter	caddr_t sg;
364100384Speter	struct sigaltstack32 *p32, *op32, s32;
365100384Speter	struct sigaltstack *p = NULL, *op = NULL, s;
366100384Speter
367107849Salfred	p32 = uap->ss;
368100384Speter	if (p32) {
369100384Speter		sg = stackgap_init();
370100384Speter		p = stackgap_alloc(&sg, sizeof(struct sigaltstack));
371107849Salfred		uap->ss = (struct sigaltstack32 *)p;
372100384Speter		error = copyin(p32, &s32, sizeof(s32));
373100384Speter		if (error)
374100384Speter			return (error);
375100384Speter		PTRIN_CP(s32, s, ss_sp);
376100384Speter		CP(s32, s, ss_size);
377100384Speter		CP(s32, s, ss_flags);
378100384Speter		error = copyout(&s, p, sizeof(s));
379100384Speter		if (error)
380100384Speter			return (error);
381100384Speter	}
382107849Salfred	op32 = uap->oss;
383100384Speter	if (op32) {
384100384Speter		sg = stackgap_init();
385100384Speter		op = stackgap_alloc(&sg, sizeof(struct sigaltstack));
386107849Salfred		uap->oss = (struct sigaltstack32 *)op;
387100384Speter	}
388100384Speter	error = sigaltstack(td, (struct sigaltstack_args *) uap);
389100384Speter	if (error)
390100384Speter		return (error);
391100384Speter	if (op32) {
392100384Speter		error = copyin(op, &s, sizeof(s));
393100384Speter		if (error)
394100384Speter			return (error);
395100384Speter		PTROUT_CP(s, s32, ss_sp);
396100384Speter		CP(s, s32, ss_size);
397100384Speter		CP(s, s32, ss_flags);
398100384Speter		error = copyout(&s32, op32, sizeof(s32));
399100384Speter	}
400100384Speter	return (error);
401100384Speter}
402100384Speter
403100384Speterint
404100384Speteria32_execve(struct thread *td, struct ia32_execve_args *uap)
405100384Speter{
406100384Speter	int error;
407100384Speter	caddr_t sg;
408100384Speter	struct execve_args ap;
409100384Speter	u_int32_t *p32, arg;
410100384Speter	char **p;
411100384Speter	int count;
412100384Speter
413100384Speter	sg = stackgap_init();
414107849Salfred	CHECKALTEXIST(td, &sg, uap->fname);
415107849Salfred	ap.fname = uap->fname;
416100384Speter
417107849Salfred	if (uap->argv) {
418100384Speter		count = 0;
419107849Salfred		p32 = uap->argv;
420100384Speter		do {
421100384Speter			error = copyin(p32++, &arg, sizeof(arg));
422100384Speter			if (error)
423100384Speter				return error;
424100384Speter			count++;
425100384Speter		} while (arg != 0);
426100384Speter		p = stackgap_alloc(&sg, count * sizeof(char *));
427107849Salfred		ap.argv = p;
428107849Salfred		p32 = uap->argv;
429100384Speter		do {
430100384Speter			error = copyin(p32++, &arg, sizeof(arg));
431100384Speter			if (error)
432100384Speter				return error;
433100384Speter			*p++ = PTRIN(arg);
434100384Speter		} while (arg != 0);
435100384Speter	}
436107849Salfred	if (uap->envv) {
437100384Speter		count = 0;
438107849Salfred		p32 = uap->envv;
439100384Speter		do {
440100384Speter			error = copyin(p32++, &arg, sizeof(arg));
441100384Speter			if (error)
442100384Speter				return error;
443100384Speter			count++;
444100384Speter		} while (arg != 0);
445100384Speter		p = stackgap_alloc(&sg, count * sizeof(char *));
446107849Salfred		ap.envv = p;
447107849Salfred		p32 = uap->envv;
448100384Speter		do {
449100384Speter			error = copyin(p32++, &arg, sizeof(arg));
450100384Speter			if (error)
451100384Speter				return error;
452100384Speter			*p++ = PTRIN(arg);
453100384Speter		} while (arg != 0);
454100384Speter	}
455100384Speter
456100384Speter	return execve(td, &ap);
457100384Speter}
458100384Speter
459100384Speterstatic int
460100384Speteria32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
461100384Speter		  int prot, int fd, off_t pos)
462100384Speter{
463100384Speter	vm_map_t map;
464100384Speter	vm_map_entry_t entry;
465100384Speter	int rv;
466100384Speter
467100384Speter	map = &td->td_proc->p_vmspace->vm_map;
468100384Speter	if (fd != -1)
469100384Speter		prot |= VM_PROT_WRITE;
470100384Speter
471100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
472100384Speter		if ((entry->protection & prot) != prot) {
473100384Speter			rv = vm_map_protect(map,
474100384Speter					    trunc_page(start),
475100384Speter					    round_page(end),
476100384Speter					    entry->protection | prot,
477100384Speter					    FALSE);
478100384Speter			if (rv != KERN_SUCCESS)
479100384Speter				return (EINVAL);
480100384Speter		}
481100384Speter	} else {
482100384Speter		vm_offset_t addr = trunc_page(start);
483100384Speter		rv = vm_map_find(map, 0, 0,
484100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
485100384Speter				 VM_PROT_ALL, 0);
486100384Speter		if (rv != KERN_SUCCESS)
487100384Speter			return (EINVAL);
488100384Speter	}
489100384Speter
490100384Speter	if (fd != -1) {
491100384Speter		struct pread_args r;
492107849Salfred		r.fd = fd;
493107849Salfred		r.buf = (void *) start;
494107849Salfred		r.nbyte = end - start;
495107849Salfred		r.offset = pos;
496100384Speter		return (pread(td, &r));
497100384Speter	} else {
498100384Speter		while (start < end) {
499100384Speter			subyte((void *) start, 0);
500100384Speter			start++;
501100384Speter		}
502100384Speter		return (0);
503100384Speter	}
504100384Speter}
505100384Speter
506100384Speterint
507100384Speteria32_mmap(struct thread *td, struct ia32_mmap_args *uap)
508100384Speter{
509100384Speter	struct mmap_args ap;
510107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
511107849Salfred	vm_size_t len	 = uap->len;
512107849Salfred	int prot	 = uap->prot;
513107849Salfred	int flags	 = uap->flags;
514107849Salfred	int fd		 = uap->fd;
515107849Salfred	off_t pos	 = (uap->poslo
516107849Salfred			    | ((off_t)uap->poshi << 32));
517100384Speter	vm_size_t pageoff;
518100384Speter	int error;
519100384Speter
520100384Speter	/*
521100384Speter	 * Attempt to handle page size hassles.
522100384Speter	 */
523100384Speter	pageoff = (pos & PAGE_MASK);
524100384Speter	if (flags & MAP_FIXED) {
525100384Speter		vm_offset_t start, end;
526100384Speter		start = addr;
527100384Speter		end = addr + len;
528100384Speter
529100384Speter		if (start != trunc_page(start)) {
530100384Speter			error = ia32_mmap_partial(td, start, round_page(start),
531100384Speter						  prot, fd, pos);
532100384Speter			if (fd != -1)
533100384Speter				pos += round_page(start) - start;
534100384Speter			start = round_page(start);
535100384Speter		}
536100384Speter		if (end != round_page(end)) {
537100384Speter			vm_offset_t t = trunc_page(end);
538100384Speter			error = ia32_mmap_partial(td, t, end,
539100384Speter						  prot, fd,
540100384Speter						  pos + t - start);
541100384Speter			end = trunc_page(end);
542100384Speter		}
543100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
544100384Speter			/*
545100384Speter			 * We can't map this region at all. The specified
546100384Speter			 * address doesn't have the same alignment as the file
547100384Speter			 * position. Fake the mapping by simply reading the
548100384Speter			 * entire region into memory. First we need to make
549100384Speter			 * sure the region exists.
550100384Speter			 */
551100384Speter			vm_map_t map;
552100384Speter			struct pread_args r;
553100384Speter			int rv;
554100384Speter
555100384Speter			prot |= VM_PROT_WRITE;
556100384Speter			map = &td->td_proc->p_vmspace->vm_map;
557100384Speter			rv = vm_map_remove(map, start, end);
558100384Speter			if (rv != KERN_SUCCESS)
559100384Speter				return (EINVAL);
560100384Speter			rv = vm_map_find(map, 0, 0,
561100384Speter					 &start, end - start, FALSE,
562100384Speter					 prot, VM_PROT_ALL, 0);
563100384Speter			if (rv != KERN_SUCCESS)
564100384Speter				return (EINVAL);
565107849Salfred			r.fd = fd;
566107849Salfred			r.buf = (void *) start;
567107849Salfred			r.nbyte = end - start;
568107849Salfred			r.offset = pos;
569100384Speter			error = pread(td, &r);
570100384Speter			if (error)
571100384Speter				return (error);
572100384Speter
573100384Speter			td->td_retval[0] = addr;
574100384Speter			return (0);
575100384Speter		}
576100384Speter		if (end == start) {
577100384Speter			/*
578100384Speter			 * After dealing with the ragged ends, there
579100384Speter			 * might be none left.
580100384Speter			 */
581100384Speter			td->td_retval[0] = addr;
582100384Speter			return (0);
583100384Speter		}
584100384Speter		addr = start;
585100384Speter		len = end - start;
586100384Speter	}
587100384Speter
588107849Salfred	ap.addr = (void *) addr;
589107849Salfred	ap.len = len;
590107849Salfred	ap.prot = prot;
591107849Salfred	ap.flags = flags;
592107849Salfred	ap.fd = fd;
593107849Salfred	ap.pos = pos;
594100384Speter
595100384Speter	return (mmap(td, &ap));
596100384Speter}
597100384Speter
598100384Speterstruct itimerval32 {
599100384Speter	struct timeval32 it_interval;
600100384Speter	struct timeval32 it_value;
601100384Speter};
602100384Speter
603100384Speterint
604100384Speteria32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
605100384Speter{
606100384Speter	int error;
607100384Speter	caddr_t sg;
608100384Speter	struct itimerval32 *p32, *op32, s32;
609100384Speter	struct itimerval *p = NULL, *op = NULL, s;
610100384Speter
611107849Salfred	p32 = uap->itv;
612100384Speter	if (p32) {
613100384Speter		sg = stackgap_init();
614100384Speter		p = stackgap_alloc(&sg, sizeof(struct itimerval));
615107849Salfred		uap->itv = (struct itimerval32 *)p;
616100384Speter		error = copyin(p32, &s32, sizeof(s32));
617100384Speter		if (error)
618100384Speter			return (error);
619100384Speter		TV_CP(s32, s, it_interval);
620100384Speter		TV_CP(s32, s, it_value);
621100384Speter		error = copyout(&s, p, sizeof(s));
622100384Speter		if (error)
623100384Speter			return (error);
624100384Speter	}
625107849Salfred	op32 = uap->oitv;
626100384Speter	if (op32) {
627100384Speter		sg = stackgap_init();
628100384Speter		op = stackgap_alloc(&sg, sizeof(struct itimerval));
629107849Salfred		uap->oitv = (struct itimerval32 *)op;
630100384Speter	}
631100384Speter	error = setitimer(td, (struct setitimer_args *) uap);
632100384Speter	if (error)
633100384Speter		return (error);
634100384Speter	if (op32) {
635100384Speter		error = copyin(op, &s, sizeof(s));
636100384Speter		if (error)
637100384Speter			return (error);
638100384Speter		TV_CP(s, s32, it_interval);
639100384Speter		TV_CP(s, s32, it_value);
640100384Speter		error = copyout(&s32, op32, sizeof(s32));
641100384Speter	}
642100384Speter	return (error);
643100384Speter}
644100384Speter
645100384Speterint
646100384Speteria32_select(struct thread *td, struct ia32_select_args *uap)
647100384Speter{
648100384Speter	int error;
649100384Speter	caddr_t sg;
650100384Speter	struct timeval32 *p32, s32;
651100384Speter	struct timeval *p = NULL, s;
652100384Speter
653107849Salfred	p32 = uap->tv;
654100384Speter	if (p32) {
655100384Speter		sg = stackgap_init();
656100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
657107849Salfred		uap->tv = (struct timeval32 *)p;
658100384Speter		error = copyin(p32, &s32, sizeof(s32));
659100384Speter		if (error)
660100384Speter			return (error);
661100384Speter		CP(s32, s, tv_sec);
662100384Speter		CP(s32, s, tv_usec);
663100384Speter		error = copyout(&s, p, sizeof(s));
664100384Speter		if (error)
665100384Speter			return (error);
666100384Speter	}
667100384Speter	/*
668100384Speter	 * XXX big-endian needs to convert the fd_sets too.
669100384Speter	 */
670100384Speter	return (select(td, (struct select_args *) uap));
671100384Speter}
672100384Speter
673100384Speterint
674100384Speteria32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
675100384Speter{
676100384Speter	int error;
677100384Speter	caddr_t sg;
678100384Speter	struct timeval32 *p32, s32;
679100384Speter	struct timeval *p = NULL, s;
680100384Speter
681107849Salfred	p32 = uap->tp;
682100384Speter	if (p32) {
683100384Speter		sg = stackgap_init();
684100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
685107849Salfred		uap->tp = (struct timeval32 *)p;
686100384Speter	}
687100384Speter	error = gettimeofday(td, (struct gettimeofday_args *) uap);
688100384Speter	if (error)
689100384Speter		return (error);
690100384Speter	if (p32) {
691100384Speter		error = copyin(p, &s, sizeof(s));
692100384Speter		if (error)
693100384Speter			return (error);
694100384Speter		CP(s, s32, tv_sec);
695100384Speter		CP(s, s32, tv_usec);
696100384Speter		error = copyout(&s32, p32, sizeof(s32));
697100384Speter		if (error)
698100384Speter			return (error);
699100384Speter	}
700100384Speter	return (error);
701100384Speter}
702100384Speter
703100384Speterint
704100384Speteria32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
705100384Speter{
706100384Speter	int error;
707100384Speter	caddr_t sg;
708100384Speter	struct rusage32 *p32, s32;
709100384Speter	struct rusage *p = NULL, s;
710100384Speter
711107849Salfred	p32 = uap->rusage;
712100384Speter	if (p32) {
713100384Speter		sg = stackgap_init();
714100384Speter		p = stackgap_alloc(&sg, sizeof(struct rusage));
715107849Salfred		uap->rusage = (struct rusage32 *)p;
716100384Speter	}
717100384Speter	error = getrusage(td, (struct getrusage_args *) uap);
718100384Speter	if (error)
719100384Speter		return (error);
720100384Speter	if (p32) {
721100384Speter		error = copyin(p, &s, sizeof(s));
722100384Speter		if (error)
723100384Speter			return (error);
724100384Speter		TV_CP(s, s32, ru_utime);
725100384Speter		TV_CP(s, s32, ru_stime);
726100384Speter		CP(s, s32, ru_maxrss);
727100384Speter		CP(s, s32, ru_ixrss);
728100384Speter		CP(s, s32, ru_idrss);
729100384Speter		CP(s, s32, ru_isrss);
730100384Speter		CP(s, s32, ru_minflt);
731100384Speter		CP(s, s32, ru_majflt);
732100384Speter		CP(s, s32, ru_nswap);
733100384Speter		CP(s, s32, ru_inblock);
734100384Speter		CP(s, s32, ru_oublock);
735100384Speter		CP(s, s32, ru_msgsnd);
736100384Speter		CP(s, s32, ru_msgrcv);
737100384Speter		CP(s, s32, ru_nsignals);
738100384Speter		CP(s, s32, ru_nvcsw);
739100384Speter		CP(s, s32, ru_nivcsw);
740100384Speter		error = copyout(&s32, p32, sizeof(s32));
741100384Speter	}
742100384Speter	return (error);
743100384Speter}
744100384Speter
745100384Speterstruct iovec32 {
746100384Speter	u_int32_t iov_base;
747100384Speter	int	iov_len;
748100384Speter};
749100384Speter#define	STACKGAPLEN	400
750100384Speter
751100384Speterint
752100384Speteria32_readv(struct thread *td, struct ia32_readv_args *uap)
753100384Speter{
754100384Speter	int error, osize, nsize, i;
755100384Speter	caddr_t sg;
756100384Speter	struct readv_args /* {
757100384Speter		syscallarg(int) fd;
758100384Speter		syscallarg(struct iovec *) iovp;
759100384Speter		syscallarg(u_int) iovcnt;
760100384Speter	} */ a;
761100384Speter	struct iovec32 *oio;
762100384Speter	struct iovec *nio;
763100384Speter
764100384Speter	sg = stackgap_init();
765100384Speter
766107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
767100384Speter		return (EINVAL);
768100384Speter
769107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
770107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
771100384Speter
772100384Speter	oio = malloc(osize, M_TEMP, M_WAITOK);
773100384Speter	nio = malloc(nsize, M_TEMP, M_WAITOK);
774100384Speter
775100384Speter	error = 0;
776107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
777100384Speter		goto punt;
778107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
779100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
780100384Speter		nio[i].iov_len = oio[i].iov_len;
781100384Speter	}
782100384Speter
783107849Salfred	a.fd = uap->fd;
784107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
785107849Salfred	a.iovcnt = uap->iovcnt;
786100384Speter
787107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
788100384Speter		goto punt;
789100384Speter	error = readv(td, &a);
790100384Speter
791100384Speterpunt:
792100384Speter	free(oio, M_TEMP);
793100384Speter	free(nio, M_TEMP);
794100384Speter	return (error);
795100384Speter}
796100384Speter
797100384Speterint
798100384Speteria32_writev(struct thread *td, struct ia32_writev_args *uap)
799100384Speter{
800100384Speter	int error, i, nsize, osize;
801100384Speter	caddr_t sg;
802100384Speter	struct writev_args /* {
803100384Speter		syscallarg(int) fd;
804100384Speter		syscallarg(struct iovec *) iovp;
805100384Speter		syscallarg(u_int) iovcnt;
806100384Speter	} */ a;
807100384Speter	struct iovec32 *oio;
808100384Speter	struct iovec *nio;
809100384Speter
810100384Speter	sg = stackgap_init();
811100384Speter
812107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
813100384Speter		return (EINVAL);
814100384Speter
815107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
816107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
817100384Speter
818100384Speter	oio = malloc(osize, M_TEMP, M_WAITOK);
819100384Speter	nio = malloc(nsize, M_TEMP, M_WAITOK);
820100384Speter
821100384Speter	error = 0;
822107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
823100384Speter		goto punt;
824107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
825100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
826100384Speter		nio[i].iov_len = oio[i].iov_len;
827100384Speter	}
828100384Speter
829107849Salfred	a.fd = uap->fd;
830107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
831107849Salfred	a.iovcnt = uap->iovcnt;
832100384Speter
833107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
834100384Speter		goto punt;
835100384Speter	error = writev(td, &a);
836100384Speter
837100384Speterpunt:
838100384Speter	free(oio, M_TEMP);
839100384Speter	free(nio, M_TEMP);
840100384Speter	return (error);
841100384Speter}
842100384Speter
843100384Speterint
844100384Speteria32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
845100384Speter{
846100384Speter	int error;
847100384Speter	caddr_t sg;
848100384Speter	struct timeval32 *p32, s32;
849100384Speter	struct timeval *p = NULL, s;
850100384Speter
851107849Salfred	p32 = uap->tv;
852100384Speter	if (p32) {
853100384Speter		sg = stackgap_init();
854100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
855107849Salfred		uap->tv = (struct timeval32 *)p;
856100384Speter		error = copyin(p32, &s32, sizeof(s32));
857100384Speter		if (error)
858100384Speter			return (error);
859100384Speter		CP(s32, s, tv_sec);
860100384Speter		CP(s32, s, tv_usec);
861100384Speter		error = copyout(&s, p, sizeof(s));
862100384Speter		if (error)
863100384Speter			return (error);
864100384Speter	}
865100384Speter	return (settimeofday(td, (struct settimeofday_args *) uap));
866100384Speter}
867100384Speter
868100384Speterint
869100384Speteria32_utimes(struct thread *td, struct ia32_utimes_args *uap)
870100384Speter{
871100384Speter	int error;
872100384Speter	caddr_t sg;
873100384Speter	struct timeval32 *p32, s32[2];
874100384Speter	struct timeval *p = NULL, s[2];
875100384Speter
876107849Salfred	p32 = uap->tptr;
877100384Speter	if (p32) {
878100384Speter		sg = stackgap_init();
879100384Speter		p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
880107849Salfred		uap->tptr = (struct timeval32 *)p;
881100384Speter		error = copyin(p32, s32, sizeof(s32));
882100384Speter		if (error)
883100384Speter			return (error);
884100384Speter		CP(s32[0], s[0], tv_sec);
885100384Speter		CP(s32[0], s[0], tv_usec);
886100384Speter		CP(s32[1], s[1], tv_sec);
887100384Speter		CP(s32[1], s[1], tv_usec);
888100384Speter		error = copyout(s, p, sizeof(s));
889100384Speter		if (error)
890100384Speter			return (error);
891100384Speter	}
892100384Speter	return (utimes(td, (struct utimes_args *) uap));
893100384Speter}
894100384Speter
895100384Speterint
896100384Speteria32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
897100384Speter{
898100384Speter	int error;
899100384Speter	caddr_t sg;
900100384Speter	struct timeval32 *p32, *op32, s32;
901100384Speter	struct timeval *p = NULL, *op = NULL, s;
902100384Speter
903107849Salfred	p32 = uap->delta;
904100384Speter	if (p32) {
905100384Speter		sg = stackgap_init();
906100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
907107849Salfred		uap->delta = (struct timeval32 *)p;
908100384Speter		error = copyin(p32, &s32, sizeof(s32));
909100384Speter		if (error)
910100384Speter			return (error);
911100384Speter		CP(s32, s, tv_sec);
912100384Speter		CP(s32, s, tv_usec);
913100384Speter		error = copyout(&s, p, sizeof(s));
914100384Speter		if (error)
915100384Speter			return (error);
916100384Speter	}
917107849Salfred	op32 = uap->olddelta;
918100384Speter	if (op32) {
919100384Speter		sg = stackgap_init();
920100384Speter		op = stackgap_alloc(&sg, sizeof(struct timeval));
921107849Salfred		uap->olddelta = (struct timeval32 *)op;
922100384Speter	}
923100384Speter	error = utimes(td, (struct utimes_args *) uap);
924100384Speter	if (error)
925100384Speter		return error;
926100384Speter	if (op32) {
927100384Speter		error = copyin(op, &s, sizeof(s));
928100384Speter		if (error)
929100384Speter			return (error);
930100384Speter		CP(s, s32, tv_sec);
931100384Speter		CP(s, s32, tv_usec);
932100384Speter		error = copyout(&s32, op32, sizeof(s32));
933100384Speter	}
934100384Speter	return (error);
935100384Speter}
936100384Speter
937100384Speterint
938100384Speteria32_statfs(struct thread *td, struct ia32_statfs_args *uap)
939100384Speter{
940100384Speter	int error;
941100384Speter	caddr_t sg;
942100384Speter	struct statfs32 *p32, s32;
943100384Speter	struct statfs *p = NULL, s;
944100384Speter
945107849Salfred	p32 = uap->buf;
946100384Speter	if (p32) {
947100384Speter		sg = stackgap_init();
948100384Speter		p = stackgap_alloc(&sg, sizeof(struct statfs));
949107849Salfred		uap->buf = (struct statfs32 *)p;
950100384Speter	}
951100384Speter	error = statfs(td, (struct statfs_args *) uap);
952100384Speter	if (error)
953100384Speter		return (error);
954100384Speter	if (p32) {
955100384Speter		error = copyin(p, &s, sizeof(s));
956100384Speter		if (error)
957100384Speter			return (error);
958100384Speter		copy_statfs(&s, &s32);
959100384Speter		error = copyout(&s32, p32, sizeof(s32));
960100384Speter	}
961100384Speter	return (error);
962100384Speter}
963100384Speter
964100384Speterint
965100384Speteria32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
966100384Speter{
967100384Speter	int error;
968100384Speter	caddr_t sg;
969100384Speter	struct statfs32 *p32, s32;
970100384Speter	struct statfs *p = NULL, s;
971100384Speter
972107849Salfred	p32 = uap->buf;
973100384Speter	if (p32) {
974100384Speter		sg = stackgap_init();
975100384Speter		p = stackgap_alloc(&sg, sizeof(struct statfs));
976107849Salfred		uap->buf = (struct statfs32 *)p;
977100384Speter	}
978100384Speter	error = fstatfs(td, (struct fstatfs_args *) uap);
979100384Speter	if (error)
980100384Speter		return (error);
981100384Speter	if (p32) {
982100384Speter		error = copyin(p, &s, sizeof(s));
983100384Speter		if (error)
984100384Speter			return (error);
985100384Speter		copy_statfs(&s, &s32);
986100384Speter		error = copyout(&s32, p32, sizeof(s32));
987100384Speter	}
988100384Speter	return (error);
989100384Speter}
990100384Speter
991100384Speterint
992100384Speteria32_semsys(struct thread *td, struct ia32_semsys_args *uap)
993100384Speter{
994100384Speter	/*
995100384Speter	 * Vector through to semsys if it is loaded.
996100384Speter	 */
997100384Speter	return sysent[169].sy_call(td, uap);
998100384Speter}
999100384Speter
1000100384Speterint
1001100384Speteria32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
1002100384Speter{
1003100384Speter	/*
1004100384Speter	 * Vector through to msgsys if it is loaded.
1005100384Speter	 */
1006100384Speter	return sysent[170].sy_call(td, uap);
1007100384Speter}
1008100384Speter
1009100384Speterint
1010100384Speteria32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
1011100384Speter{
1012100384Speter	/*
1013100384Speter	 * Vector through to shmsys if it is loaded.
1014100384Speter	 */
1015100384Speter	return sysent[171].sy_call(td, uap);
1016100384Speter}
1017100384Speter
1018100384Speterint
1019100384Speteria32_pread(struct thread *td, struct ia32_pread_args *uap)
1020100384Speter{
1021100384Speter	struct pread_args ap;
1022100384Speter
1023107849Salfred	ap.fd = uap->fd;
1024107849Salfred	ap.buf = uap->buf;
1025107849Salfred	ap.nbyte = uap->nbyte;
1026107849Salfred	ap.offset = (uap->offsetlo
1027107849Salfred			      | ((off_t)uap->offsethi << 32));
1028100384Speter	return (pread(td, &ap));
1029100384Speter}
1030100384Speter
1031100384Speterint
1032100384Speteria32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
1033100384Speter{
1034100384Speter	struct pwrite_args ap;
1035100384Speter
1036107849Salfred	ap.fd = uap->fd;
1037107849Salfred	ap.buf = uap->buf;
1038107849Salfred	ap.nbyte = uap->nbyte;
1039107849Salfred	ap.offset = (uap->offsetlo
1040107849Salfred			      | ((off_t)uap->offsethi << 32));
1041100384Speter	return (pwrite(td, &ap));
1042100384Speter}
1043100384Speter
1044100384Speterint
1045100384Speteria32_lseek(struct thread *td, struct ia32_lseek_args *uap)
1046100384Speter{
1047100384Speter	int error;
1048100384Speter	struct lseek_args ap;
1049100384Speter	off_t pos;
1050100384Speter
1051107849Salfred	ap.fd = uap->fd;
1052107849Salfred	ap.offset = (uap->offsetlo
1053107849Salfred			      | ((off_t)uap->offsethi << 32));
1054107849Salfred	ap.whence = uap->whence;
1055100384Speter	error = lseek(td, &ap);
1056100384Speter	/* Expand the quad return into two parts for eax and edx */
1057100384Speter	pos = *(off_t *)(td->td_retval);
1058100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1059100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
1060100384Speter	return error;
1061100384Speter}
1062100384Speter
1063100384Speterint
1064100384Speteria32_truncate(struct thread *td, struct ia32_truncate_args *uap)
1065100384Speter{
1066100384Speter	struct truncate_args ap;
1067100384Speter
1068107849Salfred	ap.path = uap->path;
1069107849Salfred	ap.length = (uap->lengthlo
1070107849Salfred			      | ((off_t)uap->lengthhi << 32));
1071100384Speter	return (truncate(td, &ap));
1072100384Speter}
1073100384Speter
1074100384Speterint
1075100384Speteria32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
1076100384Speter{
1077100384Speter	struct ftruncate_args ap;
1078100384Speter
1079107849Salfred	ap.fd = uap->fd;
1080107849Salfred	ap.length = (uap->lengthlo
1081107849Salfred			      | ((off_t)uap->lengthhi << 32));
1082100384Speter	return (ftruncate(td, &ap));
1083100384Speter}
1084100384Speter
1085104738Speter#ifdef COMPAT_FREEBSD4
1086100384Speterint
1087104738Speterfreebsd4_ia32_sendfile(struct thread *td,
1088104738Speter    struct freebsd4_ia32_sendfile_args *uap)
1089104738Speter{
1090104738Speter	struct freebsd4_sendfile_args ap;
1091104738Speter
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;
1100104738Speter	return (freebsd4_sendfile(td, &ap));
1101104738Speter}
1102104738Speter#endif
1103104738Speter
1104104738Speterint
1105100384Speteria32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
1106100384Speter{
1107100384Speter	struct sendfile_args ap;
1108100384Speter
1109107849Salfred	ap.fd = uap->fd;
1110107849Salfred	ap.s = uap->s;
1111107849Salfred	ap.offset = (uap->offsetlo
1112107849Salfred			      | ((off_t)uap->offsethi << 32));
1113107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1114107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1115107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1116107849Salfred	ap.flags = uap->flags;
1117100384Speter	return (sendfile(td, &ap));
1118100384Speter}
1119100384Speter
1120100384Speterstruct stat32 {
1121100384Speter	udev_t	st_dev;
1122100384Speter	ino_t	st_ino;
1123100384Speter	mode_t	st_mode;
1124100384Speter	nlink_t	st_nlink;
1125100384Speter	uid_t	st_uid;
1126100384Speter	gid_t	st_gid;
1127100384Speter	udev_t	st_rdev;
1128100384Speter	struct timespec32 st_atimespec;
1129100384Speter	struct timespec32 st_mtimespec;
1130100384Speter	struct timespec32 st_ctimespec;
1131100384Speter	off_t	st_size;
1132100384Speter	int64_t	st_blocks;
1133100384Speter	u_int32_t st_blksize;
1134100384Speter	u_int32_t st_flags;
1135100384Speter	u_int32_t st_gen;
1136100384Speter};
1137100384Speter
1138100384Speterstatic void
1139100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1140100384Speter{
1141100384Speter	CP(*in, *out, st_dev);
1142100384Speter	CP(*in, *out, st_ino);
1143100384Speter	CP(*in, *out, st_mode);
1144100384Speter	CP(*in, *out, st_nlink);
1145100384Speter	CP(*in, *out, st_uid);
1146100384Speter	CP(*in, *out, st_gid);
1147100384Speter	CP(*in, *out, st_rdev);
1148100384Speter	TS_CP(*in, *out, st_atimespec);
1149100384Speter	TS_CP(*in, *out, st_mtimespec);
1150100384Speter	TS_CP(*in, *out, st_ctimespec);
1151100384Speter	CP(*in, *out, st_size);
1152100384Speter	CP(*in, *out, st_blocks);
1153100384Speter	CP(*in, *out, st_blksize);
1154100384Speter	CP(*in, *out, st_flags);
1155100384Speter	CP(*in, *out, st_gen);
1156100384Speter}
1157100384Speter
1158100384Speterint
1159100384Speteria32_stat(struct thread *td, struct ia32_stat_args *uap)
1160100384Speter{
1161100384Speter	int error;
1162100384Speter	caddr_t sg;
1163100384Speter	struct stat32 *p32, s32;
1164100384Speter	struct stat *p = NULL, s;
1165100384Speter
1166107849Salfred	p32 = uap->ub;
1167100384Speter	if (p32) {
1168100384Speter		sg = stackgap_init();
1169100384Speter		p = stackgap_alloc(&sg, sizeof(struct stat));
1170107849Salfred		uap->ub = (struct stat32 *)p;
1171100384Speter	}
1172100384Speter	error = stat(td, (struct stat_args *) uap);
1173100384Speter	if (error)
1174100384Speter		return (error);
1175100384Speter	if (p32) {
1176100384Speter		error = copyin(p, &s, sizeof(s));
1177100384Speter		if (error)
1178100384Speter			return (error);
1179100384Speter		copy_stat(&s, &s32);
1180100384Speter		error = copyout(&s32, p32, sizeof(s32));
1181100384Speter	}
1182100384Speter	return (error);
1183100384Speter}
1184100384Speter
1185100384Speterint
1186100384Speteria32_fstat(struct thread *td, struct ia32_fstat_args *uap)
1187100384Speter{
1188100384Speter	int error;
1189100384Speter	caddr_t sg;
1190100384Speter	struct stat32 *p32, s32;
1191100384Speter	struct stat *p = NULL, s;
1192100384Speter
1193107849Salfred	p32 = uap->ub;
1194100384Speter	if (p32) {
1195100384Speter		sg = stackgap_init();
1196100384Speter		p = stackgap_alloc(&sg, sizeof(struct stat));
1197107849Salfred		uap->ub = (struct stat32 *)p;
1198100384Speter	}
1199100384Speter	error = fstat(td, (struct fstat_args *) uap);
1200100384Speter	if (error)
1201100384Speter		return (error);
1202100384Speter	if (p32) {
1203100384Speter		error = copyin(p, &s, sizeof(s));
1204100384Speter		if (error)
1205100384Speter			return (error);
1206100384Speter		copy_stat(&s, &s32);
1207100384Speter		error = copyout(&s32, p32, sizeof(s32));
1208100384Speter	}
1209100384Speter	return (error);
1210100384Speter}
1211100384Speter
1212100384Speterint
1213100384Speteria32_lstat(struct thread *td, struct ia32_lstat_args *uap)
1214100384Speter{
1215100384Speter	int error;
1216100384Speter	caddr_t sg;
1217100384Speter	struct stat32 *p32, s32;
1218100384Speter	struct stat *p = NULL, s;
1219100384Speter
1220107849Salfred	p32 = uap->ub;
1221100384Speter	if (p32) {
1222100384Speter		sg = stackgap_init();
1223100384Speter		p = stackgap_alloc(&sg, sizeof(struct stat));
1224107849Salfred		uap->ub = (struct stat32 *)p;
1225100384Speter	}
1226100384Speter	error = lstat(td, (struct lstat_args *) uap);
1227100384Speter	if (error)
1228100384Speter		return (error);
1229100384Speter	if (p32) {
1230100384Speter		error = copyin(p, &s, sizeof(s));
1231100384Speter		if (error)
1232100384Speter			return (error);
1233100384Speter		copy_stat(&s, &s32);
1234100384Speter		error = copyout(&s32, p32, sizeof(s32));
1235100384Speter	}
1236100384Speter	return (error);
1237100384Speter}
1238100384Speter
1239100384Speter/*
1240100384Speter * MPSAFE
1241100384Speter */
1242100384Speterint
1243100384Speteria32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
1244100384Speter{
1245100384Speter	int error, name[CTL_MAXNAME];
1246100384Speter	size_t j, oldlen;
1247100384Speter
1248100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1249100384Speter		return (EINVAL);
1250100384Speter
1251100384Speter 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1252100384Speter 	if (error)
1253100384Speter		return (error);
1254100384Speter
1255100384Speter	mtx_lock(&Giant);
1256100384Speter
1257100384Speter	if (uap->oldlenp)
1258100384Speter		oldlen = fuword32(uap->oldlenp);
1259100384Speter	else
1260100384Speter		oldlen = 0;
1261100384Speter	error = userland_sysctl(td, name, uap->namelen,
1262100384Speter		uap->old, &oldlen, 1,
1263100384Speter		uap->new, uap->newlen, &j);
1264100384Speter	if (error && error != ENOMEM)
1265100384Speter		goto done2;
1266100384Speter	if (uap->oldlenp) {
1267100384Speter		suword32(uap->oldlenp, j);
1268100384Speter	}
1269100384Speterdone2:
1270100384Speter	mtx_unlock(&Giant);
1271100384Speter	return (error);
1272100384Speter}
1273100384Speter
1274100384Speterstruct sigaction32 {
1275100384Speter	u_int32_t	sa_u;
1276100384Speter	int		sa_flags;
1277100384Speter	sigset_t	sa_mask;
1278100384Speter};
1279100384Speter
1280100384Speterint
1281100384Speteria32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
1282100384Speter{
1283100384Speter	int error;
1284100384Speter	caddr_t sg;
1285100384Speter	struct sigaction32 *p32, *op32, s32;
1286100384Speter	struct sigaction *p = NULL, *op = NULL, s;
1287100384Speter
1288107849Salfred	p32 = uap->act;
1289100384Speter	if (p32) {
1290100384Speter		sg = stackgap_init();
1291100384Speter		p = stackgap_alloc(&sg, sizeof(struct sigaction));
1292107849Salfred		uap->act = (struct sigaction32 *)p;
1293100384Speter		error = copyin(p32, &s32, sizeof(s32));
1294100384Speter		if (error)
1295100384Speter			return (error);
1296100384Speter		s.sa_handler = PTRIN(s32.sa_u);
1297100384Speter		CP(s32, s, sa_flags);
1298100384Speter		CP(s32, s, sa_mask);
1299100384Speter		error = copyout(&s, p, sizeof(s));
1300100384Speter		if (error)
1301100384Speter			return (error);
1302100384Speter	}
1303107849Salfred	op32 = uap->oact;
1304100384Speter	if (op32) {
1305100384Speter		sg = stackgap_init();
1306100384Speter		op = stackgap_alloc(&sg, sizeof(struct sigaction));
1307107849Salfred		uap->oact = (struct sigaction32 *)op;
1308100384Speter	}
1309100384Speter	error = sigaction(td, (struct sigaction_args *) uap);
1310100384Speter	if (error)
1311100384Speter		return (error);
1312100384Speter	if (op32) {
1313100384Speter		error = copyin(op, &s, sizeof(s));
1314100384Speter		if (error)
1315100384Speter			return (error);
1316100384Speter		s32.sa_u = PTROUT(s.sa_handler);
1317100384Speter		CP(s, s32, sa_flags);
1318100384Speter		CP(s, s32, sa_mask);
1319100384Speter		error = copyout(&s32, op32, sizeof(s32));
1320100384Speter	}
1321100384Speter	return (error);
1322100384Speter}
1323100384Speter
1324100384Speter#if 0
1325100384Speter
1326100384Speterint
1327100384Speteria32_xxx(struct thread *td, struct ia32_xxx_args *uap)
1328100384Speter{
1329100384Speter	int error;
1330100384Speter	caddr_t sg;
1331100384Speter	struct yyy32 *p32, s32;
1332100384Speter	struct yyy *p = NULL, s;
1333100384Speter
1334107849Salfred	p32 = uap->zzz;
1335100384Speter	if (p32) {
1336100384Speter		sg = stackgap_init();
1337100384Speter		p = stackgap_alloc(&sg, sizeof(struct yyy));
1338107849Salfred		uap->zzz = (struct yyy32 *)p;
1339100384Speter		error = copyin(p32, &s32, sizeof(s32));
1340100384Speter		if (error)
1341100384Speter			return (error);
1342100384Speter		/* translate in */
1343100384Speter		error = copyout(&s, p, sizeof(s));
1344100384Speter		if (error)
1345100384Speter			return (error);
1346100384Speter	}
1347100384Speter	error = xxx(td, (struct xxx_args *) uap);
1348100384Speter	if (error)
1349100384Speter		return (error);
1350100384Speter	if (p32) {
1351100384Speter		error = copyin(p, &s, sizeof(s));
1352100384Speter		if (error)
1353100384Speter			return (error);
1354100384Speter		/* translate out */
1355100384Speter		error = copyout(&s32, p32, sizeof(s32));
1356100384Speter	}
1357100384Speter	return (error);
1358100384Speter}
1359100384Speter
1360100384Speter#endif
1361