freebsd32_misc.c revision 146950
16562Sphk/*-
237421Scharnier * Copyright (c) 2002 Doug Rabson
36562Sphk * All rights reserved.
46562Sphk *
53995Spst * Redistribution and use in source and binary forms, with or without
63995Spst * modification, are permitted provided that the following conditions
76562Sphk * are met:
86562Sphk * 1. Redistributions of source code must retain the above copyright
96562Sphk *    notice, this list of conditions and the following disclaimer.
106562Sphk * 2. Redistributions in binary form must reproduce the above copyright
116562Sphk *    notice, this list of conditions and the following disclaimer in the
126562Sphk *    documentation and/or other materials provided with the distribution.
136562Sphk *
146562Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
156562Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
166562Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
176562Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
183995Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
193995Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2037421Scharnier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2137421Scharnier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2250476Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2337421Scharnier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2437421Scharnier * SUCH DAMAGE.
2519168Sbde */
2637421Scharnier
2719168Sbde#include <sys/cdefs.h>
283995Spst__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 146950 2005-06-03 23:15:01Z ps $");
293995Spst
3032074Ssteve#include "opt_compat.h"
3148953Sbillf
3219168Sbde#include <sys/param.h>
333995Spst#include <sys/systm.h>
343995Spst#include <sys/bus.h>
356562Sphk#include <sys/exec.h>
366562Sphk#include <sys/fcntl.h>
373995Spst#include <sys/filedesc.h>
3846226Skris#include <sys/namei.h>
3946226Skris#include <sys/imgact.h>
403995Spst#include <sys/kernel.h>
4152949Sobrien#include <sys/lock.h>
4252949Sobrien#include <sys/malloc.h>
436562Sphk#include <sys/file.h>		/* Must come after sys/malloc.h */
446562Sphk#include <sys/mman.h>
456562Sphk#include <sys/module.h>
466725Sphk#include <sys/mount.h>
4732074Ssteve#include <sys/mutex.h>
483995Spst#include <sys/namei.h>
493995Spst#include <sys/param.h>
503995Spst#include <sys/proc.h>
513995Spst#include <sys/reboot.h>
523995Spst#include <sys/resource.h>
533995Spst#include <sys/resourcevar.h>
543995Spst#include <sys/selinfo.h>
553995Spst#include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
563995Spst#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
573995Spst#include <sys/signal.h>
586562Sphk#include <sys/signalvar.h>
596562Sphk#include <sys/socket.h>
606562Sphk#include <sys/socketvar.h>
616562Sphk#include <sys/stat.h>
623995Spst#include <sys/syscallsubr.h>
6332086Ssteve#include <sys/sysctl.h>
646562Sphk#include <sys/sysent.h>
659489Sphk#include <sys/sysproto.h>
663995Spst#include <sys/systm.h>
6732074Ssteve#include <sys/unistd.h>
6852949Sobrien#include <sys/vnode.h>
6932086Ssteve#include <sys/wait.h>
7032074Ssteve
7132074Ssteve#include <vm/vm.h>
7232074Ssteve#include <vm/vm_kern.h>
7352949Sobrien#include <vm/vm_param.h>
7452949Sobrien#include <vm/pmap.h>
7552949Sobrien#include <vm/vm_map.h>
7632074Ssteve#include <vm/vm_object.h>
7732074Ssteve#include <vm/vm_extern.h>
7832074Ssteve
7932074Ssteve#include <compat/freebsd32/freebsd32_util.h>
806562Sphk#include <compat/freebsd32/freebsd32.h>
8132074Ssteve#include <compat/freebsd32/freebsd32_proto.h>
8232074Ssteve
836562SphkCTASSERT(sizeof(struct timeval32) == 8);
8432074SsteveCTASSERT(sizeof(struct timespec32) == 8);
8532074SsteveCTASSERT(sizeof(struct statfs32) == 256);
8632074SsteveCTASSERT(sizeof(struct rusage32) == 72);
876562Sphk
8832074Ssteveint
8932074Sstevefreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
9032074Ssteve{
9132074Ssteve	int error, status;
9237421Scharnier	struct rusage32 ru32;
9332074Ssteve	struct rusage ru, *rup;
9452949Sobrien
9552949Sobrien	if (uap->rusage != NULL)
9652949Sobrien		rup = &ru;
9752949Sobrien	else
9852949Sobrien		rup = NULL;
9932074Ssteve	error = kern_wait(td, uap->pid, &status, uap->options, rup);
10032074Ssteve	if (error)
10132074Ssteve		return (error);
1026725Sphk	if (uap->status != NULL)
1033995Spst		error = copyout(&status, uap->status, sizeof(status));
1046562Sphk	if (uap->rusage != NULL && error == 0) {
1053995Spst		TV_CP(ru, ru32, ru_utime);
1066562Sphk		TV_CP(ru, ru32, ru_stime);
1076562Sphk		CP(ru, ru32, ru_maxrss);
1083995Spst		CP(ru, ru32, ru_ixrss);
1096562Sphk		CP(ru, ru32, ru_idrss);
1106562Sphk		CP(ru, ru32, ru_isrss);
1116562Sphk		CP(ru, ru32, ru_minflt);
1123995Spst		CP(ru, ru32, ru_majflt);
11348953Sbillf		CP(ru, ru32, ru_nswap);
1149489Sphk		CP(ru, ru32, ru_inblock);
1153995Spst		CP(ru, ru32, ru_oublock);
11652949Sobrien		CP(ru, ru32, ru_msgsnd);
11752949Sobrien		CP(ru, ru32, ru_msgrcv);
11852949Sobrien		CP(ru, ru32, ru_nsignals);
11952949Sobrien		CP(ru, ru32, ru_nvcsw);
1203995Spst		CP(ru, ru32, ru_nivcsw);
1216562Sphk		error = copyout(&ru32, uap->rusage, sizeof(ru32));
1226562Sphk	}
1233995Spst	return (error);
1246562Sphk}
1256562Sphk
1263995Spst#ifdef COMPAT_FREEBSD4
1276562Sphkstatic void
1286562Sphkcopy_statfs(struct statfs *in, struct statfs32 *out)
1296725Sphk{
1306562Sphk	CP(*in, *out, f_bsize);
1319489Sphk	CP(*in, *out, f_iosize);
1323995Spst	CP(*in, *out, f_blocks);
1336562Sphk	CP(*in, *out, f_bfree);
1346562Sphk	CP(*in, *out, f_bavail);
13521763Sphk	CP(*in, *out, f_files);
13646226Skris	CP(*in, *out, f_ffree);
1373995Spst	CP(*in, *out, f_fsid);
1386562Sphk	CP(*in, *out, f_owner);
1396562Sphk	CP(*in, *out, f_type);
1406562Sphk	CP(*in, *out, f_flags);
1413995Spst	CP(*in, *out, f_flags);
1426562Sphk	CP(*in, *out, f_syncwrites);
1436562Sphk	CP(*in, *out, f_asyncwrites);
1443995Spst	bcopy(in->f_fstypename,
1456562Sphk	      out->f_fstypename, MFSNAMELEN);
1466562Sphk	bcopy(in->f_mntonname,
1476562Sphk	      out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
1486562Sphk	CP(*in, *out, f_syncreads);
1499489Sphk	CP(*in, *out, f_asyncreads);
1503995Spst	bcopy(in->f_mntfromname,
1516562Sphk	      out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
1526562Sphk}
1533995Spst#endif
1546562Sphk
1556562Sphk#ifdef COMPAT_FREEBSD4
1566562Sphkint
1576562Sphkfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
1586562Sphk{
1596562Sphk	int error;
1606562Sphk	caddr_t sg;
1616562Sphk	struct statfs32 *sp32, stat32;
1623995Spst	struct statfs *sp = NULL, stat;
1636562Sphk	int maxcount, count, i;
1646562Sphk
1653995Spst	sp32 = uap->buf;
1666562Sphk	maxcount = uap->bufsize / sizeof(struct statfs32);
1676562Sphk
1683995Spst	if (sp32) {
16932086Ssteve		sg = stackgap_init();
1706562Sphk		sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
1713995Spst		uap->buf = (struct statfs32 *)sp;
1726562Sphk	}
1736562Sphk	error = getfsstat(td, (struct getfsstat_args *) uap);
1746562Sphk	if (sp32 && !error) {
1756562Sphk		count = td->td_retval[0];
1766562Sphk		for (i = 0; i < count; i++) {
1776562Sphk			error = copyin(&sp[i], &stat, sizeof(stat));
1786562Sphk			if (error)
1796562Sphk				return (error);
1806562Sphk			copy_statfs(&stat, &stat32);
1813995Spst			error = copyout(&stat32, &sp32[i], sizeof(stat32));
1823995Spst			if (error)
1833995Spst				return (error);
1846562Sphk		}
1856562Sphk	}
1863995Spst	return (error);
1876562Sphk}
18832086Ssteve#endif
18932086Ssteve
1903995Spststruct sigaltstack32 {
1916562Sphk	u_int32_t	ss_sp;
1926562Sphk	u_int32_t	ss_size;
19332074Ssteve	int		ss_flags;
1949489Sphk};
1953995Spst
1966562SphkCTASSERT(sizeof(struct sigaltstack32) == 12);
19732074Ssteve
19837421Scharnierint
19937421Scharnierfreebsd32_sigaltstack(struct thread *td,
2006562Sphk		      struct freebsd32_sigaltstack_args *uap)
2016725Sphk{
2029489Sphk	struct sigaltstack32 s32;
2033995Spst	struct sigaltstack ss, oss, *ssp;
20432074Ssteve	int error;
20532074Ssteve
20632086Ssteve	if (uap->ss != NULL) {
20732074Ssteve		error = copyin(uap->ss, &s32, sizeof(s32));
20832086Ssteve		if (error)
20932086Ssteve			return (error);
21032074Ssteve		PTRIN_CP(s32, ss, ss_sp);
21132074Ssteve		CP(s32, ss, ss_size);
212		CP(s32, ss, ss_flags);
213		ssp = &ss;
214	} else
215		ssp = NULL;
216	error = kern_sigaltstack(td, ssp, &oss);
217	if (error == 0 && uap->oss != NULL) {
218		PTROUT_CP(oss, s32, ss_sp);
219		CP(oss, s32, ss_size);
220		CP(oss, s32, ss_flags);
221		error = copyout(&s32, uap->oss, sizeof(s32));
222	}
223	return (error);
224}
225
226/*
227 * Custom version of exec_copyin_args() so that we can translate
228 * the pointers.
229 */
230static int
231freebsd32_exec_copyin_args(struct image_args *args, char *fname,
232    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
233{
234	char *argp, *envp;
235	u_int32_t *p32, arg;
236	size_t length;
237	int error;
238
239	bzero(args, sizeof(*args));
240	if (argv == NULL)
241		return (EFAULT);
242
243	/*
244	 * Allocate temporary demand zeroed space for argument and
245	 *	environment strings
246	 */
247	args->buf = (char *) kmem_alloc_wait(exec_map, PATH_MAX + ARG_MAX);
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		return (error);
264
265	/*
266	 * extract arguments first
267	 */
268	p32 = argv;
269	for (;;) {
270		error = copyin(p32++, &arg, sizeof(arg));
271		if (error)
272			return (error);
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				return (E2BIG);
280			else
281				return (error);
282		}
283		args->stringspace -= length;
284		args->endp += length;
285		args->argc++;
286	}
287
288	args->begin_envv = args->endp;
289
290	/*
291	 * extract environment strings
292	 */
293	if (envv) {
294		p32 = envv;
295		for (;;) {
296			error = copyin(p32++, &arg, sizeof(arg));
297			if (error)
298				return (error);
299			if (arg == 0)
300				break;
301			envp = PTRIN(arg);
302			error = copyinstr(envp, args->endp, args->stringspace,
303			    &length);
304			if (error) {
305				if (error == ENAMETOOLONG)
306					return (E2BIG);
307				else
308					return (error);
309			}
310			args->stringspace -= length;
311			args->endp += length;
312			args->envc++;
313		}
314	}
315
316	return (0);
317}
318
319int
320freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
321{
322	struct image_args eargs;
323	int error;
324
325	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
326	    uap->argv, uap->envv);
327	if (error == 0)
328		error = kern_execve(td, &eargs, NULL);
329	exec_free_args(&eargs);
330	return (error);
331}
332
333#ifdef __ia64__
334static int
335freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
336		       int prot, int fd, off_t pos)
337{
338	vm_map_t map;
339	vm_map_entry_t entry;
340	int rv;
341
342	map = &td->td_proc->p_vmspace->vm_map;
343	if (fd != -1)
344		prot |= VM_PROT_WRITE;
345
346	if (vm_map_lookup_entry(map, start, &entry)) {
347		if ((entry->protection & prot) != prot) {
348			rv = vm_map_protect(map,
349					    trunc_page(start),
350					    round_page(end),
351					    entry->protection | prot,
352					    FALSE);
353			if (rv != KERN_SUCCESS)
354				return (EINVAL);
355		}
356	} else {
357		vm_offset_t addr = trunc_page(start);
358		rv = vm_map_find(map, 0, 0,
359				 &addr, PAGE_SIZE, FALSE, prot,
360				 VM_PROT_ALL, 0);
361		if (rv != KERN_SUCCESS)
362			return (EINVAL);
363	}
364
365	if (fd != -1) {
366		struct pread_args r;
367		r.fd = fd;
368		r.buf = (void *) start;
369		r.nbyte = end - start;
370		r.offset = pos;
371		return (pread(td, &r));
372	} else {
373		while (start < end) {
374			subyte((void *) start, 0);
375			start++;
376		}
377		return (0);
378	}
379}
380#endif
381
382int
383freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
384{
385	struct mmap_args ap;
386	vm_offset_t addr = (vm_offset_t) uap->addr;
387	vm_size_t len	 = uap->len;
388	int prot	 = uap->prot;
389	int flags	 = uap->flags;
390	int fd		 = uap->fd;
391	off_t pos	 = (uap->poslo
392			    | ((off_t)uap->poshi << 32));
393#ifdef __ia64__
394	vm_size_t pageoff;
395	int error;
396
397	/*
398	 * Attempt to handle page size hassles.
399	 */
400	pageoff = (pos & PAGE_MASK);
401	if (flags & MAP_FIXED) {
402		vm_offset_t start, end;
403		start = addr;
404		end = addr + len;
405
406		if (start != trunc_page(start)) {
407			error = freebsd32_mmap_partial(td, start,
408						       round_page(start), prot,
409						       fd, pos);
410			if (fd != -1)
411				pos += round_page(start) - start;
412			start = round_page(start);
413		}
414		if (end != round_page(end)) {
415			vm_offset_t t = trunc_page(end);
416			error = freebsd32_mmap_partial(td, t, end,
417						  prot, fd,
418						  pos + t - start);
419			end = trunc_page(end);
420		}
421		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
422			/*
423			 * We can't map this region at all. The specified
424			 * address doesn't have the same alignment as the file
425			 * position. Fake the mapping by simply reading the
426			 * entire region into memory. First we need to make
427			 * sure the region exists.
428			 */
429			vm_map_t map;
430			struct pread_args r;
431			int rv;
432
433			prot |= VM_PROT_WRITE;
434			map = &td->td_proc->p_vmspace->vm_map;
435			rv = vm_map_remove(map, start, end);
436			if (rv != KERN_SUCCESS)
437				return (EINVAL);
438			rv = vm_map_find(map, 0, 0,
439					 &start, end - start, FALSE,
440					 prot, VM_PROT_ALL, 0);
441			if (rv != KERN_SUCCESS)
442				return (EINVAL);
443			r.fd = fd;
444			r.buf = (void *) start;
445			r.nbyte = end - start;
446			r.offset = pos;
447			error = pread(td, &r);
448			if (error)
449				return (error);
450
451			td->td_retval[0] = addr;
452			return (0);
453		}
454		if (end == start) {
455			/*
456			 * After dealing with the ragged ends, there
457			 * might be none left.
458			 */
459			td->td_retval[0] = addr;
460			return (0);
461		}
462		addr = start;
463		len = end - start;
464	}
465#endif
466
467	ap.addr = (void *) addr;
468	ap.len = len;
469	ap.prot = prot;
470	ap.flags = flags;
471	ap.fd = fd;
472	ap.pos = pos;
473
474	return (mmap(td, &ap));
475}
476
477struct itimerval32 {
478	struct timeval32 it_interval;
479	struct timeval32 it_value;
480};
481
482CTASSERT(sizeof(struct itimerval32) == 16);
483
484int
485freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
486{
487	struct itimerval itv, oitv, *itvp;
488	struct itimerval32 i32;
489	int error;
490
491	if (uap->itv != NULL) {
492		error = copyin(uap->itv, &i32, sizeof(i32));
493		if (error)
494			return (error);
495		TV_CP(i32, itv, it_interval);
496		TV_CP(i32, itv, it_value);
497		itvp = &itv;
498	} else
499		itvp = NULL;
500	error = kern_setitimer(td, uap->which, itvp, &oitv);
501	if (error || uap->oitv == NULL)
502		return (error);
503	TV_CP(oitv, i32, it_interval);
504	TV_CP(oitv, i32, it_value);
505	return (copyout(&i32, uap->oitv, sizeof(i32)));
506}
507
508int
509freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
510{
511	struct itimerval itv;
512	struct itimerval32 i32;
513	int error;
514
515	error = kern_getitimer(td, uap->which, &itv);
516	if (error || uap->itv == NULL)
517		return (error);
518	TV_CP(itv, i32, it_interval);
519	TV_CP(itv, i32, it_value);
520	return (copyout(&i32, uap->itv, sizeof(i32)));
521}
522
523int
524freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
525{
526	struct timeval32 tv32;
527	struct timeval tv, *tvp;
528	int error;
529
530	if (uap->tv != NULL) {
531		error = copyin(uap->tv, &tv32, sizeof(tv32));
532		if (error)
533			return (error);
534		CP(tv32, tv, tv_sec);
535		CP(tv32, tv, tv_usec);
536		tvp = &tv;
537	} else
538		tvp = NULL;
539	/*
540	 * XXX big-endian needs to convert the fd_sets too.
541	 * XXX Do pointers need PTRIN()?
542	 */
543	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
544}
545
546struct kevent32 {
547	u_int32_t	ident;		/* identifier for this event */
548	short		filter;		/* filter for event */
549	u_short		flags;
550	u_int		fflags;
551	int32_t		data;
552	u_int32_t	udata;		/* opaque user data identifier */
553};
554
555CTASSERT(sizeof(struct kevent32) == 20);
556static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
557static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
558
559/*
560 * Copy 'count' items into the destination list pointed to by uap->eventlist.
561 */
562static int
563freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
564{
565	struct freebsd32_kevent_args *uap;
566	struct kevent32	ks32[KQ_NEVENTS];
567	int i, error = 0;
568
569	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
570	uap = (struct freebsd32_kevent_args *)arg;
571
572	for (i = 0; i < count; i++) {
573		CP(kevp[i], ks32[i], ident);
574		CP(kevp[i], ks32[i], filter);
575		CP(kevp[i], ks32[i], flags);
576		CP(kevp[i], ks32[i], fflags);
577		CP(kevp[i], ks32[i], data);
578		PTROUT_CP(kevp[i], ks32[i], udata);
579	}
580	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
581	if (error == 0)
582		uap->eventlist += count;
583	return (error);
584}
585
586/*
587 * Copy 'count' items from the list pointed to by uap->changelist.
588 */
589static int
590freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
591{
592	struct freebsd32_kevent_args *uap;
593	struct kevent32	ks32[KQ_NEVENTS];
594	int i, error = 0;
595
596	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
597	uap = (struct freebsd32_kevent_args *)arg;
598
599	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
600	if (error)
601		goto done;
602	uap->changelist += count;
603
604	for (i = 0; i < count; i++) {
605		CP(ks32[i], kevp[i], ident);
606		CP(ks32[i], kevp[i], filter);
607		CP(ks32[i], kevp[i], flags);
608		CP(ks32[i], kevp[i], fflags);
609		CP(ks32[i], kevp[i], data);
610		PTRIN_CP(ks32[i], kevp[i], udata);
611	}
612done:
613	return (error);
614}
615
616int
617freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
618{
619	struct timespec32 ts32;
620	struct timespec ts, *tsp;
621	struct kevent_copyops k_ops = { uap,
622					freebsd32_kevent_copyout,
623					freebsd32_kevent_copyin};
624	int error;
625
626
627	if (uap->timeout) {
628		error = copyin(uap->timeout, &ts32, sizeof(ts32));
629		if (error)
630			return (error);
631		CP(ts32, ts, tv_sec);
632		CP(ts32, ts, tv_nsec);
633		tsp = &ts;
634	} else
635		tsp = NULL;
636	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
637	    &k_ops, tsp);
638	return (error);
639}
640
641int
642freebsd32_gettimeofday(struct thread *td,
643		       struct freebsd32_gettimeofday_args *uap)
644{
645	struct timeval atv;
646	struct timeval32 atv32;
647	struct timezone rtz;
648	int error = 0;
649
650	if (uap->tp) {
651		microtime(&atv);
652		CP(atv, atv32, tv_sec);
653		CP(atv, atv32, tv_usec);
654		error = copyout(&atv32, uap->tp, sizeof (atv32));
655	}
656	if (error == 0 && uap->tzp != NULL) {
657		rtz.tz_minuteswest = tz_minuteswest;
658		rtz.tz_dsttime = tz_dsttime;
659		error = copyout(&rtz, uap->tzp, sizeof (rtz));
660	}
661	return (error);
662}
663
664int
665freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
666{
667	struct rusage32 s32;
668	struct rusage s;
669	int error;
670
671	error = kern_getrusage(td, uap->who, &s);
672	if (error)
673		return (error);
674	if (uap->rusage != NULL) {
675		TV_CP(s, s32, ru_utime);
676		TV_CP(s, s32, ru_stime);
677		CP(s, s32, ru_maxrss);
678		CP(s, s32, ru_ixrss);
679		CP(s, s32, ru_idrss);
680		CP(s, s32, ru_isrss);
681		CP(s, s32, ru_minflt);
682		CP(s, s32, ru_majflt);
683		CP(s, s32, ru_nswap);
684		CP(s, s32, ru_inblock);
685		CP(s, s32, ru_oublock);
686		CP(s, s32, ru_msgsnd);
687		CP(s, s32, ru_msgrcv);
688		CP(s, s32, ru_nsignals);
689		CP(s, s32, ru_nvcsw);
690		CP(s, s32, ru_nivcsw);
691		error = copyout(&s32, uap->rusage, sizeof(s32));
692	}
693	return (error);
694}
695
696struct iovec32 {
697	u_int32_t iov_base;
698	int	iov_len;
699};
700
701CTASSERT(sizeof(struct iovec32) == 8);
702
703static int
704freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
705{
706	struct iovec32 iov32;
707	struct iovec *iov;
708	struct uio *uio;
709	u_int iovlen;
710	int error, i;
711
712	*uiop = NULL;
713	if (iovcnt > UIO_MAXIOV)
714		return (EINVAL);
715	iovlen = iovcnt * sizeof(struct iovec);
716	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
717	iov = (struct iovec *)(uio + 1);
718	for (i = 0; i < iovcnt; i++) {
719		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
720		if (error) {
721			free(uio, M_IOV);
722			return (error);
723		}
724		iov[i].iov_base = PTRIN(iov32.iov_base);
725		iov[i].iov_len = iov32.iov_len;
726	}
727	uio->uio_iov = iov;
728	uio->uio_iovcnt = iovcnt;
729	uio->uio_segflg = UIO_USERSPACE;
730	uio->uio_offset = -1;
731	uio->uio_resid = 0;
732	for (i = 0; i < iovcnt; i++) {
733		if (iov->iov_len > INT_MAX - uio->uio_resid) {
734			free(uio, M_IOV);
735			return (EINVAL);
736		}
737		uio->uio_resid += iov->iov_len;
738		iov++;
739	}
740	*uiop = uio;
741	return (0);
742}
743
744int
745freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
746{
747	struct uio *auio;
748	int error;
749
750	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
751	if (error)
752		return (error);
753	error = kern_readv(td, uap->fd, auio);
754	free(auio, M_IOV);
755	return (error);
756}
757
758int
759freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
760{
761	struct uio *auio;
762	int error;
763
764	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
765	if (error)
766		return (error);
767	error = kern_writev(td, uap->fd, auio);
768	free(auio, M_IOV);
769	return (error);
770}
771
772int
773freebsd32_settimeofday(struct thread *td,
774		       struct freebsd32_settimeofday_args *uap)
775{
776	struct timeval32 tv32;
777	struct timeval tv, *tvp;
778	struct timezone tz, *tzp;
779	int error;
780
781	if (uap->tv) {
782		error = copyin(uap->tv, &tv32, sizeof(tv32));
783		if (error)
784			return (error);
785		CP(tv32, tv, tv_sec);
786		CP(tv32, tv, tv_usec);
787		tvp = &tv;
788	} else
789		tvp = NULL;
790	if (uap->tzp) {
791		error = copyin(uap->tzp, &tz, sizeof(tz));
792		if (error)
793			return (error);
794		tzp = &tz;
795	} else
796		tzp = NULL;
797	return (kern_settimeofday(td, tvp, tzp));
798}
799
800int
801freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
802{
803	struct timeval32 s32[2];
804	struct timeval s[2], *sp;
805	int error;
806
807	if (uap->tptr != NULL) {
808		error = copyin(uap->tptr, s32, sizeof(s32));
809		if (error)
810			return (error);
811		CP(s32[0], s[0], tv_sec);
812		CP(s32[0], s[0], tv_usec);
813		CP(s32[1], s[1], tv_sec);
814		CP(s32[1], s[1], tv_usec);
815		sp = s;
816	} else
817		sp = NULL;
818	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
819}
820
821int
822freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
823{
824	struct timeval32 tv32;
825	struct timeval delta, olddelta, *deltap;
826	int error;
827
828	if (uap->delta) {
829		error = copyin(uap->delta, &tv32, sizeof(tv32));
830		if (error)
831			return (error);
832		CP(tv32, delta, tv_sec);
833		CP(tv32, delta, tv_usec);
834		deltap = &delta;
835	} else
836		deltap = NULL;
837	error = kern_adjtime(td, deltap, &olddelta);
838	if (uap->olddelta && error == 0) {
839		CP(olddelta, tv32, tv_sec);
840		CP(olddelta, tv32, tv_usec);
841		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
842	}
843	return (error);
844}
845
846#ifdef COMPAT_FREEBSD4
847int
848freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
849{
850	struct statfs32 s32;
851	struct statfs s;
852	int error;
853
854	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
855	if (error)
856		return (error);
857	copy_statfs(&s, &s32);
858	return (copyout(&s32, uap->buf, sizeof(s32)));
859}
860#endif
861
862#ifdef COMPAT_FREEBSD4
863int
864freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
865{
866	struct statfs32 s32;
867	struct statfs s;
868	int error;
869
870	error = kern_fstatfs(td, uap->fd, &s);
871	if (error)
872		return (error);
873	copy_statfs(&s, &s32);
874	return (copyout(&s32, uap->buf, sizeof(s32)));
875}
876#endif
877
878#ifdef COMPAT_FREEBSD4
879int
880freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
881{
882	struct statfs32 s32;
883	struct statfs s;
884	fhandle_t fh;
885	int error;
886
887	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
888		return (error);
889	error = kern_fhstatfs(td, fh, &s);
890	if (error)
891		return (error);
892	copy_statfs(&s, &s32);
893	return (copyout(&s32, uap->buf, sizeof(s32)));
894}
895#endif
896
897int
898freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
899{
900	/*
901	 * Vector through to semsys if it is loaded.
902	 */
903	return sysent[169].sy_call(td, uap);
904}
905
906int
907freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
908{
909	/*
910	 * Vector through to msgsys if it is loaded.
911	 */
912	return sysent[170].sy_call(td, uap);
913}
914
915int
916freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
917{
918	/*
919	 * Vector through to shmsys if it is loaded.
920	 */
921	return sysent[171].sy_call(td, uap);
922}
923
924int
925freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
926{
927	struct pread_args ap;
928
929	ap.fd = uap->fd;
930	ap.buf = uap->buf;
931	ap.nbyte = uap->nbyte;
932	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
933	return (pread(td, &ap));
934}
935
936int
937freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
938{
939	struct pwrite_args ap;
940
941	ap.fd = uap->fd;
942	ap.buf = uap->buf;
943	ap.nbyte = uap->nbyte;
944	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
945	return (pwrite(td, &ap));
946}
947
948int
949freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
950{
951	int error;
952	struct lseek_args ap;
953	off_t pos;
954
955	ap.fd = uap->fd;
956	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
957	ap.whence = uap->whence;
958	error = lseek(td, &ap);
959	/* Expand the quad return into two parts for eax and edx */
960	pos = *(off_t *)(td->td_retval);
961	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
962	td->td_retval[1] = pos >> 32;		/* %edx */
963	return error;
964}
965
966int
967freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
968{
969	struct truncate_args ap;
970
971	ap.path = uap->path;
972	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
973	return (truncate(td, &ap));
974}
975
976int
977freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
978{
979	struct ftruncate_args ap;
980
981	ap.fd = uap->fd;
982	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
983	return (ftruncate(td, &ap));
984}
985
986#ifdef COMPAT_FREEBSD4
987int
988freebsd4_freebsd32_sendfile(struct thread *td,
989    struct freebsd4_freebsd32_sendfile_args *uap)
990{
991	struct freebsd4_sendfile_args ap;
992
993	ap.fd = uap->fd;
994	ap.s = uap->s;
995	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
996	ap.nbytes = uap->nbytes;	/* XXX check */
997	ap.hdtr = uap->hdtr;		/* XXX check */
998	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
999	ap.flags = uap->flags;
1000	return (freebsd4_sendfile(td, &ap));
1001}
1002#endif
1003
1004int
1005freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1006{
1007	struct sendfile_args ap;
1008
1009	ap.fd = uap->fd;
1010	ap.s = uap->s;
1011	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1012	ap.nbytes = uap->nbytes;	/* XXX check */
1013	ap.hdtr = uap->hdtr;		/* XXX check */
1014	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1015	ap.flags = uap->flags;
1016	return (sendfile(td, &ap));
1017}
1018
1019struct stat32 {
1020	dev_t	st_dev;
1021	ino_t	st_ino;
1022	mode_t	st_mode;
1023	nlink_t	st_nlink;
1024	uid_t	st_uid;
1025	gid_t	st_gid;
1026	dev_t	st_rdev;
1027	struct timespec32 st_atimespec;
1028	struct timespec32 st_mtimespec;
1029	struct timespec32 st_ctimespec;
1030	off_t	st_size;
1031	int64_t	st_blocks;
1032	u_int32_t st_blksize;
1033	u_int32_t st_flags;
1034	u_int32_t st_gen;
1035	struct timespec32 st_birthtimespec;
1036	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1037	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1038};
1039
1040
1041CTASSERT(sizeof(struct stat32) == 96);
1042
1043static void
1044copy_stat( struct stat *in, struct stat32 *out)
1045{
1046	CP(*in, *out, st_dev);
1047	CP(*in, *out, st_ino);
1048	CP(*in, *out, st_mode);
1049	CP(*in, *out, st_nlink);
1050	CP(*in, *out, st_uid);
1051	CP(*in, *out, st_gid);
1052	CP(*in, *out, st_rdev);
1053	TS_CP(*in, *out, st_atimespec);
1054	TS_CP(*in, *out, st_mtimespec);
1055	TS_CP(*in, *out, st_ctimespec);
1056	CP(*in, *out, st_size);
1057	CP(*in, *out, st_blocks);
1058	CP(*in, *out, st_blksize);
1059	CP(*in, *out, st_flags);
1060	CP(*in, *out, st_gen);
1061}
1062
1063int
1064freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1065{
1066	struct stat sb;
1067	struct stat32 sb32;
1068	int error;
1069
1070	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1071	if (error)
1072		return (error);
1073	copy_stat(&sb, &sb32);
1074	error = copyout(&sb32, uap->ub, sizeof (sb32));
1075	return (error);
1076}
1077
1078int
1079freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1080{
1081	struct stat ub;
1082	struct stat32 ub32;
1083	int error;
1084
1085	error = kern_fstat(td, uap->fd, &ub);
1086	if (error)
1087		return (error);
1088	copy_stat(&ub, &ub32);
1089	error = copyout(&ub32, uap->ub, sizeof(ub32));
1090	return (error);
1091}
1092
1093int
1094freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1095{
1096	struct stat sb;
1097	struct stat32 sb32;
1098	int error;
1099
1100	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1101	if (error)
1102		return (error);
1103	copy_stat(&sb, &sb32);
1104	error = copyout(&sb32, uap->ub, sizeof (sb32));
1105	return (error);
1106}
1107
1108/*
1109 * MPSAFE
1110 */
1111int
1112freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1113{
1114	int error, name[CTL_MAXNAME];
1115	size_t j, oldlen;
1116
1117	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1118		return (EINVAL);
1119 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1120 	if (error)
1121		return (error);
1122	mtx_lock(&Giant);
1123	if (uap->oldlenp)
1124		oldlen = fuword32(uap->oldlenp);
1125	else
1126		oldlen = 0;
1127	error = userland_sysctl(td, name, uap->namelen,
1128		uap->old, &oldlen, 1,
1129		uap->new, uap->newlen, &j, SCTL_MASK32);
1130	if (error && error != ENOMEM)
1131		goto done2;
1132	if (uap->oldlenp)
1133		suword32(uap->oldlenp, j);
1134done2:
1135	mtx_unlock(&Giant);
1136	return (error);
1137}
1138
1139struct sigaction32 {
1140	u_int32_t	sa_u;
1141	int		sa_flags;
1142	sigset_t	sa_mask;
1143};
1144
1145CTASSERT(sizeof(struct sigaction32) == 24);
1146
1147int
1148freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1149{
1150	struct sigaction32 s32;
1151	struct sigaction sa, osa, *sap;
1152	int error;
1153
1154	if (uap->act) {
1155		error = copyin(uap->act, &s32, sizeof(s32));
1156		if (error)
1157			return (error);
1158		sa.sa_handler = PTRIN(s32.sa_u);
1159		CP(s32, sa, sa_flags);
1160		CP(s32, sa, sa_mask);
1161		sap = &sa;
1162	} else
1163		sap = NULL;
1164	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1165	if (error == 0 && uap->oact != NULL) {
1166		s32.sa_u = PTROUT(osa.sa_handler);
1167		CP(osa, s32, sa_flags);
1168		CP(osa, s32, sa_mask);
1169		error = copyout(&s32, uap->oact, sizeof(s32));
1170	}
1171	return (error);
1172}
1173
1174#ifdef COMPAT_FREEBSD4
1175int
1176freebsd4_freebsd32_sigaction(struct thread *td,
1177			     struct freebsd4_freebsd32_sigaction_args *uap)
1178{
1179	struct sigaction32 s32;
1180	struct sigaction sa, osa, *sap;
1181	int error;
1182
1183	if (uap->act) {
1184		error = copyin(uap->act, &s32, sizeof(s32));
1185		if (error)
1186			return (error);
1187		sa.sa_handler = PTRIN(s32.sa_u);
1188		CP(s32, sa, sa_flags);
1189		CP(s32, sa, sa_mask);
1190		sap = &sa;
1191	} else
1192		sap = NULL;
1193	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1194	if (error == 0 && uap->oact != NULL) {
1195		s32.sa_u = PTROUT(osa.sa_handler);
1196		CP(osa, s32, sa_flags);
1197		CP(osa, s32, sa_mask);
1198		error = copyout(&s32, uap->oact, sizeof(s32));
1199	}
1200	return (error);
1201}
1202#endif
1203
1204int
1205freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1206{
1207	struct timespec32 rmt32, rqt32;
1208	struct timespec rmt, rqt;
1209	int error;
1210
1211	error = copyin(uap->rqtp, &rqt32, sizeof(rqt));
1212	if (error)
1213		return (error);
1214
1215	CP(rqt32, rqt, tv_sec);
1216	CP(rqt32, rqt, tv_nsec);
1217
1218	if (uap->rmtp &&
1219	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1220		return (EFAULT);
1221	error = kern_nanosleep(td, &rqt, &rmt);
1222	if (error && uap->rmtp) {
1223		int error2;
1224
1225		CP(rmt, rmt32, tv_sec);
1226		CP(rmt, rmt32, tv_nsec);
1227
1228		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt));
1229		if (error2)
1230			error = error2;
1231	}
1232	return (error);
1233}
1234
1235#if 0
1236
1237int
1238freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1239{
1240	int error;
1241	caddr_t sg;
1242	struct yyy32 *p32, s32;
1243	struct yyy *p = NULL, s;
1244
1245	p32 = uap->zzz;
1246	if (p32) {
1247		sg = stackgap_init();
1248		p = stackgap_alloc(&sg, sizeof(struct yyy));
1249		uap->zzz = (struct yyy32 *)p;
1250		error = copyin(p32, &s32, sizeof(s32));
1251		if (error)
1252			return (error);
1253		/* translate in */
1254		error = copyout(&s, p, sizeof(s));
1255		if (error)
1256			return (error);
1257	}
1258	error = xxx(td, (struct xxx_args *) uap);
1259	if (error)
1260		return (error);
1261	if (p32) {
1262		error = copyin(p, &s, sizeof(s));
1263		if (error)
1264			return (error);
1265		/* translate out */
1266		error = copyout(&s32, p32, sizeof(s32));
1267	}
1268	return (error);
1269}
1270
1271#endif
1272