freebsd32_misc.c revision 156440
114125Speter/*-
214125Speter * Copyright (c) 2002 Doug Rabson
314125Speter * All rights reserved.
414125Speter *
514125Speter * Redistribution and use in source and binary forms, with or without
614125Speter * modification, are permitted provided that the following conditions
714125Speter * are met:
814125Speter * 1. Redistributions of source code must retain the above copyright
914125Speter *    notice, this list of conditions and the following disclaimer.
1014125Speter * 2. Redistributions in binary form must reproduce the above copyright
1114125Speter *    notice, this list of conditions and the following disclaimer in the
1214125Speter *    documentation and/or other materials provided with the distribution.
1314125Speter *
1414125Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1514125Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1614125Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1714125Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1814125Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1914125Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2014125Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2114125Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2214125Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2314125Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2414125Speter * SUCH DAMAGE.
2514125Speter */
2614125Speter
2714125Speter#include <sys/cdefs.h>
2814125Speter__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 156440 2006-03-08 20:21:54Z ups $");
2914125Speter
3014125Speter#include "opt_compat.h"
3114125Speter
3214125Speter#include <sys/param.h>
3314125Speter#include <sys/systm.h>
3450479Speter#include <sys/bus.h>
3514125Speter#include <sys/exec.h>
36173263Smatteo#include <sys/fcntl.h>
3714125Speter#include <sys/filedesc.h>
3814125Speter#include <sys/namei.h>
3914125Speter#include <sys/imgact.h>
4079755Sdd#include <sys/kernel.h>
4114125Speter#include <sys/lock.h>
4214125Speter#include <sys/malloc.h>
4368965Sru#include <sys/file.h>		/* Must come after sys/malloc.h */
4414125Speter#include <sys/mbuf.h>
45173263Smatteo#include <sys/mman.h>
46168325Smatteo#include <sys/module.h>
4714125Speter#include <sys/mount.h>
4899968Scharnier#include <sys/mutex.h>
4999968Scharnier#include <sys/namei.h>
5099968Scharnier#include <sys/param.h>
5199968Scharnier#include <sys/proc.h>
5299968Scharnier#include <sys/reboot.h>
5399968Scharnier#include <sys/resource.h>
54131500Sru#include <sys/resourcevar.h>
55131500Sru#include <sys/selinfo.h>
5614125Speter#include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
5714125Speter#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
5814125Speter#include <sys/signal.h>
59131500Sru#include <sys/signalvar.h>
60131500Sru#include <sys/socket.h>
6114125Speter#include <sys/socketvar.h>
62131500Sru#include <sys/stat.h>
63131500Sru#include <sys/syscall.h>
6414125Speter#include <sys/syscallsubr.h>
6530376Scharnier#include <sys/sysctl.h>
6614125Speter#include <sys/sysent.h>
6714125Speter#include <sys/sysproto.h>
6814125Speter#include <sys/systm.h>
6930376Scharnier#include <sys/unistd.h>
7030376Scharnier#include <sys/vnode.h>
7114125Speter#include <sys/wait.h>
7230376Scharnier
73131500Sru#include <vm/vm.h>
74131500Sru#include <vm/vm_kern.h>
75131500Sru#include <vm/vm_param.h>
76131500Sru#include <vm/pmap.h>
7714125Speter#include <vm/vm_map.h>
78173263Smatteo#include <vm/vm_object.h>
79173263Smatteo#include <vm/vm_extern.h>
80173263Smatteo
81173263Smatteo#include <machine/cpu.h>
82173263Smatteo
83173263Smatteo#include <compat/freebsd32/freebsd32_util.h>
84173263Smatteo#include <compat/freebsd32/freebsd32.h>
85173263Smatteo#include <compat/freebsd32/freebsd32_proto.h>
86173263Smatteo
87173263SmatteoCTASSERT(sizeof(struct timeval32) == 8);
88173263SmatteoCTASSERT(sizeof(struct timespec32) == 8);
89173263SmatteoCTASSERT(sizeof(struct statfs32) == 256);
90173263SmatteoCTASSERT(sizeof(struct rusage32) == 72);
91173263Smatteo
92173263Smatteoint
93173263Smatteofreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
94173263Smatteo{
95168325Smatteo	int error, status;
96168325Smatteo	struct rusage32 ru32;
97168325Smatteo	struct rusage ru, *rup;
98168325Smatteo
99168325Smatteo	if (uap->rusage != NULL)
100168325Smatteo		rup = &ru;
10114125Speter	else
10214125Speter		rup = NULL;
10314125Speter	error = kern_wait(td, uap->pid, &status, uap->options, rup);
10430376Scharnier	if (error)
10599968Scharnier		return (error);
10614125Speter	if (uap->status != NULL)
10714125Speter		error = copyout(&status, uap->status, sizeof(status));
10814125Speter	if (uap->rusage != NULL && error == 0) {
10914125Speter		TV_CP(ru, ru32, ru_utime);
11014125Speter		TV_CP(ru, ru32, ru_stime);
11114125Speter		CP(ru, ru32, ru_maxrss);
11214125Speter		CP(ru, ru32, ru_ixrss);
11314125Speter		CP(ru, ru32, ru_idrss);
11414125Speter		CP(ru, ru32, ru_isrss);
11514125Speter		CP(ru, ru32, ru_minflt);
11614125Speter		CP(ru, ru32, ru_majflt);
11714125Speter		CP(ru, ru32, ru_nswap);
11814125Speter		CP(ru, ru32, ru_inblock);
11921880Swosch		CP(ru, ru32, ru_oublock);
12014125Speter		CP(ru, ru32, ru_msgsnd);
12121880Swosch		CP(ru, ru32, ru_msgrcv);
122140442Sru		CP(ru, ru32, ru_nsignals);
123140442Sru		CP(ru, ru32, ru_nvcsw);
124140442Sru		CP(ru, ru32, ru_nivcsw);
12514125Speter		error = copyout(&ru32, uap->rusage, sizeof(ru32));
12614125Speter	}
127131500Sru	return (error);
128131500Sru}
129131500Sru
13014125Speter#ifdef COMPAT_FREEBSD4
13114125Speterstatic void
13270403Srucopy_statfs(struct statfs *in, struct statfs32 *out)
13314125Speter{
13414125Speter
13514125Speter	bzero(out, sizeof(*out));
13614125Speter	CP(*in, *out, f_bsize);
13770403Sru	CP(*in, *out, f_iosize);
13814125Speter	CP(*in, *out, f_blocks);
139131500Sru	CP(*in, *out, f_bfree);
140131500Sru	CP(*in, *out, f_bavail);
14114125Speter	CP(*in, *out, f_files);
142	CP(*in, *out, f_ffree);
143	CP(*in, *out, f_fsid);
144	CP(*in, *out, f_owner);
145	CP(*in, *out, f_type);
146	CP(*in, *out, f_flags);
147	CP(*in, *out, f_flags);
148	CP(*in, *out, f_syncwrites);
149	CP(*in, *out, f_asyncwrites);
150	strlcpy(out->f_fstypename,
151	      in->f_fstypename, MFSNAMELEN);
152	strlcpy(out->f_mntonname,
153	      in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
154	CP(*in, *out, f_syncreads);
155	CP(*in, *out, f_asyncreads);
156	strlcpy(out->f_mntfromname,
157	      in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
158}
159#endif
160
161#ifdef COMPAT_FREEBSD4
162int
163freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
164{
165	struct statfs *buf, *sp;
166	struct statfs32 stat32;
167	size_t count, size;
168	int error;
169
170	count = uap->bufsize / sizeof(struct statfs32);
171	size = count * sizeof(struct statfs);
172	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
173	if (size > 0) {
174		count = td->td_retval[0];
175		sp = buf;
176		while (count > 0 && error == 0) {
177			copy_statfs(sp, &stat32);
178			error = copyout(&stat32, uap->buf, sizeof(stat32));
179			sp++;
180			uap->buf++;
181			count--;
182		}
183		free(buf, M_TEMP);
184	}
185	return (error);
186}
187#endif
188
189struct sigaltstack32 {
190	u_int32_t	ss_sp;
191	u_int32_t	ss_size;
192	int		ss_flags;
193};
194
195CTASSERT(sizeof(struct sigaltstack32) == 12);
196
197int
198freebsd32_sigaltstack(struct thread *td,
199		      struct freebsd32_sigaltstack_args *uap)
200{
201	struct sigaltstack32 s32;
202	struct sigaltstack ss, oss, *ssp;
203	int error;
204
205	if (uap->ss != NULL) {
206		error = copyin(uap->ss, &s32, sizeof(s32));
207		if (error)
208			return (error);
209		PTRIN_CP(s32, ss, ss_sp);
210		CP(s32, ss, ss_size);
211		CP(s32, ss, ss_flags);
212		ssp = &ss;
213	} else
214		ssp = NULL;
215	error = kern_sigaltstack(td, ssp, &oss);
216	if (error == 0 && uap->oss != NULL) {
217		PTROUT_CP(oss, s32, ss_sp);
218		CP(oss, s32, ss_size);
219		CP(oss, s32, ss_flags);
220		error = copyout(&s32, uap->oss, sizeof(s32));
221	}
222	return (error);
223}
224
225/*
226 * Custom version of exec_copyin_args() so that we can translate
227 * the pointers.
228 */
229static int
230freebsd32_exec_copyin_args(struct image_args *args, char *fname,
231    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
232{
233	char *argp, *envp;
234	u_int32_t *p32, arg;
235	size_t length;
236	int error;
237
238	bzero(args, sizeof(*args));
239	if (argv == NULL)
240		return (EFAULT);
241
242	/*
243	 * Allocate temporary demand zeroed space for argument and
244	 *	environment strings
245	 */
246	args->buf = (char *) kmem_alloc_wait(exec_map,
247	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
248	if (args->buf == NULL)
249		return (ENOMEM);
250	args->begin_argv = args->buf;
251	args->endp = args->begin_argv;
252	args->stringspace = ARG_MAX;
253
254	args->fname = args->buf + ARG_MAX;
255
256	/*
257	 * Copy the file name.
258	 */
259	error = (segflg == UIO_SYSSPACE) ?
260	    copystr(fname, args->fname, PATH_MAX, &length) :
261	    copyinstr(fname, args->fname, PATH_MAX, &length);
262	if (error != 0)
263		goto err_exit;
264
265	/*
266	 * extract arguments first
267	 */
268	p32 = argv;
269	for (;;) {
270		error = copyin(p32++, &arg, sizeof(arg));
271		if (error)
272			goto err_exit;
273		if (arg == 0)
274			break;
275		argp = PTRIN(arg);
276		error = copyinstr(argp, args->endp, args->stringspace, &length);
277		if (error) {
278			if (error == ENAMETOOLONG)
279				error = E2BIG;
280			goto err_exit;
281		}
282		args->stringspace -= length;
283		args->endp += length;
284		args->argc++;
285	}
286
287	args->begin_envv = args->endp;
288
289	/*
290	 * extract environment strings
291	 */
292	if (envv) {
293		p32 = envv;
294		for (;;) {
295			error = copyin(p32++, &arg, sizeof(arg));
296			if (error)
297				goto err_exit;
298			if (arg == 0)
299				break;
300			envp = PTRIN(arg);
301			error = copyinstr(envp, args->endp, args->stringspace,
302			    &length);
303			if (error) {
304				if (error == ENAMETOOLONG)
305					error = E2BIG;
306				goto err_exit;
307			}
308			args->stringspace -= length;
309			args->endp += length;
310			args->envc++;
311		}
312	}
313
314	return (0);
315
316err_exit:
317	kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
318	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
319	args->buf = NULL;
320	return (error);
321}
322
323int
324freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
325{
326	struct image_args eargs;
327	int error;
328
329	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
330	    uap->argv, uap->envv);
331	if (error == 0)
332		error = kern_execve(td, &eargs, NULL);
333	return (error);
334}
335
336#ifdef __ia64__
337static int
338freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
339		       int prot, int fd, off_t pos)
340{
341	vm_map_t map;
342	vm_map_entry_t entry;
343	int rv;
344
345	map = &td->td_proc->p_vmspace->vm_map;
346	if (fd != -1)
347		prot |= VM_PROT_WRITE;
348
349	if (vm_map_lookup_entry(map, start, &entry)) {
350		if ((entry->protection & prot) != prot) {
351			rv = vm_map_protect(map,
352					    trunc_page(start),
353					    round_page(end),
354					    entry->protection | prot,
355					    FALSE);
356			if (rv != KERN_SUCCESS)
357				return (EINVAL);
358		}
359	} else {
360		vm_offset_t addr = trunc_page(start);
361		rv = vm_map_find(map, 0, 0,
362				 &addr, PAGE_SIZE, FALSE, prot,
363				 VM_PROT_ALL, 0);
364		if (rv != KERN_SUCCESS)
365			return (EINVAL);
366	}
367
368	if (fd != -1) {
369		struct pread_args r;
370		r.fd = fd;
371		r.buf = (void *) start;
372		r.nbyte = end - start;
373		r.offset = pos;
374		return (pread(td, &r));
375	} else {
376		while (start < end) {
377			subyte((void *) start, 0);
378			start++;
379		}
380		return (0);
381	}
382}
383#endif
384
385int
386freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
387{
388	struct mmap_args ap;
389	vm_offset_t addr = (vm_offset_t) uap->addr;
390	vm_size_t len	 = uap->len;
391	int prot	 = uap->prot;
392	int flags	 = uap->flags;
393	int fd		 = uap->fd;
394	off_t pos	 = (uap->poslo
395			    | ((off_t)uap->poshi << 32));
396#ifdef __ia64__
397	vm_size_t pageoff;
398	int error;
399
400	/*
401	 * Attempt to handle page size hassles.
402	 */
403	pageoff = (pos & PAGE_MASK);
404	if (flags & MAP_FIXED) {
405		vm_offset_t start, end;
406		start = addr;
407		end = addr + len;
408
409		mtx_lock(&Giant);
410		if (start != trunc_page(start)) {
411			error = freebsd32_mmap_partial(td, start,
412						       round_page(start), prot,
413						       fd, pos);
414			if (fd != -1)
415				pos += round_page(start) - start;
416			start = round_page(start);
417		}
418		if (end != round_page(end)) {
419			vm_offset_t t = trunc_page(end);
420			error = freebsd32_mmap_partial(td, t, end,
421						  prot, fd,
422						  pos + t - start);
423			end = trunc_page(end);
424		}
425		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
426			/*
427			 * We can't map this region at all. The specified
428			 * address doesn't have the same alignment as the file
429			 * position. Fake the mapping by simply reading the
430			 * entire region into memory. First we need to make
431			 * sure the region exists.
432			 */
433			vm_map_t map;
434			struct pread_args r;
435			int rv;
436
437			prot |= VM_PROT_WRITE;
438			map = &td->td_proc->p_vmspace->vm_map;
439			rv = vm_map_remove(map, start, end);
440			if (rv != KERN_SUCCESS) {
441				mtx_unlock(&Giant);
442				return (EINVAL);
443			}
444			rv = vm_map_find(map, 0, 0,
445					 &start, end - start, FALSE,
446					 prot, VM_PROT_ALL, 0);
447			mtx_unlock(&Giant);
448			if (rv != KERN_SUCCESS)
449				return (EINVAL);
450			r.fd = fd;
451			r.buf = (void *) start;
452			r.nbyte = end - start;
453			r.offset = pos;
454			error = pread(td, &r);
455			if (error)
456				return (error);
457
458			td->td_retval[0] = addr;
459			return (0);
460		}
461		mtx_unlock(&Giant);
462		if (end == start) {
463			/*
464			 * After dealing with the ragged ends, there
465			 * might be none left.
466			 */
467			td->td_retval[0] = addr;
468			return (0);
469		}
470		addr = start;
471		len = end - start;
472	}
473#endif
474
475	ap.addr = (void *) addr;
476	ap.len = len;
477	ap.prot = prot;
478	ap.flags = flags;
479	ap.fd = fd;
480	ap.pos = pos;
481
482	return (mmap(td, &ap));
483}
484
485struct itimerval32 {
486	struct timeval32 it_interval;
487	struct timeval32 it_value;
488};
489
490CTASSERT(sizeof(struct itimerval32) == 16);
491
492int
493freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
494{
495	struct itimerval itv, oitv, *itvp;
496	struct itimerval32 i32;
497	int error;
498
499	if (uap->itv != NULL) {
500		error = copyin(uap->itv, &i32, sizeof(i32));
501		if (error)
502			return (error);
503		TV_CP(i32, itv, it_interval);
504		TV_CP(i32, itv, it_value);
505		itvp = &itv;
506	} else
507		itvp = NULL;
508	error = kern_setitimer(td, uap->which, itvp, &oitv);
509	if (error || uap->oitv == NULL)
510		return (error);
511	TV_CP(oitv, i32, it_interval);
512	TV_CP(oitv, i32, it_value);
513	return (copyout(&i32, uap->oitv, sizeof(i32)));
514}
515
516int
517freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
518{
519	struct itimerval itv;
520	struct itimerval32 i32;
521	int error;
522
523	error = kern_getitimer(td, uap->which, &itv);
524	if (error || uap->itv == NULL)
525		return (error);
526	TV_CP(itv, i32, it_interval);
527	TV_CP(itv, i32, it_value);
528	return (copyout(&i32, uap->itv, sizeof(i32)));
529}
530
531int
532freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
533{
534	struct timeval32 tv32;
535	struct timeval tv, *tvp;
536	int error;
537
538	if (uap->tv != NULL) {
539		error = copyin(uap->tv, &tv32, sizeof(tv32));
540		if (error)
541			return (error);
542		CP(tv32, tv, tv_sec);
543		CP(tv32, tv, tv_usec);
544		tvp = &tv;
545	} else
546		tvp = NULL;
547	/*
548	 * XXX big-endian needs to convert the fd_sets too.
549	 * XXX Do pointers need PTRIN()?
550	 */
551	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
552}
553
554struct kevent32 {
555	u_int32_t	ident;		/* identifier for this event */
556	short		filter;		/* filter for event */
557	u_short		flags;
558	u_int		fflags;
559	int32_t		data;
560	u_int32_t	udata;		/* opaque user data identifier */
561};
562
563CTASSERT(sizeof(struct kevent32) == 20);
564static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
565static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
566
567/*
568 * Copy 'count' items into the destination list pointed to by uap->eventlist.
569 */
570static int
571freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
572{
573	struct freebsd32_kevent_args *uap;
574	struct kevent32	ks32[KQ_NEVENTS];
575	int i, error = 0;
576
577	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
578	uap = (struct freebsd32_kevent_args *)arg;
579
580	for (i = 0; i < count; i++) {
581		CP(kevp[i], ks32[i], ident);
582		CP(kevp[i], ks32[i], filter);
583		CP(kevp[i], ks32[i], flags);
584		CP(kevp[i], ks32[i], fflags);
585		CP(kevp[i], ks32[i], data);
586		PTROUT_CP(kevp[i], ks32[i], udata);
587	}
588	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
589	if (error == 0)
590		uap->eventlist += count;
591	return (error);
592}
593
594/*
595 * Copy 'count' items from the list pointed to by uap->changelist.
596 */
597static int
598freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
599{
600	struct freebsd32_kevent_args *uap;
601	struct kevent32	ks32[KQ_NEVENTS];
602	int i, error = 0;
603
604	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
605	uap = (struct freebsd32_kevent_args *)arg;
606
607	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
608	if (error)
609		goto done;
610	uap->changelist += count;
611
612	for (i = 0; i < count; i++) {
613		CP(ks32[i], kevp[i], ident);
614		CP(ks32[i], kevp[i], filter);
615		CP(ks32[i], kevp[i], flags);
616		CP(ks32[i], kevp[i], fflags);
617		CP(ks32[i], kevp[i], data);
618		PTRIN_CP(ks32[i], kevp[i], udata);
619	}
620done:
621	return (error);
622}
623
624int
625freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
626{
627	struct timespec32 ts32;
628	struct timespec ts, *tsp;
629	struct kevent_copyops k_ops = { uap,
630					freebsd32_kevent_copyout,
631					freebsd32_kevent_copyin};
632	int error;
633
634
635	if (uap->timeout) {
636		error = copyin(uap->timeout, &ts32, sizeof(ts32));
637		if (error)
638			return (error);
639		CP(ts32, ts, tv_sec);
640		CP(ts32, ts, tv_nsec);
641		tsp = &ts;
642	} else
643		tsp = NULL;
644	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
645	    &k_ops, tsp);
646	return (error);
647}
648
649int
650freebsd32_gettimeofday(struct thread *td,
651		       struct freebsd32_gettimeofday_args *uap)
652{
653	struct timeval atv;
654	struct timeval32 atv32;
655	struct timezone rtz;
656	int error = 0;
657
658	if (uap->tp) {
659		microtime(&atv);
660		CP(atv, atv32, tv_sec);
661		CP(atv, atv32, tv_usec);
662		error = copyout(&atv32, uap->tp, sizeof (atv32));
663	}
664	if (error == 0 && uap->tzp != NULL) {
665		rtz.tz_minuteswest = tz_minuteswest;
666		rtz.tz_dsttime = tz_dsttime;
667		error = copyout(&rtz, uap->tzp, sizeof (rtz));
668	}
669	return (error);
670}
671
672int
673freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
674{
675	struct rusage32 s32;
676	struct rusage s;
677	int error;
678
679	error = kern_getrusage(td, uap->who, &s);
680	if (error)
681		return (error);
682	if (uap->rusage != NULL) {
683		TV_CP(s, s32, ru_utime);
684		TV_CP(s, s32, ru_stime);
685		CP(s, s32, ru_maxrss);
686		CP(s, s32, ru_ixrss);
687		CP(s, s32, ru_idrss);
688		CP(s, s32, ru_isrss);
689		CP(s, s32, ru_minflt);
690		CP(s, s32, ru_majflt);
691		CP(s, s32, ru_nswap);
692		CP(s, s32, ru_inblock);
693		CP(s, s32, ru_oublock);
694		CP(s, s32, ru_msgsnd);
695		CP(s, s32, ru_msgrcv);
696		CP(s, s32, ru_nsignals);
697		CP(s, s32, ru_nvcsw);
698		CP(s, s32, ru_nivcsw);
699		error = copyout(&s32, uap->rusage, sizeof(s32));
700	}
701	return (error);
702}
703
704struct iovec32 {
705	u_int32_t iov_base;
706	int	iov_len;
707};
708
709CTASSERT(sizeof(struct iovec32) == 8);
710
711static int
712freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
713{
714	struct iovec32 iov32;
715	struct iovec *iov;
716	struct uio *uio;
717	u_int iovlen;
718	int error, i;
719
720	*uiop = NULL;
721	if (iovcnt > UIO_MAXIOV)
722		return (EINVAL);
723	iovlen = iovcnt * sizeof(struct iovec);
724	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
725	iov = (struct iovec *)(uio + 1);
726	for (i = 0; i < iovcnt; i++) {
727		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
728		if (error) {
729			free(uio, M_IOV);
730			return (error);
731		}
732		iov[i].iov_base = PTRIN(iov32.iov_base);
733		iov[i].iov_len = iov32.iov_len;
734	}
735	uio->uio_iov = iov;
736	uio->uio_iovcnt = iovcnt;
737	uio->uio_segflg = UIO_USERSPACE;
738	uio->uio_offset = -1;
739	uio->uio_resid = 0;
740	for (i = 0; i < iovcnt; i++) {
741		if (iov->iov_len > INT_MAX - uio->uio_resid) {
742			free(uio, M_IOV);
743			return (EINVAL);
744		}
745		uio->uio_resid += iov->iov_len;
746		iov++;
747	}
748	*uiop = uio;
749	return (0);
750}
751
752int
753freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
754{
755	struct uio *auio;
756	int error;
757
758	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
759	if (error)
760		return (error);
761	error = kern_readv(td, uap->fd, auio);
762	free(auio, M_IOV);
763	return (error);
764}
765
766int
767freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
768{
769	struct uio *auio;
770	int error;
771
772	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
773	if (error)
774		return (error);
775	error = kern_writev(td, uap->fd, auio);
776	free(auio, M_IOV);
777	return (error);
778}
779
780int
781freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
782{
783	struct uio *auio;
784	int error;
785
786	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
787	if (error)
788		return (error);
789	error = kern_preadv(td, uap->fd, auio, uap->offset);
790	free(auio, M_IOV);
791	return (error);
792}
793
794int
795freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
796{
797	struct uio *auio;
798	int error;
799
800	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
801	if (error)
802		return (error);
803	error = kern_pwritev(td, uap->fd, auio, uap->offset);
804	free(auio, M_IOV);
805	return (error);
806}
807
808static int
809freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
810    int error)
811{
812	struct iovec32 iov32;
813	struct iovec *iov;
814	u_int iovlen;
815	int i;
816
817	*iovp = NULL;
818	if (iovcnt > UIO_MAXIOV)
819		return (error);
820	iovlen = iovcnt * sizeof(struct iovec);
821	iov = malloc(iovlen, M_IOV, M_WAITOK);
822	for (i = 0; i < iovcnt; i++) {
823		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
824		if (error) {
825			free(iov, M_IOV);
826			return (error);
827		}
828		iov[i].iov_base = PTRIN(iov32.iov_base);
829		iov[i].iov_len = iov32.iov_len;
830	}
831	*iovp = iov;
832	return (0);
833}
834
835static int
836freebsd32_copyoutiov(struct iovec *iov, u_int iovcnt, struct iovec32 *iovp,
837    int error)
838{
839	struct iovec32 iov32;
840	int i;
841
842	if (iovcnt > UIO_MAXIOV)
843		return (error);
844	for (i = 0; i < iovcnt; i++) {
845		iov32.iov_base = PTROUT(iov[i].iov_base);
846		iov32.iov_len = iov[i].iov_len;
847		error = copyout(&iov32, &iovp[i], sizeof(iov32));
848		if (error)
849			return (error);
850	}
851	return (0);
852}
853
854
855struct msghdr32 {
856	u_int32_t	 msg_name;
857	socklen_t	 msg_namelen;
858	u_int32_t	 msg_iov;
859	int		 msg_iovlen;
860	u_int32_t	 msg_control;
861	socklen_t	 msg_controllen;
862	int		 msg_flags;
863};
864CTASSERT(sizeof(struct msghdr32) == 28);
865
866static int
867freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
868{
869	struct msghdr32 m32;
870	int error;
871
872	error = copyin(msg32, &m32, sizeof(m32));
873	if (error)
874		return (error);
875	msg->msg_name = PTRIN(m32.msg_name);
876	msg->msg_namelen = m32.msg_namelen;
877	msg->msg_iov = PTRIN(m32.msg_iov);
878	msg->msg_iovlen = m32.msg_iovlen;
879	msg->msg_control = PTRIN(m32.msg_control);
880	msg->msg_controllen = m32.msg_controllen;
881	msg->msg_flags = m32.msg_flags;
882	return (0);
883}
884
885static int
886freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
887{
888	struct msghdr32 m32;
889	int error;
890
891	m32.msg_name = PTROUT(msg->msg_name);
892	m32.msg_namelen = msg->msg_namelen;
893	m32.msg_iov = PTROUT(msg->msg_iov);
894	m32.msg_iovlen = msg->msg_iovlen;
895	m32.msg_control = PTROUT(msg->msg_control);
896	m32.msg_controllen = msg->msg_controllen;
897	m32.msg_flags = msg->msg_flags;
898	error = copyout(&m32, msg32, sizeof(m32));
899	return (error);
900}
901
902#define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
903#define FREEBSD32_ALIGN(p)	\
904	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
905#define	FREEBSD32_CMSG_SPACE(l)	\
906	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
907
908#define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
909				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
910static int
911freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
912{
913	struct cmsghdr *cm;
914	void *data;
915	socklen_t clen, datalen;
916	int error;
917	caddr_t ctlbuf;
918	int len, maxlen, copylen;
919	struct mbuf *m;
920	error = 0;
921
922	len    = msg->msg_controllen;
923	maxlen = msg->msg_controllen;
924	msg->msg_controllen = 0;
925
926	m = control;
927	ctlbuf = msg->msg_control;
928
929	while (m && len > 0) {
930		cm = mtod(m, struct cmsghdr *);
931		clen = m->m_len;
932
933		while (cm != NULL) {
934
935			if (sizeof(struct cmsghdr) > clen ||
936			    cm->cmsg_len > clen) {
937				error = EINVAL;
938				break;
939			}
940
941			data   = CMSG_DATA(cm);
942			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
943
944			/* Adjust message length */
945			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
946			    datalen;
947
948
949			/* Copy cmsghdr */
950			copylen = sizeof(struct cmsghdr);
951			if (len < copylen) {
952				msg->msg_flags |= MSG_CTRUNC;
953				copylen = len;
954			}
955
956			error = copyout(cm,ctlbuf,copylen);
957			if (error)
958				goto exit;
959
960			ctlbuf += FREEBSD32_ALIGN(copylen);
961			len    -= FREEBSD32_ALIGN(copylen);
962
963			if (len <= 0)
964				break;
965
966			/* Copy data */
967			copylen = datalen;
968			if (len < copylen) {
969				msg->msg_flags |= MSG_CTRUNC;
970				copylen = len;
971			}
972
973			error = copyout(data,ctlbuf,copylen);
974			if (error)
975				goto exit;
976
977			ctlbuf += FREEBSD32_ALIGN(copylen);
978			len    -= FREEBSD32_ALIGN(copylen);
979
980			if (CMSG_SPACE(datalen) < clen) {
981				clen -= CMSG_SPACE(datalen);
982				cm = (struct cmsghdr *)
983					((caddr_t)cm + CMSG_SPACE(datalen));
984			} else {
985				clen = 0;
986				cm = NULL;
987			}
988		}
989		m = m->m_next;
990	}
991
992	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
993
994exit:
995	return (error);
996
997}
998
999int
1000freebsd32_recvmsg(td, uap)
1001	struct thread *td;
1002	struct freebsd32_recvmsg_args /* {
1003		int	s;
1004		struct	msghdr32 *msg;
1005		int	flags;
1006	} */ *uap;
1007{
1008	struct msghdr msg;
1009	struct msghdr32 m32;
1010	struct iovec *uiov, *iov;
1011	struct mbuf *control = NULL;
1012	struct mbuf **controlp;
1013
1014	int error;
1015	error = copyin(uap->msg, &m32, sizeof(m32));
1016	if (error)
1017		return (error);
1018	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1019	if (error)
1020		return (error);
1021	error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov,
1022	    m32.msg_iovlen, &iov, EMSGSIZE);
1023	if (error)
1024		return (error);
1025	msg.msg_flags = uap->flags;
1026	uiov = msg.msg_iov;
1027	msg.msg_iov = iov;
1028
1029	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1030	error = kern_recvit(td, uap->s, &msg, NULL, UIO_USERSPACE, controlp);
1031	if (error == 0) {
1032		msg.msg_iov = uiov;
1033
1034		if (control != NULL)
1035			error = freebsd32_copy_msg_out(&msg, control);
1036
1037		if (error == 0)
1038			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1039
1040		if (error == 0)
1041			error = freebsd32_copyoutiov(iov, m32.msg_iovlen,
1042			    (struct iovec32 *)(uintptr_t)m32.msg_iov, EMSGSIZE);
1043	}
1044	free(iov, M_IOV);
1045
1046	if (control != NULL)
1047		m_freem(control);
1048
1049	return (error);
1050}
1051
1052
1053static int
1054freebsd32_convert_msg_in(struct mbuf **controlp)
1055{
1056	struct mbuf *control = *controlp;
1057	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1058	void *data;
1059	socklen_t clen = control->m_len, datalen;
1060	int error;
1061
1062	error = 0;
1063	*controlp = NULL;
1064
1065	while (cm != NULL) {
1066		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1067			error = EINVAL;
1068			break;
1069		}
1070
1071		data = FREEBSD32_CMSG_DATA(cm);
1072		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1073
1074		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1075		    cm->cmsg_level);
1076		controlp = &(*controlp)->m_next;
1077
1078		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1079			clen -= FREEBSD32_CMSG_SPACE(datalen);
1080			cm = (struct cmsghdr *)
1081				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1082		} else {
1083			clen = 0;
1084			cm = NULL;
1085		}
1086	}
1087
1088	m_freem(control);
1089	return (error);
1090}
1091
1092
1093int
1094freebsd32_sendmsg(struct thread *td,
1095		  struct freebsd32_sendmsg_args *uap)
1096{
1097	struct msghdr msg;
1098	struct msghdr32 m32;
1099	struct iovec *iov;
1100	struct mbuf *control = NULL;
1101	struct sockaddr *to = NULL;
1102	int error;
1103
1104	error = copyin(uap->msg, &m32, sizeof(m32));
1105	if (error)
1106		return (error);
1107	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1108	if (error)
1109		return (error);
1110	error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov,
1111	    m32.msg_iovlen, &iov, EMSGSIZE);
1112	if (error)
1113		return (error);
1114	msg.msg_iov = iov;
1115	if (msg.msg_name != NULL) {
1116		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1117		if (error) {
1118			to = NULL;
1119			goto out;
1120		}
1121		msg.msg_name = to;
1122	}
1123
1124	if (msg.msg_control) {
1125		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1126			error = EINVAL;
1127			goto out;
1128		}
1129
1130		error = sockargs(&control, msg.msg_control,
1131		    msg.msg_controllen, MT_CONTROL);
1132		if (error)
1133			goto out;
1134
1135		error = freebsd32_convert_msg_in(&control);
1136		if (error)
1137			goto out;
1138	}
1139
1140	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1141	    UIO_USERSPACE);
1142
1143out:
1144	free(iov, M_IOV);
1145	if (to)
1146		free(to, M_SONAME);
1147	return (error);
1148}
1149
1150int
1151freebsd32_recvfrom(struct thread *td,
1152		   struct freebsd32_recvfrom_args *uap)
1153{
1154	struct msghdr msg;
1155	struct iovec aiov;
1156	int error;
1157
1158	if (uap->fromlenaddr) {
1159		error = copyin((void *)(uintptr_t)uap->fromlenaddr,
1160		    &msg.msg_namelen, sizeof(msg.msg_namelen));
1161		if (error)
1162			return (error);
1163	} else {
1164		msg.msg_namelen = 0;
1165	}
1166
1167	msg.msg_name = (void *)(uintptr_t)uap->from;
1168	msg.msg_iov = &aiov;
1169	msg.msg_iovlen = 1;
1170	aiov.iov_base = (void *)(uintptr_t)uap->buf;
1171	aiov.iov_len = uap->len;
1172	msg.msg_control = 0;
1173	msg.msg_flags = uap->flags;
1174	error = kern_recvit(td, uap->s, &msg,
1175	    (void *)(uintptr_t)uap->fromlenaddr, UIO_USERSPACE, NULL);
1176	return (error);
1177}
1178
1179int
1180freebsd32_settimeofday(struct thread *td,
1181		       struct freebsd32_settimeofday_args *uap)
1182{
1183	struct timeval32 tv32;
1184	struct timeval tv, *tvp;
1185	struct timezone tz, *tzp;
1186	int error;
1187
1188	if (uap->tv) {
1189		error = copyin(uap->tv, &tv32, sizeof(tv32));
1190		if (error)
1191			return (error);
1192		CP(tv32, tv, tv_sec);
1193		CP(tv32, tv, tv_usec);
1194		tvp = &tv;
1195	} else
1196		tvp = NULL;
1197	if (uap->tzp) {
1198		error = copyin(uap->tzp, &tz, sizeof(tz));
1199		if (error)
1200			return (error);
1201		tzp = &tz;
1202	} else
1203		tzp = NULL;
1204	return (kern_settimeofday(td, tvp, tzp));
1205}
1206
1207int
1208freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1209{
1210	struct timeval32 s32[2];
1211	struct timeval s[2], *sp;
1212	int error;
1213
1214	if (uap->tptr != NULL) {
1215		error = copyin(uap->tptr, s32, sizeof(s32));
1216		if (error)
1217			return (error);
1218		CP(s32[0], s[0], tv_sec);
1219		CP(s32[0], s[0], tv_usec);
1220		CP(s32[1], s[1], tv_sec);
1221		CP(s32[1], s[1], tv_usec);
1222		sp = s;
1223	} else
1224		sp = NULL;
1225	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1226}
1227
1228int
1229freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
1230{
1231	struct timeval32 s32[2];
1232	struct timeval s[2], *sp;
1233	int error;
1234
1235	if (uap->tptr != NULL) {
1236		error = copyin(uap->tptr, s32, sizeof(s32));
1237		if (error)
1238			return (error);
1239		CP(s32[0], s[0], tv_sec);
1240		CP(s32[0], s[0], tv_usec);
1241		CP(s32[1], s[1], tv_sec);
1242		CP(s32[1], s[1], tv_usec);
1243		sp = s;
1244	} else
1245		sp = NULL;
1246	return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1247}
1248
1249int
1250freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1251{
1252	struct timeval32 s32[2];
1253	struct timeval s[2], *sp;
1254	int error;
1255
1256	if (uap->tptr != NULL) {
1257		error = copyin(uap->tptr, s32, sizeof(s32));
1258		if (error)
1259			return (error);
1260		CP(s32[0], s[0], tv_sec);
1261		CP(s32[0], s[0], tv_usec);
1262		CP(s32[1], s[1], tv_sec);
1263		CP(s32[1], s[1], tv_usec);
1264		sp = s;
1265	} else
1266		sp = NULL;
1267	return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1268}
1269
1270
1271int
1272freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1273{
1274	struct timeval32 tv32;
1275	struct timeval delta, olddelta, *deltap;
1276	int error;
1277
1278	if (uap->delta) {
1279		error = copyin(uap->delta, &tv32, sizeof(tv32));
1280		if (error)
1281			return (error);
1282		CP(tv32, delta, tv_sec);
1283		CP(tv32, delta, tv_usec);
1284		deltap = &delta;
1285	} else
1286		deltap = NULL;
1287	error = kern_adjtime(td, deltap, &olddelta);
1288	if (uap->olddelta && error == 0) {
1289		CP(olddelta, tv32, tv_sec);
1290		CP(olddelta, tv32, tv_usec);
1291		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1292	}
1293	return (error);
1294}
1295
1296#ifdef COMPAT_FREEBSD4
1297int
1298freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1299{
1300	struct statfs32 s32;
1301	struct statfs s;
1302	int error;
1303
1304	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1305	if (error)
1306		return (error);
1307	copy_statfs(&s, &s32);
1308	return (copyout(&s32, uap->buf, sizeof(s32)));
1309}
1310#endif
1311
1312#ifdef COMPAT_FREEBSD4
1313int
1314freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1315{
1316	struct statfs32 s32;
1317	struct statfs s;
1318	int error;
1319
1320	error = kern_fstatfs(td, uap->fd, &s);
1321	if (error)
1322		return (error);
1323	copy_statfs(&s, &s32);
1324	return (copyout(&s32, uap->buf, sizeof(s32)));
1325}
1326#endif
1327
1328#ifdef COMPAT_FREEBSD4
1329int
1330freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1331{
1332	struct statfs32 s32;
1333	struct statfs s;
1334	fhandle_t fh;
1335	int error;
1336
1337	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1338		return (error);
1339	error = kern_fhstatfs(td, fh, &s);
1340	if (error)
1341		return (error);
1342	copy_statfs(&s, &s32);
1343	return (copyout(&s32, uap->buf, sizeof(s32)));
1344}
1345#endif
1346
1347int
1348freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1349{
1350	/*
1351	 * Vector through to semsys if it is loaded.
1352	 */
1353	return sysent[SYS_semsys].sy_call(td, uap);
1354}
1355
1356int
1357freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1358{
1359	/*
1360	 * Vector through to msgsys if it is loaded.
1361	 */
1362	return sysent[SYS_msgsys].sy_call(td, uap);
1363}
1364
1365int
1366freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1367{
1368	/*
1369	 * Vector through to shmsys if it is loaded.
1370	 */
1371	return sysent[SYS_shmsys].sy_call(td, uap);
1372}
1373
1374int
1375freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1376{
1377	struct pread_args ap;
1378
1379	ap.fd = uap->fd;
1380	ap.buf = uap->buf;
1381	ap.nbyte = uap->nbyte;
1382	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1383	return (pread(td, &ap));
1384}
1385
1386int
1387freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1388{
1389	struct pwrite_args ap;
1390
1391	ap.fd = uap->fd;
1392	ap.buf = uap->buf;
1393	ap.nbyte = uap->nbyte;
1394	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1395	return (pwrite(td, &ap));
1396}
1397
1398int
1399freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1400{
1401	int error;
1402	struct lseek_args ap;
1403	off_t pos;
1404
1405	ap.fd = uap->fd;
1406	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1407	ap.whence = uap->whence;
1408	error = lseek(td, &ap);
1409	/* Expand the quad return into two parts for eax and edx */
1410	pos = *(off_t *)(td->td_retval);
1411	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1412	td->td_retval[1] = pos >> 32;		/* %edx */
1413	return error;
1414}
1415
1416int
1417freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1418{
1419	struct truncate_args ap;
1420
1421	ap.path = uap->path;
1422	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1423	return (truncate(td, &ap));
1424}
1425
1426int
1427freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1428{
1429	struct ftruncate_args ap;
1430
1431	ap.fd = uap->fd;
1432	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1433	return (ftruncate(td, &ap));
1434}
1435
1436struct sf_hdtr32 {
1437	uint32_t headers;
1438	int hdr_cnt;
1439	uint32_t trailers;
1440	int trl_cnt;
1441};
1442
1443static int
1444freebsd32_do_sendfile(struct thread *td,
1445    struct freebsd32_sendfile_args *uap, int compat)
1446{
1447	struct sendfile_args ap;
1448	struct sf_hdtr32 hdtr32;
1449	struct sf_hdtr hdtr;
1450	struct uio *hdr_uio, *trl_uio;
1451	struct iovec32 *iov32;
1452	int error;
1453
1454	hdr_uio = trl_uio = NULL;
1455
1456	ap.fd = uap->fd;
1457	ap.s = uap->s;
1458	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1459	ap.nbytes = uap->nbytes;
1460	ap.hdtr = (struct sf_hdtr *)uap->hdtr;		/* XXX not used */
1461	ap.sbytes = uap->sbytes;
1462	ap.flags = uap->flags;
1463
1464	if (uap->hdtr != NULL) {
1465		error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
1466		if (error)
1467			goto out;
1468		PTRIN_CP(hdtr32, hdtr, headers);
1469		CP(hdtr32, hdtr, hdr_cnt);
1470		PTRIN_CP(hdtr32, hdtr, trailers);
1471		CP(hdtr32, hdtr, trl_cnt);
1472
1473		if (hdtr.headers != NULL) {
1474			iov32 = (struct iovec32 *)(uintptr_t)hdtr32.headers;
1475			error = freebsd32_copyinuio(iov32,
1476			    hdtr32.hdr_cnt, &hdr_uio);
1477			if (error)
1478				goto out;
1479		}
1480		if (hdtr.trailers != NULL) {
1481			iov32 = (struct iovec32 *)(uintptr_t)hdtr32.trailers;
1482			error = freebsd32_copyinuio(iov32,
1483			    hdtr32.trl_cnt, &trl_uio);
1484			if (error)
1485				goto out;
1486		}
1487	}
1488
1489	error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
1490out:
1491	if (hdr_uio)
1492		free(hdr_uio, M_IOV);
1493	if (trl_uio)
1494		free(trl_uio, M_IOV);
1495	return (error);
1496}
1497
1498#ifdef COMPAT_FREEBSD4
1499int
1500freebsd4_freebsd32_sendfile(struct thread *td,
1501    struct freebsd4_freebsd32_sendfile_args *uap)
1502{
1503	return (freebsd32_do_sendfile(td,
1504	    (struct freebsd32_sendfile_args *)uap, 1));
1505}
1506#endif
1507
1508int
1509freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1510{
1511
1512	return (freebsd32_do_sendfile(td, uap, 0));
1513}
1514
1515struct stat32 {
1516	dev_t	st_dev;
1517	ino_t	st_ino;
1518	mode_t	st_mode;
1519	nlink_t	st_nlink;
1520	uid_t	st_uid;
1521	gid_t	st_gid;
1522	dev_t	st_rdev;
1523	struct timespec32 st_atimespec;
1524	struct timespec32 st_mtimespec;
1525	struct timespec32 st_ctimespec;
1526	off_t	st_size;
1527	int64_t	st_blocks;
1528	u_int32_t st_blksize;
1529	u_int32_t st_flags;
1530	u_int32_t st_gen;
1531	struct timespec32 st_birthtimespec;
1532	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1533	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1534};
1535
1536
1537CTASSERT(sizeof(struct stat32) == 96);
1538
1539static void
1540copy_stat( struct stat *in, struct stat32 *out)
1541{
1542	CP(*in, *out, st_dev);
1543	CP(*in, *out, st_ino);
1544	CP(*in, *out, st_mode);
1545	CP(*in, *out, st_nlink);
1546	CP(*in, *out, st_uid);
1547	CP(*in, *out, st_gid);
1548	CP(*in, *out, st_rdev);
1549	TS_CP(*in, *out, st_atimespec);
1550	TS_CP(*in, *out, st_mtimespec);
1551	TS_CP(*in, *out, st_ctimespec);
1552	CP(*in, *out, st_size);
1553	CP(*in, *out, st_blocks);
1554	CP(*in, *out, st_blksize);
1555	CP(*in, *out, st_flags);
1556	CP(*in, *out, st_gen);
1557}
1558
1559int
1560freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1561{
1562	struct stat sb;
1563	struct stat32 sb32;
1564	int error;
1565
1566	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1567	if (error)
1568		return (error);
1569	copy_stat(&sb, &sb32);
1570	error = copyout(&sb32, uap->ub, sizeof (sb32));
1571	return (error);
1572}
1573
1574int
1575freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1576{
1577	struct stat ub;
1578	struct stat32 ub32;
1579	int error;
1580
1581	error = kern_fstat(td, uap->fd, &ub);
1582	if (error)
1583		return (error);
1584	copy_stat(&ub, &ub32);
1585	error = copyout(&ub32, uap->ub, sizeof(ub32));
1586	return (error);
1587}
1588
1589int
1590freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1591{
1592	struct stat sb;
1593	struct stat32 sb32;
1594	int error;
1595
1596	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1597	if (error)
1598		return (error);
1599	copy_stat(&sb, &sb32);
1600	error = copyout(&sb32, uap->ub, sizeof (sb32));
1601	return (error);
1602}
1603
1604/*
1605 * MPSAFE
1606 */
1607int
1608freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1609{
1610	int error, name[CTL_MAXNAME];
1611	size_t j, oldlen;
1612
1613	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1614		return (EINVAL);
1615 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1616 	if (error)
1617		return (error);
1618	mtx_lock(&Giant);
1619	if (uap->oldlenp)
1620		oldlen = fuword32(uap->oldlenp);
1621	else
1622		oldlen = 0;
1623	error = userland_sysctl(td, name, uap->namelen,
1624		uap->old, &oldlen, 1,
1625		uap->new, uap->newlen, &j, SCTL_MASK32);
1626	if (error && error != ENOMEM)
1627		goto done2;
1628	if (uap->oldlenp)
1629		suword32(uap->oldlenp, j);
1630done2:
1631	mtx_unlock(&Giant);
1632	return (error);
1633}
1634
1635struct sigaction32 {
1636	u_int32_t	sa_u;
1637	int		sa_flags;
1638	sigset_t	sa_mask;
1639};
1640
1641CTASSERT(sizeof(struct sigaction32) == 24);
1642
1643int
1644freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1645{
1646	struct sigaction32 s32;
1647	struct sigaction sa, osa, *sap;
1648	int error;
1649
1650	if (uap->act) {
1651		error = copyin(uap->act, &s32, sizeof(s32));
1652		if (error)
1653			return (error);
1654		sa.sa_handler = PTRIN(s32.sa_u);
1655		CP(s32, sa, sa_flags);
1656		CP(s32, sa, sa_mask);
1657		sap = &sa;
1658	} else
1659		sap = NULL;
1660	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1661	if (error == 0 && uap->oact != NULL) {
1662		s32.sa_u = PTROUT(osa.sa_handler);
1663		CP(osa, s32, sa_flags);
1664		CP(osa, s32, sa_mask);
1665		error = copyout(&s32, uap->oact, sizeof(s32));
1666	}
1667	return (error);
1668}
1669
1670#ifdef COMPAT_FREEBSD4
1671int
1672freebsd4_freebsd32_sigaction(struct thread *td,
1673			     struct freebsd4_freebsd32_sigaction_args *uap)
1674{
1675	struct sigaction32 s32;
1676	struct sigaction sa, osa, *sap;
1677	int error;
1678
1679	if (uap->act) {
1680		error = copyin(uap->act, &s32, sizeof(s32));
1681		if (error)
1682			return (error);
1683		sa.sa_handler = PTRIN(s32.sa_u);
1684		CP(s32, sa, sa_flags);
1685		CP(s32, sa, sa_mask);
1686		sap = &sa;
1687	} else
1688		sap = NULL;
1689	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1690	if (error == 0 && uap->oact != NULL) {
1691		s32.sa_u = PTROUT(osa.sa_handler);
1692		CP(osa, s32, sa_flags);
1693		CP(osa, s32, sa_mask);
1694		error = copyout(&s32, uap->oact, sizeof(s32));
1695	}
1696	return (error);
1697}
1698#endif
1699
1700#ifdef COMPAT_43
1701struct osigaction32 {
1702	u_int32_t	sa_u;
1703	osigset_t	sa_mask;
1704	int		sa_flags;
1705};
1706
1707#define	ONSIG	32
1708
1709int
1710ofreebsd32_sigaction(struct thread *td,
1711			     struct ofreebsd32_sigaction_args *uap)
1712{
1713	struct osigaction32 s32;
1714	struct sigaction sa, osa, *sap;
1715	int error;
1716
1717	if (uap->signum <= 0 || uap->signum >= ONSIG)
1718		return (EINVAL);
1719
1720	if (uap->nsa) {
1721		error = copyin(uap->nsa, &s32, sizeof(s32));
1722		if (error)
1723			return (error);
1724		sa.sa_handler = PTRIN(s32.sa_u);
1725		CP(s32, sa, sa_flags);
1726		OSIG2SIG(s32.sa_mask, sa.sa_mask);
1727		sap = &sa;
1728	} else
1729		sap = NULL;
1730	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1731	if (error == 0 && uap->osa != NULL) {
1732		s32.sa_u = PTROUT(osa.sa_handler);
1733		CP(osa, s32, sa_flags);
1734		SIG2OSIG(osa.sa_mask, s32.sa_mask);
1735		error = copyout(&s32, uap->osa, sizeof(s32));
1736	}
1737	return (error);
1738}
1739
1740int
1741ofreebsd32_sigprocmask(struct thread *td,
1742			       struct ofreebsd32_sigprocmask_args *uap)
1743{
1744	sigset_t set, oset;
1745	int error;
1746
1747	OSIG2SIG(uap->mask, set);
1748	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
1749	SIG2OSIG(oset, td->td_retval[0]);
1750	return (error);
1751}
1752
1753int
1754ofreebsd32_sigpending(struct thread *td,
1755			      struct ofreebsd32_sigpending_args *uap)
1756{
1757	struct proc *p = td->td_proc;
1758	sigset_t siglist;
1759
1760	PROC_LOCK(p);
1761	siglist = p->p_siglist;
1762	SIGSETOR(siglist, td->td_siglist);
1763	PROC_UNLOCK(p);
1764	SIG2OSIG(siglist, td->td_retval[0]);
1765	return (0);
1766}
1767
1768struct sigvec32 {
1769	u_int32_t	sv_handler;
1770	int		sv_mask;
1771	int		sv_flags;
1772};
1773
1774int
1775ofreebsd32_sigvec(struct thread *td,
1776			  struct ofreebsd32_sigvec_args *uap)
1777{
1778	struct sigvec32 vec;
1779	struct sigaction sa, osa, *sap;
1780	int error;
1781
1782	if (uap->signum <= 0 || uap->signum >= ONSIG)
1783		return (EINVAL);
1784
1785	if (uap->nsv) {
1786		error = copyin(uap->nsv, &vec, sizeof(vec));
1787		if (error)
1788			return (error);
1789		sa.sa_handler = PTRIN(vec.sv_handler);
1790		OSIG2SIG(vec.sv_mask, sa.sa_mask);
1791		sa.sa_flags = vec.sv_flags;
1792		sa.sa_flags ^= SA_RESTART;
1793		sap = &sa;
1794	} else
1795		sap = NULL;
1796	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1797	if (error == 0 && uap->osv != NULL) {
1798		vec.sv_handler = PTROUT(osa.sa_handler);
1799		SIG2OSIG(osa.sa_mask, vec.sv_mask);
1800		vec.sv_flags = osa.sa_flags;
1801		vec.sv_flags &= ~SA_NOCLDWAIT;
1802		vec.sv_flags ^= SA_RESTART;
1803		error = copyout(&vec, uap->osv, sizeof(vec));
1804	}
1805	return (error);
1806}
1807
1808int
1809ofreebsd32_sigblock(struct thread *td,
1810			    struct ofreebsd32_sigblock_args *uap)
1811{
1812	struct proc *p = td->td_proc;
1813	sigset_t set;
1814
1815	OSIG2SIG(uap->mask, set);
1816	SIG_CANTMASK(set);
1817	PROC_LOCK(p);
1818	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1819	SIGSETOR(td->td_sigmask, set);
1820	PROC_UNLOCK(p);
1821	return (0);
1822}
1823
1824int
1825ofreebsd32_sigsetmask(struct thread *td,
1826			      struct ofreebsd32_sigsetmask_args *uap)
1827{
1828	struct proc *p = td->td_proc;
1829	sigset_t set;
1830
1831	OSIG2SIG(uap->mask, set);
1832	SIG_CANTMASK(set);
1833	PROC_LOCK(p);
1834	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1835	SIGSETLO(td->td_sigmask, set);
1836	signotify(td);
1837	PROC_UNLOCK(p);
1838	return (0);
1839}
1840
1841int
1842ofreebsd32_sigsuspend(struct thread *td,
1843			      struct ofreebsd32_sigsuspend_args *uap)
1844{
1845	struct proc *p = td->td_proc;
1846	sigset_t mask;
1847
1848	PROC_LOCK(p);
1849	td->td_oldsigmask = td->td_sigmask;
1850	td->td_pflags |= TDP_OLDMASK;
1851	OSIG2SIG(uap->mask, mask);
1852	SIG_CANTMASK(mask);
1853	SIGSETLO(td->td_sigmask, mask);
1854	signotify(td);
1855	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
1856		/* void */;
1857	PROC_UNLOCK(p);
1858	/* always return EINTR rather than ERESTART... */
1859	return (EINTR);
1860}
1861
1862struct sigstack32 {
1863	u_int32_t	ss_sp;
1864	int		ss_onstack;
1865};
1866
1867int
1868ofreebsd32_sigstack(struct thread *td,
1869			    struct ofreebsd32_sigstack_args *uap)
1870{
1871	struct sigstack32 s32;
1872	struct sigstack nss, oss;
1873	int error = 0;
1874
1875	if (uap->nss != NULL) {
1876		error = copyin(uap->nss, &s32, sizeof(s32));
1877		if (error)
1878			return (error);
1879		nss.ss_sp = PTRIN(s32.ss_sp);
1880		CP(s32, nss, ss_onstack);
1881	}
1882	oss.ss_sp = td->td_sigstk.ss_sp;
1883	oss.ss_onstack = sigonstack(cpu_getstack(td));
1884	if (uap->nss != NULL) {
1885		td->td_sigstk.ss_sp = nss.ss_sp;
1886		td->td_sigstk.ss_size = 0;
1887		td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK;
1888		td->td_pflags |= TDP_ALTSTACK;
1889	}
1890	if (uap->oss != NULL) {
1891		s32.ss_sp = PTROUT(oss.ss_sp);
1892		CP(oss, s32, ss_onstack);
1893		error = copyout(&s32, uap->oss, sizeof(s32));
1894	}
1895	return (error);
1896}
1897#endif
1898
1899int
1900freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1901{
1902	struct timespec32 rmt32, rqt32;
1903	struct timespec rmt, rqt;
1904	int error;
1905
1906	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
1907	if (error)
1908		return (error);
1909
1910	CP(rqt32, rqt, tv_sec);
1911	CP(rqt32, rqt, tv_nsec);
1912
1913	if (uap->rmtp &&
1914	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1915		return (EFAULT);
1916	error = kern_nanosleep(td, &rqt, &rmt);
1917	if (error && uap->rmtp) {
1918		int error2;
1919
1920		CP(rmt, rmt32, tv_sec);
1921		CP(rmt, rmt32, tv_nsec);
1922
1923		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
1924		if (error2)
1925			error = error2;
1926	}
1927	return (error);
1928}
1929
1930int
1931freebsd32_clock_gettime(struct thread *td,
1932			struct freebsd32_clock_gettime_args *uap)
1933{
1934	struct timespec	ats;
1935	struct timespec32 ats32;
1936	int error;
1937
1938	error = kern_clock_gettime(td, uap->clock_id, &ats);
1939	if (error == 0) {
1940		CP(ats, ats32, tv_sec);
1941		CP(ats, ats32, tv_nsec);
1942		error = copyout(&ats32, uap->tp, sizeof(ats32));
1943	}
1944	return (error);
1945}
1946
1947int
1948freebsd32_clock_settime(struct thread *td,
1949			struct freebsd32_clock_settime_args *uap)
1950{
1951	struct timespec	ats;
1952	struct timespec32 ats32;
1953	int error;
1954
1955	error = copyin(uap->tp, &ats32, sizeof(ats32));
1956	if (error)
1957		return (error);
1958	CP(ats32, ats, tv_sec);
1959	CP(ats32, ats, tv_nsec);
1960
1961	return (kern_clock_settime(td, uap->clock_id, &ats));
1962}
1963
1964int
1965freebsd32_clock_getres(struct thread *td,
1966		       struct freebsd32_clock_getres_args *uap)
1967{
1968	struct timespec	ts;
1969	struct timespec32 ts32;
1970	int error;
1971
1972	if (uap->tp == NULL)
1973		return (0);
1974	error = kern_clock_getres(td, uap->clock_id, &ts);
1975	if (error == 0) {
1976		CP(ts, ts32, tv_sec);
1977		CP(ts, ts32, tv_nsec);
1978		error = copyout(&ts32, uap->tp, sizeof(ts32));
1979	}
1980	return (error);
1981}
1982
1983#if 0
1984
1985int
1986freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1987{
1988	int error;
1989	struct yyy32 *p32, s32;
1990	struct yyy *p = NULL, s;
1991
1992	if (uap->zzz) {
1993		error = copyin(uap->zzz, &s32, sizeof(s32));
1994		if (error)
1995			return (error);
1996		/* translate in */
1997		p = &s;
1998	}
1999	error = kern_xxx(td, p);
2000	if (error)
2001		return (error);
2002	if (uap->zzz) {
2003		/* translate out */
2004		error = copyout(&s32, p32, sizeof(s32));
2005	}
2006	return (error);
2007}
2008
2009#endif
2010