freebsd32_misc.c revision 125171
1100384Speter/*-
2100384Speter * Copyright (c) 2002 Doug Rabson
3100384Speter * All rights reserved.
4100384Speter *
5100384Speter * Redistribution and use in source and binary forms, with or without
6100384Speter * modification, are permitted provided that the following conditions
7100384Speter * are met:
8100384Speter * 1. Redistributions of source code must retain the above copyright
9100384Speter *    notice, this list of conditions and the following disclaimer.
10100384Speter * 2. Redistributions in binary form must reproduce the above copyright
11100384Speter *    notice, this list of conditions and the following disclaimer in the
12100384Speter *    documentation and/or other materials provided with the distribution.
13100384Speter *
14100384Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15100384Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16100384Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17100384Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18100384Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19100384Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20100384Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21100384Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22100384Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23100384Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24100384Speter * SUCH DAMAGE.
25100384Speter */
26100384Speter
27118031Sobrien#include <sys/cdefs.h>
28118031Sobrien__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 125171 2004-01-28 23:45:48Z peter $");
29118031Sobrien
30104738Speter#include "opt_compat.h"
31104738Speter
32100384Speter#include <sys/param.h>
33100384Speter#include <sys/systm.h>
34100384Speter#include <sys/bus.h>
35100384Speter#include <sys/exec.h>
36100384Speter#include <sys/fcntl.h>
37100384Speter#include <sys/filedesc.h>
38123746Speter#include <sys/namei.h>
39100384Speter#include <sys/imgact.h>
40100384Speter#include <sys/kernel.h>
41100384Speter#include <sys/lock.h>
42100384Speter#include <sys/malloc.h>
43100384Speter#include <sys/file.h>		/* Must come after sys/malloc.h */
44100384Speter#include <sys/mman.h>
45100384Speter#include <sys/module.h>
46100384Speter#include <sys/mount.h>
47100384Speter#include <sys/mutex.h>
48100384Speter#include <sys/namei.h>
49100384Speter#include <sys/param.h>
50100384Speter#include <sys/proc.h>
51100384Speter#include <sys/reboot.h>
52100384Speter#include <sys/resource.h>
53100384Speter#include <sys/resourcevar.h>
54100384Speter#include <sys/selinfo.h>
55100384Speter#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
56100384Speter#include <sys/signal.h>
57100384Speter#include <sys/signalvar.h>
58100384Speter#include <sys/socket.h>
59100384Speter#include <sys/socketvar.h>
60100384Speter#include <sys/stat.h>
61113859Sjhb#include <sys/syscallsubr.h>
62100384Speter#include <sys/sysctl.h>
63100384Speter#include <sys/sysent.h>
64100384Speter#include <sys/sysproto.h>
65100384Speter#include <sys/systm.h>
66100384Speter#include <sys/unistd.h>
67100384Speter#include <sys/user.h>
68100384Speter#include <sys/utsname.h>
69100384Speter#include <sys/vnode.h>
70100384Speter
71100384Speter#include <vm/vm.h>
72100384Speter#include <vm/vm_kern.h>
73100384Speter#include <vm/vm_param.h>
74100384Speter#include <vm/pmap.h>
75100384Speter#include <vm/vm_map.h>
76100384Speter#include <vm/vm_object.h>
77100384Speter#include <vm/vm_extern.h>
78100384Speter
79119333Speter#include <compat/freebsd32/freebsd32_util.h>
80119333Speter#include <compat/freebsd32/freebsd32.h>
81119333Speter#include <compat/freebsd32/freebsd32_proto.h>
82100384Speter
83121719SpeterCTASSERT(sizeof(struct timeval32) == 8);
84121719SpeterCTASSERT(sizeof(struct timespec32) == 8);
85121719SpeterCTASSERT(sizeof(struct statfs32) == 256);
86121719SpeterCTASSERT(sizeof(struct rusage32) == 72);
87121719Speter
88100384Speterint
89119333Speterfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
90100384Speter{
91100384Speter	int error;
92100384Speter	caddr_t sg;
93100384Speter	struct rusage32 *rusage32, ru32;
94100384Speter	struct rusage *rusage = NULL, ru;
95100384Speter
96107849Salfred	rusage32 = uap->rusage;
97100384Speter	if (rusage32) {
98100384Speter		sg = stackgap_init();
99100384Speter		rusage = stackgap_alloc(&sg, sizeof(struct rusage));
100107849Salfred		uap->rusage = (struct rusage32 *)rusage;
101100384Speter	}
102100384Speter	error = wait4(td, (struct wait_args *)uap);
103100384Speter	if (error)
104100384Speter		return (error);
105100384Speter	if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
106100384Speter		TV_CP(ru, ru32, ru_utime);
107100384Speter		TV_CP(ru, ru32, ru_stime);
108100384Speter		CP(ru, ru32, ru_maxrss);
109100384Speter		CP(ru, ru32, ru_ixrss);
110100384Speter		CP(ru, ru32, ru_idrss);
111100384Speter		CP(ru, ru32, ru_isrss);
112100384Speter		CP(ru, ru32, ru_minflt);
113100384Speter		CP(ru, ru32, ru_majflt);
114100384Speter		CP(ru, ru32, ru_nswap);
115100384Speter		CP(ru, ru32, ru_inblock);
116100384Speter		CP(ru, ru32, ru_oublock);
117100384Speter		CP(ru, ru32, ru_msgsnd);
118100384Speter		CP(ru, ru32, ru_msgrcv);
119100384Speter		CP(ru, ru32, ru_nsignals);
120100384Speter		CP(ru, ru32, ru_nvcsw);
121100384Speter		CP(ru, ru32, ru_nivcsw);
122100384Speter		error = copyout(&ru32, rusage32, sizeof(ru32));
123100384Speter	}
124100384Speter	return (error);
125100384Speter}
126100384Speter
127100384Speterstatic void
128100384Spetercopy_statfs(struct statfs *in, struct statfs32 *out)
129100384Speter{
130100384Speter	CP(*in, *out, f_bsize);
131100384Speter	CP(*in, *out, f_iosize);
132100384Speter	CP(*in, *out, f_blocks);
133100384Speter	CP(*in, *out, f_bfree);
134100384Speter	CP(*in, *out, f_bavail);
135100384Speter	CP(*in, *out, f_files);
136100384Speter	CP(*in, *out, f_ffree);
137100384Speter	CP(*in, *out, f_fsid);
138100384Speter	CP(*in, *out, f_owner);
139100384Speter	CP(*in, *out, f_type);
140100384Speter	CP(*in, *out, f_flags);
141100384Speter	CP(*in, *out, f_flags);
142100384Speter	CP(*in, *out, f_syncwrites);
143100384Speter	CP(*in, *out, f_asyncwrites);
144100384Speter	bcopy(in->f_fstypename,
145100384Speter	      out->f_fstypename, MFSNAMELEN);
146100384Speter	bcopy(in->f_mntonname,
147100384Speter	      out->f_mntonname, MNAMELEN);
148100384Speter	CP(*in, *out, f_syncreads);
149100384Speter	CP(*in, *out, f_asyncreads);
150100384Speter	bcopy(in->f_mntfromname,
151100384Speter	      out->f_mntfromname, MNAMELEN);
152100384Speter}
153100384Speter
154100384Speterint
155119333Speterfreebsd32_getfsstat(struct thread *td, struct freebsd32_getfsstat_args *uap)
156100384Speter{
157100384Speter	int error;
158100384Speter	caddr_t sg;
159100384Speter	struct statfs32 *sp32, stat32;
160100384Speter	struct statfs *sp = NULL, stat;
161100384Speter	int maxcount, count, i;
162100384Speter
163107849Salfred	sp32 = uap->buf;
164107849Salfred	maxcount = uap->bufsize / sizeof(struct statfs32);
165100384Speter
166100384Speter	if (sp32) {
167100384Speter		sg = stackgap_init();
168100384Speter		sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
169107849Salfred		uap->buf = (struct statfs32 *)sp;
170100384Speter	}
171100384Speter	error = getfsstat(td, (struct getfsstat_args *) uap);
172100384Speter	if (sp32 && !error) {
173100384Speter		count = td->td_retval[0];
174100384Speter		for (i = 0; i < count; i++) {
175100384Speter			error = copyin(&sp[i], &stat, sizeof(stat));
176100384Speter			if (error)
177100384Speter				return (error);
178100384Speter			copy_statfs(&stat, &stat32);
179100384Speter			error = copyout(&stat32, &sp32[i], sizeof(stat32));
180100384Speter			if (error)
181100384Speter				return (error);
182100384Speter		}
183100384Speter	}
184100384Speter	return (error);
185100384Speter}
186100384Speter
187100384Speterstruct sigaltstack32 {
188100384Speter	u_int32_t	ss_sp;
189100384Speter	u_int32_t	ss_size;
190100384Speter	int		ss_flags;
191100384Speter};
192100384Speter
193121719SpeterCTASSERT(sizeof(struct sigaltstack32) == 12);
194121719Speter
195100384Speterint
196119333Speterfreebsd32_sigaltstack(struct thread *td,
197119333Speter		      struct freebsd32_sigaltstack_args *uap)
198100384Speter{
199113859Sjhb	struct sigaltstack32 s32;
200113859Sjhb	struct sigaltstack ss, oss, *ssp;
201100384Speter	int error;
202100384Speter
203113859Sjhb	if (uap->ss != NULL) {
204113859Sjhb		error = copyin(uap->ss, &s32, sizeof(s32));
205100384Speter		if (error)
206100384Speter			return (error);
207113859Sjhb		PTRIN_CP(s32, ss, ss_sp);
208113859Sjhb		CP(s32, ss, ss_size);
209113859Sjhb		CP(s32, ss, ss_flags);
210113859Sjhb		ssp = &ss;
211113859Sjhb	} else
212113859Sjhb		ssp = NULL;
213113859Sjhb	error = kern_sigaltstack(td, ssp, &oss);
214113859Sjhb	if (error == 0 && uap->oss != NULL) {
215113859Sjhb		PTROUT_CP(oss, s32, ss_sp);
216113859Sjhb		CP(oss, s32, ss_size);
217113859Sjhb		CP(oss, s32, ss_flags);
218113859Sjhb		error = copyout(&s32, uap->oss, sizeof(s32));
219100384Speter	}
220100384Speter	return (error);
221100384Speter}
222100384Speter
223100384Speterint
224119333Speterfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
225100384Speter{
226100384Speter	int error;
227100384Speter	caddr_t sg;
228100384Speter	struct execve_args ap;
229100384Speter	u_int32_t *p32, arg;
230122253Speter	char **p, *p64;
231100384Speter	int count;
232100384Speter
233100384Speter	sg = stackgap_init();
234107849Salfred	ap.fname = uap->fname;
235100384Speter
236107849Salfred	if (uap->argv) {
237100384Speter		count = 0;
238107849Salfred		p32 = uap->argv;
239100384Speter		do {
240100384Speter			error = copyin(p32++, &arg, sizeof(arg));
241100384Speter			if (error)
242100384Speter				return error;
243100384Speter			count++;
244100384Speter		} while (arg != 0);
245100384Speter		p = stackgap_alloc(&sg, count * sizeof(char *));
246107849Salfred		ap.argv = p;
247107849Salfred		p32 = uap->argv;
248100384Speter		do {
249100384Speter			error = copyin(p32++, &arg, sizeof(arg));
250100384Speter			if (error)
251100384Speter				return error;
252122253Speter			p64 = PTRIN(arg);
253122253Speter			error = copyout(&p64, p++, sizeof(p64));
254122253Speter			if (error)
255122253Speter				return error;
256100384Speter		} while (arg != 0);
257100384Speter	}
258107849Salfred	if (uap->envv) {
259100384Speter		count = 0;
260107849Salfred		p32 = uap->envv;
261100384Speter		do {
262100384Speter			error = copyin(p32++, &arg, sizeof(arg));
263100384Speter			if (error)
264100384Speter				return error;
265100384Speter			count++;
266100384Speter		} while (arg != 0);
267100384Speter		p = stackgap_alloc(&sg, count * sizeof(char *));
268107849Salfred		ap.envv = p;
269107849Salfred		p32 = uap->envv;
270100384Speter		do {
271100384Speter			error = copyin(p32++, &arg, sizeof(arg));
272100384Speter			if (error)
273100384Speter				return error;
274122253Speter			p64 = PTRIN(arg);
275122253Speter			error = copyout(&p64, p++, sizeof(p64));
276122253Speter			if (error)
277122253Speter				return error;
278100384Speter		} while (arg != 0);
279100384Speter	}
280100384Speter
281100384Speter	return execve(td, &ap);
282100384Speter}
283100384Speter
284114987Speter#ifdef __ia64__
285100384Speterstatic int
286119333Speterfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
287119333Speter		       int prot, int fd, off_t pos)
288100384Speter{
289100384Speter	vm_map_t map;
290100384Speter	vm_map_entry_t entry;
291100384Speter	int rv;
292100384Speter
293100384Speter	map = &td->td_proc->p_vmspace->vm_map;
294100384Speter	if (fd != -1)
295100384Speter		prot |= VM_PROT_WRITE;
296100384Speter
297100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
298100384Speter		if ((entry->protection & prot) != prot) {
299100384Speter			rv = vm_map_protect(map,
300100384Speter					    trunc_page(start),
301100384Speter					    round_page(end),
302100384Speter					    entry->protection | prot,
303100384Speter					    FALSE);
304100384Speter			if (rv != KERN_SUCCESS)
305100384Speter				return (EINVAL);
306100384Speter		}
307100384Speter	} else {
308100384Speter		vm_offset_t addr = trunc_page(start);
309100384Speter		rv = vm_map_find(map, 0, 0,
310100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
311100384Speter				 VM_PROT_ALL, 0);
312100384Speter		if (rv != KERN_SUCCESS)
313100384Speter			return (EINVAL);
314100384Speter	}
315100384Speter
316100384Speter	if (fd != -1) {
317100384Speter		struct pread_args r;
318107849Salfred		r.fd = fd;
319107849Salfred		r.buf = (void *) start;
320107849Salfred		r.nbyte = end - start;
321107849Salfred		r.offset = pos;
322100384Speter		return (pread(td, &r));
323100384Speter	} else {
324100384Speter		while (start < end) {
325100384Speter			subyte((void *) start, 0);
326100384Speter			start++;
327100384Speter		}
328100384Speter		return (0);
329100384Speter	}
330100384Speter}
331114987Speter#endif
332100384Speter
333100384Speterint
334119333Speterfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
335100384Speter{
336100384Speter	struct mmap_args ap;
337107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
338107849Salfred	vm_size_t len	 = uap->len;
339107849Salfred	int prot	 = uap->prot;
340107849Salfred	int flags	 = uap->flags;
341107849Salfred	int fd		 = uap->fd;
342107849Salfred	off_t pos	 = (uap->poslo
343107849Salfred			    | ((off_t)uap->poshi << 32));
344114987Speter#ifdef __ia64__
345100384Speter	vm_size_t pageoff;
346100384Speter	int error;
347100384Speter
348100384Speter	/*
349100384Speter	 * Attempt to handle page size hassles.
350100384Speter	 */
351100384Speter	pageoff = (pos & PAGE_MASK);
352100384Speter	if (flags & MAP_FIXED) {
353100384Speter		vm_offset_t start, end;
354100384Speter		start = addr;
355100384Speter		end = addr + len;
356100384Speter
357100384Speter		if (start != trunc_page(start)) {
358119333Speter			error = freebsd32_mmap_partial(td, start,
359119333Speter						       round_page(start), prot,
360119333Speter						       fd, pos);
361100384Speter			if (fd != -1)
362100384Speter				pos += round_page(start) - start;
363100384Speter			start = round_page(start);
364100384Speter		}
365100384Speter		if (end != round_page(end)) {
366100384Speter			vm_offset_t t = trunc_page(end);
367119333Speter			error = freebsd32_mmap_partial(td, t, end,
368100384Speter						  prot, fd,
369100384Speter						  pos + t - start);
370100384Speter			end = trunc_page(end);
371100384Speter		}
372100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
373100384Speter			/*
374100384Speter			 * We can't map this region at all. The specified
375100384Speter			 * address doesn't have the same alignment as the file
376100384Speter			 * position. Fake the mapping by simply reading the
377100384Speter			 * entire region into memory. First we need to make
378100384Speter			 * sure the region exists.
379100384Speter			 */
380100384Speter			vm_map_t map;
381100384Speter			struct pread_args r;
382100384Speter			int rv;
383100384Speter
384100384Speter			prot |= VM_PROT_WRITE;
385100384Speter			map = &td->td_proc->p_vmspace->vm_map;
386100384Speter			rv = vm_map_remove(map, start, end);
387100384Speter			if (rv != KERN_SUCCESS)
388100384Speter				return (EINVAL);
389100384Speter			rv = vm_map_find(map, 0, 0,
390100384Speter					 &start, end - start, FALSE,
391100384Speter					 prot, VM_PROT_ALL, 0);
392100384Speter			if (rv != KERN_SUCCESS)
393100384Speter				return (EINVAL);
394107849Salfred			r.fd = fd;
395107849Salfred			r.buf = (void *) start;
396107849Salfred			r.nbyte = end - start;
397107849Salfred			r.offset = pos;
398100384Speter			error = pread(td, &r);
399100384Speter			if (error)
400100384Speter				return (error);
401100384Speter
402100384Speter			td->td_retval[0] = addr;
403100384Speter			return (0);
404100384Speter		}
405100384Speter		if (end == start) {
406100384Speter			/*
407100384Speter			 * After dealing with the ragged ends, there
408100384Speter			 * might be none left.
409100384Speter			 */
410100384Speter			td->td_retval[0] = addr;
411100384Speter			return (0);
412100384Speter		}
413100384Speter		addr = start;
414100384Speter		len = end - start;
415100384Speter	}
416114987Speter#endif
417100384Speter
418107849Salfred	ap.addr = (void *) addr;
419107849Salfred	ap.len = len;
420107849Salfred	ap.prot = prot;
421107849Salfred	ap.flags = flags;
422107849Salfred	ap.fd = fd;
423107849Salfred	ap.pos = pos;
424100384Speter
425100384Speter	return (mmap(td, &ap));
426100384Speter}
427100384Speter
428100384Speterstruct itimerval32 {
429100384Speter	struct timeval32 it_interval;
430100384Speter	struct timeval32 it_value;
431100384Speter};
432100384Speter
433121719SpeterCTASSERT(sizeof(struct itimerval32) == 16);
434121719Speter
435100384Speterint
436119333Speterfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
437100384Speter{
438100384Speter	int error;
439100384Speter	caddr_t sg;
440100384Speter	struct itimerval32 *p32, *op32, s32;
441100384Speter	struct itimerval *p = NULL, *op = NULL, s;
442100384Speter
443107849Salfred	p32 = uap->itv;
444100384Speter	if (p32) {
445100384Speter		sg = stackgap_init();
446100384Speter		p = stackgap_alloc(&sg, sizeof(struct itimerval));
447107849Salfred		uap->itv = (struct itimerval32 *)p;
448100384Speter		error = copyin(p32, &s32, sizeof(s32));
449100384Speter		if (error)
450100384Speter			return (error);
451100384Speter		TV_CP(s32, s, it_interval);
452100384Speter		TV_CP(s32, s, it_value);
453100384Speter		error = copyout(&s, p, sizeof(s));
454100384Speter		if (error)
455100384Speter			return (error);
456100384Speter	}
457107849Salfred	op32 = uap->oitv;
458100384Speter	if (op32) {
459100384Speter		sg = stackgap_init();
460100384Speter		op = stackgap_alloc(&sg, sizeof(struct itimerval));
461107849Salfred		uap->oitv = (struct itimerval32 *)op;
462100384Speter	}
463100384Speter	error = setitimer(td, (struct setitimer_args *) uap);
464100384Speter	if (error)
465100384Speter		return (error);
466100384Speter	if (op32) {
467100384Speter		error = copyin(op, &s, sizeof(s));
468100384Speter		if (error)
469100384Speter			return (error);
470100384Speter		TV_CP(s, s32, it_interval);
471100384Speter		TV_CP(s, s32, it_value);
472100384Speter		error = copyout(&s32, op32, sizeof(s32));
473100384Speter	}
474100384Speter	return (error);
475100384Speter}
476100384Speter
477100384Speterint
478125171Speterfreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
479125171Speter{
480125171Speter	int error;
481125171Speter	caddr_t sg;
482125171Speter	struct itimerval32 *p32, s32;
483125171Speter	struct itimerval *p = NULL, s;
484125171Speter
485125171Speter	p32 = uap->itv;
486125171Speter	if (p32) {
487125171Speter		sg = stackgap_init();
488125171Speter		p = stackgap_alloc(&sg, sizeof(struct itimerval));
489125171Speter		uap->itv = (struct itimerval32 *)p;
490125171Speter	}
491125171Speter	error = getitimer(td, (struct getitimer_args *) uap);
492125171Speter	if (error)
493125171Speter		return (error);
494125171Speter	if (p32) {
495125171Speter		error = copyin(p, &s, sizeof(s));
496125171Speter		if (error)
497125171Speter			return (error);
498125171Speter		TV_CP(s, s32, it_interval);
499125171Speter		TV_CP(s, s32, it_value);
500125171Speter		error = copyout(&s32, p32, sizeof(s32));
501125171Speter	}
502125171Speter	return (error);
503125171Speter}
504125171Speter
505125171Speterint
506119333Speterfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
507100384Speter{
508100384Speter	int error;
509100384Speter	caddr_t sg;
510100384Speter	struct timeval32 *p32, s32;
511100384Speter	struct timeval *p = NULL, s;
512100384Speter
513107849Salfred	p32 = uap->tv;
514100384Speter	if (p32) {
515100384Speter		sg = stackgap_init();
516100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
517107849Salfred		uap->tv = (struct timeval32 *)p;
518100384Speter		error = copyin(p32, &s32, sizeof(s32));
519100384Speter		if (error)
520100384Speter			return (error);
521100384Speter		CP(s32, s, tv_sec);
522100384Speter		CP(s32, s, tv_usec);
523100384Speter		error = copyout(&s, p, sizeof(s));
524100384Speter		if (error)
525100384Speter			return (error);
526100384Speter	}
527100384Speter	/*
528100384Speter	 * XXX big-endian needs to convert the fd_sets too.
529100384Speter	 */
530100384Speter	return (select(td, (struct select_args *) uap));
531100384Speter}
532100384Speter
533114987Speterstruct kevent32 {
534114987Speter	u_int32_t	ident;		/* identifier for this event */
535114987Speter	short		filter;		/* filter for event */
536114987Speter	u_short		flags;
537114987Speter	u_int		fflags;
538114987Speter	int32_t		data;
539114987Speter	u_int32_t	udata;		/* opaque user data identifier */
540114987Speter};
541114987Speter
542121719SpeterCTASSERT(sizeof(struct kevent32) == 20);
543121719Speter
544100384Speterint
545119333Speterfreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
546114987Speter{
547114987Speter	int error;
548114987Speter	caddr_t sg;
549114987Speter	struct timespec32 ts32;
550114987Speter	struct timespec ts;
551114987Speter	struct kevent32 ks32;
552114987Speter	struct kevent *ks;
553114987Speter	struct kevent_args a;
554114987Speter	int i;
555114987Speter
556114987Speter	sg = stackgap_init();
557114987Speter
558114987Speter	a.fd = uap->fd;
559114987Speter	a.changelist = uap->changelist;
560114987Speter	a.nchanges = uap->nchanges;
561114987Speter	a.eventlist = uap->eventlist;
562114987Speter	a.nevents = uap->nevents;
563114987Speter	a.timeout = NULL;
564114987Speter
565114987Speter	if (uap->timeout) {
566114987Speter		a.timeout = stackgap_alloc(&sg, sizeof(struct timespec));
567114987Speter		error = copyin(uap->timeout, &ts32, sizeof(ts32));
568114987Speter		if (error)
569114987Speter			return (error);
570114987Speter		CP(ts32, ts, tv_sec);
571114987Speter		CP(ts32, ts, tv_nsec);
572114987Speter		error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts));
573114987Speter		if (error)
574114987Speter			return (error);
575114987Speter	}
576114987Speter	if (uap->changelist) {
577119333Speter		a.changelist = (struct kevent *)stackgap_alloc(&sg,
578119333Speter		    uap->nchanges * sizeof(struct kevent));
579114987Speter		for (i = 0; i < uap->nchanges; i++) {
580119333Speter			error = copyin(&uap->changelist[i], &ks32,
581119333Speter			    sizeof(ks32));
582114987Speter			if (error)
583114987Speter				return (error);
584114987Speter			ks = (struct kevent *)(uintptr_t)&a.changelist[i];
585114987Speter			CP(ks32, *ks, ident);
586114987Speter			CP(ks32, *ks, filter);
587114987Speter			CP(ks32, *ks, flags);
588114987Speter			CP(ks32, *ks, fflags);
589114987Speter			CP(ks32, *ks, data);
590114987Speter			PTRIN_CP(ks32, *ks, udata);
591114987Speter		}
592114987Speter	}
593114987Speter	if (uap->eventlist) {
594119333Speter		a.eventlist = stackgap_alloc(&sg,
595119333Speter		    uap->nevents * sizeof(struct kevent));
596114987Speter	}
597114987Speter	error = kevent(td, &a);
598114987Speter	if (uap->eventlist && error > 0) {
599114987Speter		for (i = 0; i < error; i++) {
600114987Speter			ks = &a.eventlist[i];
601114987Speter			CP(*ks, ks32, ident);
602114987Speter			CP(*ks, ks32, filter);
603114987Speter			CP(*ks, ks32, flags);
604114987Speter			CP(*ks, ks32, fflags);
605114987Speter			CP(*ks, ks32, data);
606114987Speter			PTROUT_CP(*ks, ks32, udata);
607119333Speter			error = copyout(&ks32, &uap->eventlist[i],
608119333Speter			    sizeof(ks32));
609114987Speter			if (error)
610114987Speter				return (error);
611114987Speter		}
612114987Speter	}
613114987Speter	return error;
614114987Speter}
615114987Speter
616114987Speterint
617119333Speterfreebsd32_gettimeofday(struct thread *td,
618119333Speter		       struct freebsd32_gettimeofday_args *uap)
619100384Speter{
620123425Speter	struct timeval atv;
621123425Speter	struct timeval32 atv32;
622123425Speter	struct timezone rtz;
623123425Speter	int error = 0;
624100384Speter
625123425Speter	if (uap->tp) {
626123425Speter		microtime(&atv);
627123425Speter		CP(atv, atv32, tv_sec);
628123425Speter		CP(atv, atv32, tv_usec);
629123425Speter		error = copyout(&atv32, uap->tp, sizeof (atv32));
630100384Speter	}
631123425Speter	if (error == 0 && uap->tzp != NULL) {
632123425Speter		rtz.tz_minuteswest = tz_minuteswest;
633123425Speter		rtz.tz_dsttime = tz_dsttime;
634123425Speter		error = copyout(&rtz, uap->tzp, sizeof (rtz));
635100384Speter	}
636100384Speter	return (error);
637100384Speter}
638100384Speter
639100384Speterint
640119333Speterfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
641100384Speter{
642100384Speter	int error;
643100384Speter	caddr_t sg;
644100384Speter	struct rusage32 *p32, s32;
645100384Speter	struct rusage *p = NULL, s;
646100384Speter
647107849Salfred	p32 = uap->rusage;
648100384Speter	if (p32) {
649100384Speter		sg = stackgap_init();
650100384Speter		p = stackgap_alloc(&sg, sizeof(struct rusage));
651107849Salfred		uap->rusage = (struct rusage32 *)p;
652100384Speter	}
653100384Speter	error = getrusage(td, (struct getrusage_args *) uap);
654100384Speter	if (error)
655100384Speter		return (error);
656100384Speter	if (p32) {
657100384Speter		error = copyin(p, &s, sizeof(s));
658100384Speter		if (error)
659100384Speter			return (error);
660100384Speter		TV_CP(s, s32, ru_utime);
661100384Speter		TV_CP(s, s32, ru_stime);
662100384Speter		CP(s, s32, ru_maxrss);
663100384Speter		CP(s, s32, ru_ixrss);
664100384Speter		CP(s, s32, ru_idrss);
665100384Speter		CP(s, s32, ru_isrss);
666100384Speter		CP(s, s32, ru_minflt);
667100384Speter		CP(s, s32, ru_majflt);
668100384Speter		CP(s, s32, ru_nswap);
669100384Speter		CP(s, s32, ru_inblock);
670100384Speter		CP(s, s32, ru_oublock);
671100384Speter		CP(s, s32, ru_msgsnd);
672100384Speter		CP(s, s32, ru_msgrcv);
673100384Speter		CP(s, s32, ru_nsignals);
674100384Speter		CP(s, s32, ru_nvcsw);
675100384Speter		CP(s, s32, ru_nivcsw);
676100384Speter		error = copyout(&s32, p32, sizeof(s32));
677100384Speter	}
678100384Speter	return (error);
679100384Speter}
680100384Speter
681100384Speterstruct iovec32 {
682100384Speter	u_int32_t iov_base;
683100384Speter	int	iov_len;
684100384Speter};
685100384Speter#define	STACKGAPLEN	400
686100384Speter
687121719SpeterCTASSERT(sizeof(struct iovec32) == 8);
688121719Speter
689100384Speterint
690119333Speterfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
691100384Speter{
692100384Speter	int error, osize, nsize, i;
693100384Speter	caddr_t sg;
694100384Speter	struct readv_args /* {
695100384Speter		syscallarg(int) fd;
696100384Speter		syscallarg(struct iovec *) iovp;
697100384Speter		syscallarg(u_int) iovcnt;
698100384Speter	} */ a;
699100384Speter	struct iovec32 *oio;
700100384Speter	struct iovec *nio;
701100384Speter
702100384Speter	sg = stackgap_init();
703100384Speter
704107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
705100384Speter		return (EINVAL);
706100384Speter
707107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
708107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
709100384Speter
710111119Simp	oio = malloc(osize, M_TEMP, M_WAITOK);
711111119Simp	nio = malloc(nsize, M_TEMP, M_WAITOK);
712100384Speter
713100384Speter	error = 0;
714107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
715100384Speter		goto punt;
716107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
717100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
718100384Speter		nio[i].iov_len = oio[i].iov_len;
719100384Speter	}
720100384Speter
721107849Salfred	a.fd = uap->fd;
722107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
723107849Salfred	a.iovcnt = uap->iovcnt;
724100384Speter
725107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
726100384Speter		goto punt;
727100384Speter	error = readv(td, &a);
728100384Speter
729100384Speterpunt:
730100384Speter	free(oio, M_TEMP);
731100384Speter	free(nio, M_TEMP);
732100384Speter	return (error);
733100384Speter}
734100384Speter
735100384Speterint
736119333Speterfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
737100384Speter{
738100384Speter	int error, i, nsize, osize;
739100384Speter	caddr_t sg;
740100384Speter	struct writev_args /* {
741100384Speter		syscallarg(int) fd;
742100384Speter		syscallarg(struct iovec *) iovp;
743100384Speter		syscallarg(u_int) iovcnt;
744100384Speter	} */ a;
745100384Speter	struct iovec32 *oio;
746100384Speter	struct iovec *nio;
747100384Speter
748100384Speter	sg = stackgap_init();
749100384Speter
750107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
751100384Speter		return (EINVAL);
752100384Speter
753107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
754107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
755100384Speter
756111119Simp	oio = malloc(osize, M_TEMP, M_WAITOK);
757111119Simp	nio = malloc(nsize, M_TEMP, M_WAITOK);
758100384Speter
759100384Speter	error = 0;
760107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
761100384Speter		goto punt;
762107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
763100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
764100384Speter		nio[i].iov_len = oio[i].iov_len;
765100384Speter	}
766100384Speter
767107849Salfred	a.fd = uap->fd;
768107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
769107849Salfred	a.iovcnt = uap->iovcnt;
770100384Speter
771107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
772100384Speter		goto punt;
773100384Speter	error = writev(td, &a);
774100384Speter
775100384Speterpunt:
776100384Speter	free(oio, M_TEMP);
777100384Speter	free(nio, M_TEMP);
778100384Speter	return (error);
779100384Speter}
780100384Speter
781100384Speterint
782119333Speterfreebsd32_settimeofday(struct thread *td,
783119333Speter		       struct freebsd32_settimeofday_args *uap)
784100384Speter{
785100384Speter	int error;
786100384Speter	caddr_t sg;
787100384Speter	struct timeval32 *p32, s32;
788100384Speter	struct timeval *p = NULL, s;
789100384Speter
790107849Salfred	p32 = uap->tv;
791100384Speter	if (p32) {
792100384Speter		sg = stackgap_init();
793100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
794107849Salfred		uap->tv = (struct timeval32 *)p;
795100384Speter		error = copyin(p32, &s32, sizeof(s32));
796100384Speter		if (error)
797100384Speter			return (error);
798100384Speter		CP(s32, s, tv_sec);
799100384Speter		CP(s32, s, tv_usec);
800100384Speter		error = copyout(&s, p, sizeof(s));
801100384Speter		if (error)
802100384Speter			return (error);
803100384Speter	}
804100384Speter	return (settimeofday(td, (struct settimeofday_args *) uap));
805100384Speter}
806100384Speter
807100384Speterint
808119333Speterfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
809100384Speter{
810100384Speter	int error;
811100384Speter	caddr_t sg;
812100384Speter	struct timeval32 *p32, s32[2];
813100384Speter	struct timeval *p = NULL, s[2];
814100384Speter
815107849Salfred	p32 = uap->tptr;
816100384Speter	if (p32) {
817100384Speter		sg = stackgap_init();
818100384Speter		p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
819107849Salfred		uap->tptr = (struct timeval32 *)p;
820100384Speter		error = copyin(p32, s32, sizeof(s32));
821100384Speter		if (error)
822100384Speter			return (error);
823100384Speter		CP(s32[0], s[0], tv_sec);
824100384Speter		CP(s32[0], s[0], tv_usec);
825100384Speter		CP(s32[1], s[1], tv_sec);
826100384Speter		CP(s32[1], s[1], tv_usec);
827100384Speter		error = copyout(s, p, sizeof(s));
828100384Speter		if (error)
829100384Speter			return (error);
830100384Speter	}
831100384Speter	return (utimes(td, (struct utimes_args *) uap));
832100384Speter}
833100384Speter
834100384Speterint
835119333Speterfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
836100384Speter{
837100384Speter	int error;
838100384Speter	caddr_t sg;
839100384Speter	struct timeval32 *p32, *op32, s32;
840100384Speter	struct timeval *p = NULL, *op = NULL, s;
841100384Speter
842107849Salfred	p32 = uap->delta;
843100384Speter	if (p32) {
844100384Speter		sg = stackgap_init();
845100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
846107849Salfred		uap->delta = (struct timeval32 *)p;
847100384Speter		error = copyin(p32, &s32, sizeof(s32));
848100384Speter		if (error)
849100384Speter			return (error);
850100384Speter		CP(s32, s, tv_sec);
851100384Speter		CP(s32, s, tv_usec);
852100384Speter		error = copyout(&s, p, sizeof(s));
853100384Speter		if (error)
854100384Speter			return (error);
855100384Speter	}
856107849Salfred	op32 = uap->olddelta;
857100384Speter	if (op32) {
858100384Speter		sg = stackgap_init();
859100384Speter		op = stackgap_alloc(&sg, sizeof(struct timeval));
860107849Salfred		uap->olddelta = (struct timeval32 *)op;
861100384Speter	}
862100384Speter	error = utimes(td, (struct utimes_args *) uap);
863100384Speter	if (error)
864100384Speter		return error;
865100384Speter	if (op32) {
866100384Speter		error = copyin(op, &s, sizeof(s));
867100384Speter		if (error)
868100384Speter			return (error);
869100384Speter		CP(s, s32, tv_sec);
870100384Speter		CP(s, s32, tv_usec);
871100384Speter		error = copyout(&s32, op32, sizeof(s32));
872100384Speter	}
873100384Speter	return (error);
874100384Speter}
875100384Speter
876100384Speterint
877119333Speterfreebsd32_statfs(struct thread *td, struct freebsd32_statfs_args *uap)
878100384Speter{
879100384Speter	int error;
880100384Speter	caddr_t sg;
881100384Speter	struct statfs32 *p32, s32;
882100384Speter	struct statfs *p = NULL, s;
883100384Speter
884107849Salfred	p32 = uap->buf;
885100384Speter	if (p32) {
886100384Speter		sg = stackgap_init();
887100384Speter		p = stackgap_alloc(&sg, sizeof(struct statfs));
888107849Salfred		uap->buf = (struct statfs32 *)p;
889100384Speter	}
890100384Speter	error = statfs(td, (struct statfs_args *) uap);
891100384Speter	if (error)
892100384Speter		return (error);
893100384Speter	if (p32) {
894100384Speter		error = copyin(p, &s, sizeof(s));
895100384Speter		if (error)
896100384Speter			return (error);
897100384Speter		copy_statfs(&s, &s32);
898100384Speter		error = copyout(&s32, p32, sizeof(s32));
899100384Speter	}
900100384Speter	return (error);
901100384Speter}
902100384Speter
903100384Speterint
904119333Speterfreebsd32_fstatfs(struct thread *td, struct freebsd32_fstatfs_args *uap)
905100384Speter{
906100384Speter	int error;
907100384Speter	caddr_t sg;
908100384Speter	struct statfs32 *p32, s32;
909100384Speter	struct statfs *p = NULL, s;
910100384Speter
911107849Salfred	p32 = uap->buf;
912100384Speter	if (p32) {
913100384Speter		sg = stackgap_init();
914100384Speter		p = stackgap_alloc(&sg, sizeof(struct statfs));
915107849Salfred		uap->buf = (struct statfs32 *)p;
916100384Speter	}
917100384Speter	error = fstatfs(td, (struct fstatfs_args *) uap);
918100384Speter	if (error)
919100384Speter		return (error);
920100384Speter	if (p32) {
921100384Speter		error = copyin(p, &s, sizeof(s));
922100384Speter		if (error)
923100384Speter			return (error);
924100384Speter		copy_statfs(&s, &s32);
925100384Speter		error = copyout(&s32, p32, sizeof(s32));
926100384Speter	}
927100384Speter	return (error);
928100384Speter}
929100384Speter
930100384Speterint
931119333Speterfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
932100384Speter{
933100384Speter	/*
934100384Speter	 * Vector through to semsys if it is loaded.
935100384Speter	 */
936100384Speter	return sysent[169].sy_call(td, uap);
937100384Speter}
938100384Speter
939100384Speterint
940119333Speterfreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
941100384Speter{
942100384Speter	/*
943100384Speter	 * Vector through to msgsys if it is loaded.
944100384Speter	 */
945100384Speter	return sysent[170].sy_call(td, uap);
946100384Speter}
947100384Speter
948100384Speterint
949119333Speterfreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
950100384Speter{
951100384Speter	/*
952100384Speter	 * Vector through to shmsys if it is loaded.
953100384Speter	 */
954100384Speter	return sysent[171].sy_call(td, uap);
955100384Speter}
956100384Speter
957100384Speterint
958119333Speterfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
959100384Speter{
960100384Speter	struct pread_args ap;
961100384Speter
962107849Salfred	ap.fd = uap->fd;
963107849Salfred	ap.buf = uap->buf;
964107849Salfred	ap.nbyte = uap->nbyte;
965119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
966100384Speter	return (pread(td, &ap));
967100384Speter}
968100384Speter
969100384Speterint
970119333Speterfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
971100384Speter{
972100384Speter	struct pwrite_args ap;
973100384Speter
974107849Salfred	ap.fd = uap->fd;
975107849Salfred	ap.buf = uap->buf;
976107849Salfred	ap.nbyte = uap->nbyte;
977119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
978100384Speter	return (pwrite(td, &ap));
979100384Speter}
980100384Speter
981100384Speterint
982119333Speterfreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
983100384Speter{
984100384Speter	int error;
985100384Speter	struct lseek_args ap;
986100384Speter	off_t pos;
987100384Speter
988107849Salfred	ap.fd = uap->fd;
989119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
990107849Salfred	ap.whence = uap->whence;
991100384Speter	error = lseek(td, &ap);
992100384Speter	/* Expand the quad return into two parts for eax and edx */
993100384Speter	pos = *(off_t *)(td->td_retval);
994100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
995100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
996100384Speter	return error;
997100384Speter}
998100384Speter
999100384Speterint
1000119333Speterfreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1001100384Speter{
1002100384Speter	struct truncate_args ap;
1003100384Speter
1004107849Salfred	ap.path = uap->path;
1005119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1006100384Speter	return (truncate(td, &ap));
1007100384Speter}
1008100384Speter
1009100384Speterint
1010119333Speterfreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1011100384Speter{
1012100384Speter	struct ftruncate_args ap;
1013100384Speter
1014107849Salfred	ap.fd = uap->fd;
1015119333Speter	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1016100384Speter	return (ftruncate(td, &ap));
1017100384Speter}
1018100384Speter
1019104738Speter#ifdef COMPAT_FREEBSD4
1020100384Speterint
1021119333Speterfreebsd4_freebsd32_sendfile(struct thread *td,
1022119333Speter    struct freebsd4_freebsd32_sendfile_args *uap)
1023104738Speter{
1024104738Speter	struct freebsd4_sendfile_args ap;
1025104738Speter
1026107849Salfred	ap.fd = uap->fd;
1027107849Salfred	ap.s = uap->s;
1028119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1029107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1030107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1031107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1032107849Salfred	ap.flags = uap->flags;
1033104738Speter	return (freebsd4_sendfile(td, &ap));
1034104738Speter}
1035104738Speter#endif
1036104738Speter
1037104738Speterint
1038119333Speterfreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1039100384Speter{
1040100384Speter	struct sendfile_args ap;
1041100384Speter
1042107849Salfred	ap.fd = uap->fd;
1043107849Salfred	ap.s = uap->s;
1044119333Speter	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1045107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1046107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1047107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1048107849Salfred	ap.flags = uap->flags;
1049100384Speter	return (sendfile(td, &ap));
1050100384Speter}
1051100384Speter
1052100384Speterstruct stat32 {
1053100384Speter	udev_t	st_dev;
1054100384Speter	ino_t	st_ino;
1055100384Speter	mode_t	st_mode;
1056100384Speter	nlink_t	st_nlink;
1057100384Speter	uid_t	st_uid;
1058100384Speter	gid_t	st_gid;
1059100384Speter	udev_t	st_rdev;
1060100384Speter	struct timespec32 st_atimespec;
1061100384Speter	struct timespec32 st_mtimespec;
1062100384Speter	struct timespec32 st_ctimespec;
1063100384Speter	off_t	st_size;
1064100384Speter	int64_t	st_blocks;
1065100384Speter	u_int32_t st_blksize;
1066100384Speter	u_int32_t st_flags;
1067100384Speter	u_int32_t st_gen;
1068121719Speter	struct timespec32 st_birthtimespec;
1069121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1070121719Speter	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1071100384Speter};
1072100384Speter
1073121719Speter
1074121719SpeterCTASSERT(sizeof(struct stat32) == 96);
1075121719Speter
1076100384Speterstatic void
1077100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1078100384Speter{
1079100384Speter	CP(*in, *out, st_dev);
1080100384Speter	CP(*in, *out, st_ino);
1081100384Speter	CP(*in, *out, st_mode);
1082100384Speter	CP(*in, *out, st_nlink);
1083100384Speter	CP(*in, *out, st_uid);
1084100384Speter	CP(*in, *out, st_gid);
1085100384Speter	CP(*in, *out, st_rdev);
1086100384Speter	TS_CP(*in, *out, st_atimespec);
1087100384Speter	TS_CP(*in, *out, st_mtimespec);
1088100384Speter	TS_CP(*in, *out, st_ctimespec);
1089100384Speter	CP(*in, *out, st_size);
1090100384Speter	CP(*in, *out, st_blocks);
1091100384Speter	CP(*in, *out, st_blksize);
1092100384Speter	CP(*in, *out, st_flags);
1093100384Speter	CP(*in, *out, st_gen);
1094100384Speter}
1095100384Speter
1096100384Speterint
1097119333Speterfreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1098100384Speter{
1099123746Speter	struct stat sb;
1100123746Speter	struct stat32 sb32;
1101100384Speter	int error;
1102123746Speter	struct nameidata nd;
1103100384Speter
1104123746Speter#ifdef LOOKUP_SHARED
1105123746Speter	NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ,
1106123746Speter	    UIO_USERSPACE, uap->path, td);
1107123746Speter#else
1108123746Speter	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1109123746Speter	    uap->path, td);
1110123746Speter#endif
1111123746Speter	if ((error = namei(&nd)) != 0)
1112123746Speter		return (error);
1113123746Speter	error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
1114123746Speter	NDFREE(&nd, NDF_ONLY_PNBUF);
1115123746Speter	vput(nd.ni_vp);
1116100384Speter	if (error)
1117100384Speter		return (error);
1118123746Speter	copy_stat(&sb, &sb32);
1119123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1120100384Speter	return (error);
1121100384Speter}
1122100384Speter
1123100384Speterint
1124119333Speterfreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1125100384Speter{
1126123746Speter	struct file *fp;
1127123746Speter	struct stat ub;
1128123746Speter	struct stat32 ub32;
1129100384Speter	int error;
1130100384Speter
1131123746Speter	if ((error = fget(td, uap->fd, &fp)) != 0)
1132123746Speter		return (error);
1133123746Speter	mtx_lock(&Giant);
1134123746Speter	error = fo_stat(fp, &ub, td->td_ucred, td);
1135123746Speter	mtx_unlock(&Giant);
1136123746Speter	fdrop(fp, td);
1137100384Speter	if (error)
1138100384Speter		return (error);
1139123746Speter	copy_stat(&ub, &ub32);
1140123746Speter	error = copyout(&ub32, uap->ub, sizeof(ub32));
1141100384Speter	return (error);
1142100384Speter}
1143100384Speter
1144100384Speterint
1145119333Speterfreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1146100384Speter{
1147100384Speter	int error;
1148123746Speter	struct vnode *vp;
1149123746Speter	struct stat sb;
1150123746Speter	struct stat32 sb32;
1151123746Speter	struct nameidata nd;
1152100384Speter
1153123746Speter	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1154123746Speter	    uap->path, td);
1155123746Speter	if ((error = namei(&nd)) != 0)
1156123746Speter		return (error);
1157123746Speter	vp = nd.ni_vp;
1158123746Speter	error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
1159123746Speter	NDFREE(&nd, NDF_ONLY_PNBUF);
1160123746Speter	vput(vp);
1161100384Speter	if (error)
1162100384Speter		return (error);
1163123746Speter	copy_stat(&sb, &sb32);
1164123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
1165100384Speter	return (error);
1166100384Speter}
1167100384Speter
1168100384Speter/*
1169100384Speter * MPSAFE
1170100384Speter */
1171100384Speterint
1172119333Speterfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1173100384Speter{
1174100384Speter	int error, name[CTL_MAXNAME];
1175100384Speter	size_t j, oldlen;
1176100384Speter
1177100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1178100384Speter		return (EINVAL);
1179100384Speter
1180100384Speter 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1181100384Speter 	if (error)
1182100384Speter		return (error);
1183100384Speter
1184100384Speter	mtx_lock(&Giant);
1185100384Speter
1186100384Speter	if (uap->oldlenp)
1187100384Speter		oldlen = fuword32(uap->oldlenp);
1188100384Speter	else
1189100384Speter		oldlen = 0;
1190100384Speter	error = userland_sysctl(td, name, uap->namelen,
1191100384Speter		uap->old, &oldlen, 1,
1192100384Speter		uap->new, uap->newlen, &j);
1193100384Speter	if (error && error != ENOMEM)
1194100384Speter		goto done2;
1195100384Speter	if (uap->oldlenp) {
1196100384Speter		suword32(uap->oldlenp, j);
1197100384Speter	}
1198100384Speterdone2:
1199100384Speter	mtx_unlock(&Giant);
1200100384Speter	return (error);
1201100384Speter}
1202100384Speter
1203100384Speterstruct sigaction32 {
1204100384Speter	u_int32_t	sa_u;
1205100384Speter	int		sa_flags;
1206100384Speter	sigset_t	sa_mask;
1207100384Speter};
1208100384Speter
1209121719SpeterCTASSERT(sizeof(struct sigaction32) == 24);
1210121719Speter
1211100384Speterint
1212119333Speterfreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1213100384Speter{
1214113859Sjhb	struct sigaction32 s32;
1215113859Sjhb	struct sigaction sa, osa, *sap;
1216100384Speter	int error;
1217100384Speter
1218113859Sjhb	if (uap->act) {
1219113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
1220100384Speter		if (error)
1221100384Speter			return (error);
1222113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
1223113859Sjhb		CP(s32, sa, sa_flags);
1224113859Sjhb		CP(s32, sa, sa_mask);
1225113859Sjhb		sap = &sa;
1226113859Sjhb	} else
1227113859Sjhb		sap = NULL;
1228113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1229113859Sjhb	if (error != 0 && uap->oact != NULL) {
1230113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
1231113859Sjhb		CP(osa, s32, sa_flags);
1232113859Sjhb		CP(osa, s32, sa_mask);
1233113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
1234100384Speter	}
1235100384Speter	return (error);
1236100384Speter}
1237100384Speter
1238114987Speter#ifdef COMPAT_FREEBSD4
1239114987Speterint
1240119333Speterfreebsd4_freebsd32_sigaction(struct thread *td,
1241119333Speter			     struct freebsd4_freebsd32_sigaction_args *uap)
1242114987Speter{
1243114987Speter	struct sigaction32 s32;
1244114987Speter	struct sigaction sa, osa, *sap;
1245114987Speter	int error;
1246114987Speter
1247114987Speter	if (uap->act) {
1248114987Speter		error = copyin(uap->act, &s32, sizeof(s32));
1249114987Speter		if (error)
1250114987Speter			return (error);
1251114987Speter		sa.sa_handler = PTRIN(s32.sa_u);
1252114987Speter		CP(s32, sa, sa_flags);
1253114987Speter		CP(s32, sa, sa_mask);
1254114987Speter		sap = &sa;
1255114987Speter	} else
1256114987Speter		sap = NULL;
1257114987Speter	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1258114987Speter	if (error != 0 && uap->oact != NULL) {
1259114987Speter		s32.sa_u = PTROUT(osa.sa_handler);
1260114987Speter		CP(osa, s32, sa_flags);
1261114987Speter		CP(osa, s32, sa_mask);
1262114987Speter		error = copyout(&s32, uap->oact, sizeof(s32));
1263114987Speter	}
1264114987Speter	return (error);
1265114987Speter}
1266114987Speter#endif
1267114987Speter
1268100384Speter#if 0
1269100384Speter
1270100384Speterint
1271119333Speterfreebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1272100384Speter{
1273100384Speter	int error;
1274100384Speter	caddr_t sg;
1275100384Speter	struct yyy32 *p32, s32;
1276100384Speter	struct yyy *p = NULL, s;
1277100384Speter
1278107849Salfred	p32 = uap->zzz;
1279100384Speter	if (p32) {
1280100384Speter		sg = stackgap_init();
1281100384Speter		p = stackgap_alloc(&sg, sizeof(struct yyy));
1282107849Salfred		uap->zzz = (struct yyy32 *)p;
1283100384Speter		error = copyin(p32, &s32, sizeof(s32));
1284100384Speter		if (error)
1285100384Speter			return (error);
1286100384Speter		/* translate in */
1287100384Speter		error = copyout(&s, p, sizeof(s));
1288100384Speter		if (error)
1289100384Speter			return (error);
1290100384Speter	}
1291100384Speter	error = xxx(td, (struct xxx_args *) uap);
1292100384Speter	if (error)
1293100384Speter		return (error);
1294100384Speter	if (p32) {
1295100384Speter		error = copyin(p, &s, sizeof(s));
1296100384Speter		if (error)
1297100384Speter			return (error);
1298100384Speter		/* translate out */
1299100384Speter		error = copyout(&s32, p32, sizeof(s32));
1300100384Speter	}
1301100384Speter	return (error);
1302100384Speter}
1303100384Speter
1304100384Speter#endif
1305