xref: /freebsd/sys/compat/freebsd32/freebsd32_misc.c (revision 57c4583f70ab9d25b3aed17f20ec7843f9673539)
1 /*-
2  * Copyright (c) 2002 Doug Rabson
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include "opt_compat.h"
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/bus.h>
35 #include <sys/clock.h>
36 #include <sys/exec.h>
37 #include <sys/fcntl.h>
38 #include <sys/filedesc.h>
39 #include <sys/namei.h>
40 #include <sys/imgact.h>
41 #include <sys/kernel.h>
42 #include <sys/limits.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/file.h>		/* Must come after sys/malloc.h */
46 #include <sys/mbuf.h>
47 #include <sys/mman.h>
48 #include <sys/module.h>
49 #include <sys/mount.h>
50 #include <sys/mutex.h>
51 #include <sys/namei.h>
52 #include <sys/param.h>
53 #include <sys/proc.h>
54 #include <sys/reboot.h>
55 #include <sys/resource.h>
56 #include <sys/resourcevar.h>
57 #include <sys/selinfo.h>
58 #include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
59 #include <sys/pipe.h>		/* Must come after sys/selinfo.h */
60 #include <sys/signal.h>
61 #include <sys/signalvar.h>
62 #include <sys/socket.h>
63 #include <sys/socketvar.h>
64 #include <sys/stat.h>
65 #include <sys/syscall.h>
66 #include <sys/syscallsubr.h>
67 #include <sys/sysctl.h>
68 #include <sys/sysent.h>
69 #include <sys/sysproto.h>
70 #include <sys/systm.h>
71 #include <sys/thr.h>
72 #include <sys/unistd.h>
73 #include <sys/ucontext.h>
74 #include <sys/vnode.h>
75 #include <sys/wait.h>
76 #include <sys/ipc.h>
77 #include <sys/shm.h>
78 
79 #include <vm/vm.h>
80 #include <vm/vm_kern.h>
81 #include <vm/vm_param.h>
82 #include <vm/pmap.h>
83 #include <vm/vm_map.h>
84 #include <vm/vm_object.h>
85 #include <vm/vm_extern.h>
86 
87 #include <machine/cpu.h>
88 
89 #include <compat/freebsd32/freebsd32_util.h>
90 #include <compat/freebsd32/freebsd32.h>
91 #include <compat/freebsd32/freebsd32_signal.h>
92 #include <compat/freebsd32/freebsd32_proto.h>
93 
94 CTASSERT(sizeof(struct timeval32) == 8);
95 CTASSERT(sizeof(struct timespec32) == 8);
96 CTASSERT(sizeof(struct statfs32) == 256);
97 CTASSERT(sizeof(struct rusage32) == 72);
98 
99 int
100 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
101 {
102 	int error, status;
103 	struct rusage32 ru32;
104 	struct rusage ru, *rup;
105 
106 	if (uap->rusage != NULL)
107 		rup = &ru;
108 	else
109 		rup = NULL;
110 	error = kern_wait(td, uap->pid, &status, uap->options, rup);
111 	if (error)
112 		return (error);
113 	if (uap->status != NULL)
114 		error = copyout(&status, uap->status, sizeof(status));
115 	if (uap->rusage != NULL && error == 0) {
116 		TV_CP(ru, ru32, ru_utime);
117 		TV_CP(ru, ru32, ru_stime);
118 		CP(ru, ru32, ru_maxrss);
119 		CP(ru, ru32, ru_ixrss);
120 		CP(ru, ru32, ru_idrss);
121 		CP(ru, ru32, ru_isrss);
122 		CP(ru, ru32, ru_minflt);
123 		CP(ru, ru32, ru_majflt);
124 		CP(ru, ru32, ru_nswap);
125 		CP(ru, ru32, ru_inblock);
126 		CP(ru, ru32, ru_oublock);
127 		CP(ru, ru32, ru_msgsnd);
128 		CP(ru, ru32, ru_msgrcv);
129 		CP(ru, ru32, ru_nsignals);
130 		CP(ru, ru32, ru_nvcsw);
131 		CP(ru, ru32, ru_nivcsw);
132 		error = copyout(&ru32, uap->rusage, sizeof(ru32));
133 	}
134 	return (error);
135 }
136 
137 #ifdef COMPAT_FREEBSD4
138 static void
139 copy_statfs(struct statfs *in, struct statfs32 *out)
140 {
141 
142 	bzero(out, sizeof(*out));
143 	CP(*in, *out, f_bsize);
144 	CP(*in, *out, f_iosize);
145 	CP(*in, *out, f_blocks);
146 	CP(*in, *out, f_bfree);
147 	CP(*in, *out, f_bavail);
148 	CP(*in, *out, f_files);
149 	CP(*in, *out, f_ffree);
150 	CP(*in, *out, f_fsid);
151 	CP(*in, *out, f_owner);
152 	CP(*in, *out, f_type);
153 	CP(*in, *out, f_flags);
154 	CP(*in, *out, f_flags);
155 	CP(*in, *out, f_syncwrites);
156 	CP(*in, *out, f_asyncwrites);
157 	strlcpy(out->f_fstypename,
158 	      in->f_fstypename, MFSNAMELEN);
159 	strlcpy(out->f_mntonname,
160 	      in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
161 	CP(*in, *out, f_syncreads);
162 	CP(*in, *out, f_asyncreads);
163 	strlcpy(out->f_mntfromname,
164 	      in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
165 }
166 #endif
167 
168 #ifdef COMPAT_FREEBSD4
169 int
170 freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
171 {
172 	struct statfs *buf, *sp;
173 	struct statfs32 stat32;
174 	size_t count, size;
175 	int error;
176 
177 	count = uap->bufsize / sizeof(struct statfs32);
178 	size = count * sizeof(struct statfs);
179 	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
180 	if (size > 0) {
181 		count = td->td_retval[0];
182 		sp = buf;
183 		while (count > 0 && error == 0) {
184 			copy_statfs(sp, &stat32);
185 			error = copyout(&stat32, uap->buf, sizeof(stat32));
186 			sp++;
187 			uap->buf++;
188 			count--;
189 		}
190 		free(buf, M_TEMP);
191 	}
192 	return (error);
193 }
194 #endif
195 
196 CTASSERT(sizeof(struct sigaltstack32) == 12);
197 
198 int
199 freebsd32_sigaltstack(struct thread *td,
200 		      struct freebsd32_sigaltstack_args *uap)
201 {
202 	struct sigaltstack32 s32;
203 	struct sigaltstack ss, oss, *ssp;
204 	int error;
205 
206 	if (uap->ss != NULL) {
207 		error = copyin(uap->ss, &s32, sizeof(s32));
208 		if (error)
209 			return (error);
210 		PTRIN_CP(s32, ss, ss_sp);
211 		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  */
230 static int
231 freebsd32_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,
248 	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
249 	if (args->buf == NULL)
250 		return (ENOMEM);
251 	args->begin_argv = args->buf;
252 	args->endp = args->begin_argv;
253 	args->stringspace = ARG_MAX;
254 
255 	args->fname = args->buf + ARG_MAX;
256 
257 	/*
258 	 * Copy the file name.
259 	 */
260 	error = (segflg == UIO_SYSSPACE) ?
261 	    copystr(fname, args->fname, PATH_MAX, &length) :
262 	    copyinstr(fname, args->fname, PATH_MAX, &length);
263 	if (error != 0)
264 		goto err_exit;
265 
266 	/*
267 	 * extract arguments first
268 	 */
269 	p32 = argv;
270 	for (;;) {
271 		error = copyin(p32++, &arg, sizeof(arg));
272 		if (error)
273 			goto err_exit;
274 		if (arg == 0)
275 			break;
276 		argp = PTRIN(arg);
277 		error = copyinstr(argp, args->endp, args->stringspace, &length);
278 		if (error) {
279 			if (error == ENAMETOOLONG)
280 				error = E2BIG;
281 			goto err_exit;
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 				goto err_exit;
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 					error = E2BIG;
307 				goto err_exit;
308 			}
309 			args->stringspace -= length;
310 			args->endp += length;
311 			args->envc++;
312 		}
313 	}
314 
315 	return (0);
316 
317 err_exit:
318 	kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
319 	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
320 	args->buf = NULL;
321 	return (error);
322 }
323 
324 int
325 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
326 {
327 	struct image_args eargs;
328 	int error;
329 
330 	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
331 	    uap->argv, uap->envv);
332 	if (error == 0)
333 		error = kern_execve(td, &eargs, NULL);
334 	return (error);
335 }
336 
337 #ifdef __ia64__
338 static int
339 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
340 		       int prot, int fd, off_t pos)
341 {
342 	vm_map_t map;
343 	vm_map_entry_t entry;
344 	int rv;
345 
346 	map = &td->td_proc->p_vmspace->vm_map;
347 	if (fd != -1)
348 		prot |= VM_PROT_WRITE;
349 
350 	if (vm_map_lookup_entry(map, start, &entry)) {
351 		if ((entry->protection & prot) != prot) {
352 			rv = vm_map_protect(map,
353 					    trunc_page(start),
354 					    round_page(end),
355 					    entry->protection | prot,
356 					    FALSE);
357 			if (rv != KERN_SUCCESS)
358 				return (EINVAL);
359 		}
360 	} else {
361 		vm_offset_t addr = trunc_page(start);
362 		rv = vm_map_find(map, 0, 0,
363 				 &addr, PAGE_SIZE, FALSE, prot,
364 				 VM_PROT_ALL, 0);
365 		if (rv != KERN_SUCCESS)
366 			return (EINVAL);
367 	}
368 
369 	if (fd != -1) {
370 		struct pread_args r;
371 		r.fd = fd;
372 		r.buf = (void *) start;
373 		r.nbyte = end - start;
374 		r.offset = pos;
375 		return (pread(td, &r));
376 	} else {
377 		while (start < end) {
378 			subyte((void *) start, 0);
379 			start++;
380 		}
381 		return (0);
382 	}
383 }
384 #endif
385 
386 int
387 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
388 {
389 	struct mmap_args ap;
390 	vm_offset_t addr = (vm_offset_t) uap->addr;
391 	vm_size_t len	 = uap->len;
392 	int prot	 = uap->prot;
393 	int flags	 = uap->flags;
394 	int fd		 = uap->fd;
395 	off_t pos	 = (uap->poslo
396 			    | ((off_t)uap->poshi << 32));
397 #ifdef __ia64__
398 	vm_size_t pageoff;
399 	int error;
400 
401 	/*
402 	 * Attempt to handle page size hassles.
403 	 */
404 	pageoff = (pos & PAGE_MASK);
405 	if (flags & MAP_FIXED) {
406 		vm_offset_t start, end;
407 		start = addr;
408 		end = addr + len;
409 
410 		mtx_lock(&Giant);
411 		if (start != trunc_page(start)) {
412 			error = freebsd32_mmap_partial(td, start,
413 						       round_page(start), prot,
414 						       fd, pos);
415 			if (fd != -1)
416 				pos += round_page(start) - start;
417 			start = round_page(start);
418 		}
419 		if (end != round_page(end)) {
420 			vm_offset_t t = trunc_page(end);
421 			error = freebsd32_mmap_partial(td, t, end,
422 						  prot, fd,
423 						  pos + t - start);
424 			end = trunc_page(end);
425 		}
426 		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
427 			/*
428 			 * We can't map this region at all. The specified
429 			 * address doesn't have the same alignment as the file
430 			 * position. Fake the mapping by simply reading the
431 			 * entire region into memory. First we need to make
432 			 * sure the region exists.
433 			 */
434 			vm_map_t map;
435 			struct pread_args r;
436 			int rv;
437 
438 			prot |= VM_PROT_WRITE;
439 			map = &td->td_proc->p_vmspace->vm_map;
440 			rv = vm_map_remove(map, start, end);
441 			if (rv != KERN_SUCCESS) {
442 				mtx_unlock(&Giant);
443 				return (EINVAL);
444 			}
445 			rv = vm_map_find(map, 0, 0,
446 					 &start, end - start, FALSE,
447 					 prot, VM_PROT_ALL, 0);
448 			mtx_unlock(&Giant);
449 			if (rv != KERN_SUCCESS)
450 				return (EINVAL);
451 			r.fd = fd;
452 			r.buf = (void *) start;
453 			r.nbyte = end - start;
454 			r.offset = pos;
455 			error = pread(td, &r);
456 			if (error)
457 				return (error);
458 
459 			td->td_retval[0] = addr;
460 			return (0);
461 		}
462 		mtx_unlock(&Giant);
463 		if (end == start) {
464 			/*
465 			 * After dealing with the ragged ends, there
466 			 * might be none left.
467 			 */
468 			td->td_retval[0] = addr;
469 			return (0);
470 		}
471 		addr = start;
472 		len = end - start;
473 	}
474 #endif
475 
476 	ap.addr = (void *) addr;
477 	ap.len = len;
478 	ap.prot = prot;
479 	ap.flags = flags;
480 	ap.fd = fd;
481 	ap.pos = pos;
482 
483 	return (mmap(td, &ap));
484 }
485 
486 struct itimerval32 {
487 	struct timeval32 it_interval;
488 	struct timeval32 it_value;
489 };
490 
491 CTASSERT(sizeof(struct itimerval32) == 16);
492 
493 int
494 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
495 {
496 	struct itimerval itv, oitv, *itvp;
497 	struct itimerval32 i32;
498 	int error;
499 
500 	if (uap->itv != NULL) {
501 		error = copyin(uap->itv, &i32, sizeof(i32));
502 		if (error)
503 			return (error);
504 		TV_CP(i32, itv, it_interval);
505 		TV_CP(i32, itv, it_value);
506 		itvp = &itv;
507 	} else
508 		itvp = NULL;
509 	error = kern_setitimer(td, uap->which, itvp, &oitv);
510 	if (error || uap->oitv == NULL)
511 		return (error);
512 	TV_CP(oitv, i32, it_interval);
513 	TV_CP(oitv, i32, it_value);
514 	return (copyout(&i32, uap->oitv, sizeof(i32)));
515 }
516 
517 int
518 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
519 {
520 	struct itimerval itv;
521 	struct itimerval32 i32;
522 	int error;
523 
524 	error = kern_getitimer(td, uap->which, &itv);
525 	if (error || uap->itv == NULL)
526 		return (error);
527 	TV_CP(itv, i32, it_interval);
528 	TV_CP(itv, i32, it_value);
529 	return (copyout(&i32, uap->itv, sizeof(i32)));
530 }
531 
532 int
533 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
534 {
535 	struct timeval32 tv32;
536 	struct timeval tv, *tvp;
537 	int error;
538 
539 	if (uap->tv != NULL) {
540 		error = copyin(uap->tv, &tv32, sizeof(tv32));
541 		if (error)
542 			return (error);
543 		CP(tv32, tv, tv_sec);
544 		CP(tv32, tv, tv_usec);
545 		tvp = &tv;
546 	} else
547 		tvp = NULL;
548 	/*
549 	 * XXX big-endian needs to convert the fd_sets too.
550 	 * XXX Do pointers need PTRIN()?
551 	 */
552 	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
553 }
554 
555 struct kevent32 {
556 	u_int32_t	ident;		/* identifier for this event */
557 	short		filter;		/* filter for event */
558 	u_short		flags;
559 	u_int		fflags;
560 	int32_t		data;
561 	u_int32_t	udata;		/* opaque user data identifier */
562 };
563 
564 CTASSERT(sizeof(struct kevent32) == 20);
565 static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
566 static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
567 
568 /*
569  * Copy 'count' items into the destination list pointed to by uap->eventlist.
570  */
571 static int
572 freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
573 {
574 	struct freebsd32_kevent_args *uap;
575 	struct kevent32	ks32[KQ_NEVENTS];
576 	int i, error = 0;
577 
578 	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
579 	uap = (struct freebsd32_kevent_args *)arg;
580 
581 	for (i = 0; i < count; i++) {
582 		CP(kevp[i], ks32[i], ident);
583 		CP(kevp[i], ks32[i], filter);
584 		CP(kevp[i], ks32[i], flags);
585 		CP(kevp[i], ks32[i], fflags);
586 		CP(kevp[i], ks32[i], data);
587 		PTROUT_CP(kevp[i], ks32[i], udata);
588 	}
589 	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
590 	if (error == 0)
591 		uap->eventlist += count;
592 	return (error);
593 }
594 
595 /*
596  * Copy 'count' items from the list pointed to by uap->changelist.
597  */
598 static int
599 freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
600 {
601 	struct freebsd32_kevent_args *uap;
602 	struct kevent32	ks32[KQ_NEVENTS];
603 	int i, error = 0;
604 
605 	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
606 	uap = (struct freebsd32_kevent_args *)arg;
607 
608 	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
609 	if (error)
610 		goto done;
611 	uap->changelist += count;
612 
613 	for (i = 0; i < count; i++) {
614 		CP(ks32[i], kevp[i], ident);
615 		CP(ks32[i], kevp[i], filter);
616 		CP(ks32[i], kevp[i], flags);
617 		CP(ks32[i], kevp[i], fflags);
618 		CP(ks32[i], kevp[i], data);
619 		PTRIN_CP(ks32[i], kevp[i], udata);
620 	}
621 done:
622 	return (error);
623 }
624 
625 int
626 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
627 {
628 	struct timespec32 ts32;
629 	struct timespec ts, *tsp;
630 	struct kevent_copyops k_ops = { uap,
631 					freebsd32_kevent_copyout,
632 					freebsd32_kevent_copyin};
633 	int error;
634 
635 
636 	if (uap->timeout) {
637 		error = copyin(uap->timeout, &ts32, sizeof(ts32));
638 		if (error)
639 			return (error);
640 		CP(ts32, ts, tv_sec);
641 		CP(ts32, ts, tv_nsec);
642 		tsp = &ts;
643 	} else
644 		tsp = NULL;
645 	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
646 	    &k_ops, tsp);
647 	return (error);
648 }
649 
650 int
651 freebsd32_gettimeofday(struct thread *td,
652 		       struct freebsd32_gettimeofday_args *uap)
653 {
654 	struct timeval atv;
655 	struct timeval32 atv32;
656 	struct timezone rtz;
657 	int error = 0;
658 
659 	if (uap->tp) {
660 		microtime(&atv);
661 		CP(atv, atv32, tv_sec);
662 		CP(atv, atv32, tv_usec);
663 		error = copyout(&atv32, uap->tp, sizeof (atv32));
664 	}
665 	if (error == 0 && uap->tzp != NULL) {
666 		rtz.tz_minuteswest = tz_minuteswest;
667 		rtz.tz_dsttime = tz_dsttime;
668 		error = copyout(&rtz, uap->tzp, sizeof (rtz));
669 	}
670 	return (error);
671 }
672 
673 int
674 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
675 {
676 	struct rusage32 s32;
677 	struct rusage s;
678 	int error;
679 
680 	error = kern_getrusage(td, uap->who, &s);
681 	if (error)
682 		return (error);
683 	if (uap->rusage != NULL) {
684 		TV_CP(s, s32, ru_utime);
685 		TV_CP(s, s32, ru_stime);
686 		CP(s, s32, ru_maxrss);
687 		CP(s, s32, ru_ixrss);
688 		CP(s, s32, ru_idrss);
689 		CP(s, s32, ru_isrss);
690 		CP(s, s32, ru_minflt);
691 		CP(s, s32, ru_majflt);
692 		CP(s, s32, ru_nswap);
693 		CP(s, s32, ru_inblock);
694 		CP(s, s32, ru_oublock);
695 		CP(s, s32, ru_msgsnd);
696 		CP(s, s32, ru_msgrcv);
697 		CP(s, s32, ru_nsignals);
698 		CP(s, s32, ru_nvcsw);
699 		CP(s, s32, ru_nivcsw);
700 		error = copyout(&s32, uap->rusage, sizeof(s32));
701 	}
702 	return (error);
703 }
704 
705 struct iovec32 {
706 	u_int32_t iov_base;
707 	int	iov_len;
708 };
709 
710 CTASSERT(sizeof(struct iovec32) == 8);
711 
712 static int
713 freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
714 {
715 	struct iovec32 iov32;
716 	struct iovec *iov;
717 	struct uio *uio;
718 	u_int iovlen;
719 	int error, i;
720 
721 	*uiop = NULL;
722 	if (iovcnt > UIO_MAXIOV)
723 		return (EINVAL);
724 	iovlen = iovcnt * sizeof(struct iovec);
725 	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
726 	iov = (struct iovec *)(uio + 1);
727 	for (i = 0; i < iovcnt; i++) {
728 		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
729 		if (error) {
730 			free(uio, M_IOV);
731 			return (error);
732 		}
733 		iov[i].iov_base = PTRIN(iov32.iov_base);
734 		iov[i].iov_len = iov32.iov_len;
735 	}
736 	uio->uio_iov = iov;
737 	uio->uio_iovcnt = iovcnt;
738 	uio->uio_segflg = UIO_USERSPACE;
739 	uio->uio_offset = -1;
740 	uio->uio_resid = 0;
741 	for (i = 0; i < iovcnt; i++) {
742 		if (iov->iov_len > INT_MAX - uio->uio_resid) {
743 			free(uio, M_IOV);
744 			return (EINVAL);
745 		}
746 		uio->uio_resid += iov->iov_len;
747 		iov++;
748 	}
749 	*uiop = uio;
750 	return (0);
751 }
752 
753 int
754 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
755 {
756 	struct uio *auio;
757 	int error;
758 
759 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
760 	if (error)
761 		return (error);
762 	error = kern_readv(td, uap->fd, auio);
763 	free(auio, M_IOV);
764 	return (error);
765 }
766 
767 int
768 freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
769 {
770 	struct uio *auio;
771 	int error;
772 
773 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
774 	if (error)
775 		return (error);
776 	error = kern_writev(td, uap->fd, auio);
777 	free(auio, M_IOV);
778 	return (error);
779 }
780 
781 int
782 freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
783 {
784 	struct uio *auio;
785 	int error;
786 
787 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
788 	if (error)
789 		return (error);
790 	error = kern_preadv(td, uap->fd, auio, uap->offset);
791 	free(auio, M_IOV);
792 	return (error);
793 }
794 
795 int
796 freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
797 {
798 	struct uio *auio;
799 	int error;
800 
801 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
802 	if (error)
803 		return (error);
804 	error = kern_pwritev(td, uap->fd, auio, uap->offset);
805 	free(auio, M_IOV);
806 	return (error);
807 }
808 
809 static int
810 freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
811     int error)
812 {
813 	struct iovec32 iov32;
814 	struct iovec *iov;
815 	u_int iovlen;
816 	int i;
817 
818 	*iovp = NULL;
819 	if (iovcnt > UIO_MAXIOV)
820 		return (error);
821 	iovlen = iovcnt * sizeof(struct iovec);
822 	iov = malloc(iovlen, M_IOV, M_WAITOK);
823 	for (i = 0; i < iovcnt; i++) {
824 		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
825 		if (error) {
826 			free(iov, M_IOV);
827 			return (error);
828 		}
829 		iov[i].iov_base = PTRIN(iov32.iov_base);
830 		iov[i].iov_len = iov32.iov_len;
831 	}
832 	*iovp = iov;
833 	return (0);
834 }
835 
836 struct msghdr32 {
837 	u_int32_t	 msg_name;
838 	socklen_t	 msg_namelen;
839 	u_int32_t	 msg_iov;
840 	int		 msg_iovlen;
841 	u_int32_t	 msg_control;
842 	socklen_t	 msg_controllen;
843 	int		 msg_flags;
844 };
845 CTASSERT(sizeof(struct msghdr32) == 28);
846 
847 static int
848 freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
849 {
850 	struct msghdr32 m32;
851 	int error;
852 
853 	error = copyin(msg32, &m32, sizeof(m32));
854 	if (error)
855 		return (error);
856 	msg->msg_name = PTRIN(m32.msg_name);
857 	msg->msg_namelen = m32.msg_namelen;
858 	msg->msg_iov = PTRIN(m32.msg_iov);
859 	msg->msg_iovlen = m32.msg_iovlen;
860 	msg->msg_control = PTRIN(m32.msg_control);
861 	msg->msg_controllen = m32.msg_controllen;
862 	msg->msg_flags = m32.msg_flags;
863 	return (0);
864 }
865 
866 static int
867 freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
868 {
869 	struct msghdr32 m32;
870 	int error;
871 
872 	m32.msg_name = PTROUT(msg->msg_name);
873 	m32.msg_namelen = msg->msg_namelen;
874 	m32.msg_iov = PTROUT(msg->msg_iov);
875 	m32.msg_iovlen = msg->msg_iovlen;
876 	m32.msg_control = PTROUT(msg->msg_control);
877 	m32.msg_controllen = msg->msg_controllen;
878 	m32.msg_flags = msg->msg_flags;
879 	error = copyout(&m32, msg32, sizeof(m32));
880 	return (error);
881 }
882 
883 #define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
884 #define FREEBSD32_ALIGN(p)	\
885 	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
886 #define	FREEBSD32_CMSG_SPACE(l)	\
887 	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
888 
889 #define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
890 				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
891 static int
892 freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
893 {
894 	struct cmsghdr *cm;
895 	void *data;
896 	socklen_t clen, datalen;
897 	int error;
898 	caddr_t ctlbuf;
899 	int len, maxlen, copylen;
900 	struct mbuf *m;
901 	error = 0;
902 
903 	len    = msg->msg_controllen;
904 	maxlen = msg->msg_controllen;
905 	msg->msg_controllen = 0;
906 
907 	m = control;
908 	ctlbuf = msg->msg_control;
909 
910 	while (m && len > 0) {
911 		cm = mtod(m, struct cmsghdr *);
912 		clen = m->m_len;
913 
914 		while (cm != NULL) {
915 
916 			if (sizeof(struct cmsghdr) > clen ||
917 			    cm->cmsg_len > clen) {
918 				error = EINVAL;
919 				break;
920 			}
921 
922 			data   = CMSG_DATA(cm);
923 			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
924 
925 			/* Adjust message length */
926 			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
927 			    datalen;
928 
929 
930 			/* Copy cmsghdr */
931 			copylen = sizeof(struct cmsghdr);
932 			if (len < copylen) {
933 				msg->msg_flags |= MSG_CTRUNC;
934 				copylen = len;
935 			}
936 
937 			error = copyout(cm,ctlbuf,copylen);
938 			if (error)
939 				goto exit;
940 
941 			ctlbuf += FREEBSD32_ALIGN(copylen);
942 			len    -= FREEBSD32_ALIGN(copylen);
943 
944 			if (len <= 0)
945 				break;
946 
947 			/* Copy data */
948 			copylen = datalen;
949 			if (len < copylen) {
950 				msg->msg_flags |= MSG_CTRUNC;
951 				copylen = len;
952 			}
953 
954 			error = copyout(data,ctlbuf,copylen);
955 			if (error)
956 				goto exit;
957 
958 			ctlbuf += FREEBSD32_ALIGN(copylen);
959 			len    -= FREEBSD32_ALIGN(copylen);
960 
961 			if (CMSG_SPACE(datalen) < clen) {
962 				clen -= CMSG_SPACE(datalen);
963 				cm = (struct cmsghdr *)
964 					((caddr_t)cm + CMSG_SPACE(datalen));
965 			} else {
966 				clen = 0;
967 				cm = NULL;
968 			}
969 		}
970 		m = m->m_next;
971 	}
972 
973 	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
974 
975 exit:
976 	return (error);
977 
978 }
979 
980 int
981 freebsd32_recvmsg(td, uap)
982 	struct thread *td;
983 	struct freebsd32_recvmsg_args /* {
984 		int	s;
985 		struct	msghdr32 *msg;
986 		int	flags;
987 	} */ *uap;
988 {
989 	struct msghdr msg;
990 	struct msghdr32 m32;
991 	struct iovec *uiov, *iov;
992 	struct mbuf *control = NULL;
993 	struct mbuf **controlp;
994 
995 	int error;
996 	error = copyin(uap->msg, &m32, sizeof(m32));
997 	if (error)
998 		return (error);
999 	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1000 	if (error)
1001 		return (error);
1002 	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1003 	    EMSGSIZE);
1004 	if (error)
1005 		return (error);
1006 	msg.msg_flags = uap->flags;
1007 	uiov = msg.msg_iov;
1008 	msg.msg_iov = iov;
1009 
1010 	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1011 	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
1012 	if (error == 0) {
1013 		msg.msg_iov = uiov;
1014 
1015 		if (control != NULL)
1016 			error = freebsd32_copy_msg_out(&msg, control);
1017 
1018 		if (error == 0)
1019 			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1020 	}
1021 	free(iov, M_IOV);
1022 
1023 	if (control != NULL)
1024 		m_freem(control);
1025 
1026 	return (error);
1027 }
1028 
1029 
1030 static int
1031 freebsd32_convert_msg_in(struct mbuf **controlp)
1032 {
1033 	struct mbuf *control = *controlp;
1034 	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1035 	void *data;
1036 	socklen_t clen = control->m_len, datalen;
1037 	int error;
1038 
1039 	error = 0;
1040 	*controlp = NULL;
1041 
1042 	while (cm != NULL) {
1043 		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1044 			error = EINVAL;
1045 			break;
1046 		}
1047 
1048 		data = FREEBSD32_CMSG_DATA(cm);
1049 		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1050 
1051 		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1052 		    cm->cmsg_level);
1053 		controlp = &(*controlp)->m_next;
1054 
1055 		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1056 			clen -= FREEBSD32_CMSG_SPACE(datalen);
1057 			cm = (struct cmsghdr *)
1058 				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1059 		} else {
1060 			clen = 0;
1061 			cm = NULL;
1062 		}
1063 	}
1064 
1065 	m_freem(control);
1066 	return (error);
1067 }
1068 
1069 
1070 int
1071 freebsd32_sendmsg(struct thread *td,
1072 		  struct freebsd32_sendmsg_args *uap)
1073 {
1074 	struct msghdr msg;
1075 	struct msghdr32 m32;
1076 	struct iovec *iov;
1077 	struct mbuf *control = NULL;
1078 	struct sockaddr *to = NULL;
1079 	int error;
1080 
1081 	error = copyin(uap->msg, &m32, sizeof(m32));
1082 	if (error)
1083 		return (error);
1084 	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1085 	if (error)
1086 		return (error);
1087 	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1088 	    EMSGSIZE);
1089 	if (error)
1090 		return (error);
1091 	msg.msg_iov = iov;
1092 	if (msg.msg_name != NULL) {
1093 		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1094 		if (error) {
1095 			to = NULL;
1096 			goto out;
1097 		}
1098 		msg.msg_name = to;
1099 	}
1100 
1101 	if (msg.msg_control) {
1102 		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1103 			error = EINVAL;
1104 			goto out;
1105 		}
1106 
1107 		error = sockargs(&control, msg.msg_control,
1108 		    msg.msg_controllen, MT_CONTROL);
1109 		if (error)
1110 			goto out;
1111 
1112 		error = freebsd32_convert_msg_in(&control);
1113 		if (error)
1114 			goto out;
1115 	}
1116 
1117 	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1118 	    UIO_USERSPACE);
1119 
1120 out:
1121 	free(iov, M_IOV);
1122 	if (to)
1123 		free(to, M_SONAME);
1124 	return (error);
1125 }
1126 
1127 int
1128 freebsd32_recvfrom(struct thread *td,
1129 		   struct freebsd32_recvfrom_args *uap)
1130 {
1131 	struct msghdr msg;
1132 	struct iovec aiov;
1133 	int error;
1134 
1135 	if (uap->fromlenaddr) {
1136 		error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
1137 		    sizeof(msg.msg_namelen));
1138 		if (error)
1139 			return (error);
1140 	} else {
1141 		msg.msg_namelen = 0;
1142 	}
1143 
1144 	msg.msg_name = PTRIN(uap->from);
1145 	msg.msg_iov = &aiov;
1146 	msg.msg_iovlen = 1;
1147 	aiov.iov_base = PTRIN(uap->buf);
1148 	aiov.iov_len = uap->len;
1149 	msg.msg_control = NULL;
1150 	msg.msg_flags = uap->flags;
1151 	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
1152 	if (error == 0 && uap->fromlenaddr)
1153 		error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
1154 		    sizeof (msg.msg_namelen));
1155 	return (error);
1156 }
1157 
1158 int
1159 freebsd32_settimeofday(struct thread *td,
1160 		       struct freebsd32_settimeofday_args *uap)
1161 {
1162 	struct timeval32 tv32;
1163 	struct timeval tv, *tvp;
1164 	struct timezone tz, *tzp;
1165 	int error;
1166 
1167 	if (uap->tv) {
1168 		error = copyin(uap->tv, &tv32, sizeof(tv32));
1169 		if (error)
1170 			return (error);
1171 		CP(tv32, tv, tv_sec);
1172 		CP(tv32, tv, tv_usec);
1173 		tvp = &tv;
1174 	} else
1175 		tvp = NULL;
1176 	if (uap->tzp) {
1177 		error = copyin(uap->tzp, &tz, sizeof(tz));
1178 		if (error)
1179 			return (error);
1180 		tzp = &tz;
1181 	} else
1182 		tzp = NULL;
1183 	return (kern_settimeofday(td, tvp, tzp));
1184 }
1185 
1186 int
1187 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1188 {
1189 	struct timeval32 s32[2];
1190 	struct timeval s[2], *sp;
1191 	int error;
1192 
1193 	if (uap->tptr != NULL) {
1194 		error = copyin(uap->tptr, s32, sizeof(s32));
1195 		if (error)
1196 			return (error);
1197 		CP(s32[0], s[0], tv_sec);
1198 		CP(s32[0], s[0], tv_usec);
1199 		CP(s32[1], s[1], tv_sec);
1200 		CP(s32[1], s[1], tv_usec);
1201 		sp = s;
1202 	} else
1203 		sp = NULL;
1204 	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1205 }
1206 
1207 int
1208 freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_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_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1226 }
1227 
1228 int
1229 freebsd32_futimes(struct thread *td, struct freebsd32_futimes_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_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1247 }
1248 
1249 
1250 int
1251 freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1252 {
1253 	struct timeval32 tv32;
1254 	struct timeval delta, olddelta, *deltap;
1255 	int error;
1256 
1257 	if (uap->delta) {
1258 		error = copyin(uap->delta, &tv32, sizeof(tv32));
1259 		if (error)
1260 			return (error);
1261 		CP(tv32, delta, tv_sec);
1262 		CP(tv32, delta, tv_usec);
1263 		deltap = &delta;
1264 	} else
1265 		deltap = NULL;
1266 	error = kern_adjtime(td, deltap, &olddelta);
1267 	if (uap->olddelta && error == 0) {
1268 		CP(olddelta, tv32, tv_sec);
1269 		CP(olddelta, tv32, tv_usec);
1270 		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1271 	}
1272 	return (error);
1273 }
1274 
1275 #ifdef COMPAT_FREEBSD4
1276 int
1277 freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1278 {
1279 	struct statfs32 s32;
1280 	struct statfs s;
1281 	int error;
1282 
1283 	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1284 	if (error)
1285 		return (error);
1286 	copy_statfs(&s, &s32);
1287 	return (copyout(&s32, uap->buf, sizeof(s32)));
1288 }
1289 #endif
1290 
1291 #ifdef COMPAT_FREEBSD4
1292 int
1293 freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1294 {
1295 	struct statfs32 s32;
1296 	struct statfs s;
1297 	int error;
1298 
1299 	error = kern_fstatfs(td, uap->fd, &s);
1300 	if (error)
1301 		return (error);
1302 	copy_statfs(&s, &s32);
1303 	return (copyout(&s32, uap->buf, sizeof(s32)));
1304 }
1305 #endif
1306 
1307 #ifdef COMPAT_FREEBSD4
1308 int
1309 freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1310 {
1311 	struct statfs32 s32;
1312 	struct statfs s;
1313 	fhandle_t fh;
1314 	int error;
1315 
1316 	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1317 		return (error);
1318 	error = kern_fhstatfs(td, fh, &s);
1319 	if (error)
1320 		return (error);
1321 	copy_statfs(&s, &s32);
1322 	return (copyout(&s32, uap->buf, sizeof(s32)));
1323 }
1324 #endif
1325 
1326 int
1327 freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1328 {
1329 	/*
1330 	 * Vector through to semsys if it is loaded.
1331 	 */
1332 	return sysent[SYS_semsys].sy_call(td, uap);
1333 }
1334 
1335 int
1336 freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1337 {
1338 	/*
1339 	 * Vector through to msgsys if it is loaded.
1340 	 */
1341 	return sysent[SYS_msgsys].sy_call(td, uap);
1342 }
1343 
1344 int
1345 freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1346 {
1347 
1348 	switch (uap->which) {
1349 	case 0:	{	/* shmat */
1350 		struct shmat_args ap;
1351 
1352 		ap.shmid = uap->a2;
1353 		ap.shmaddr = PTRIN(uap->a3);
1354 		ap.shmflg = uap->a4;
1355 		return (sysent[SYS_shmat].sy_call(td, &ap));
1356 	}
1357 	case 2: {	/* shmdt */
1358 		struct shmdt_args ap;
1359 
1360 		ap.shmaddr = PTRIN(uap->a2);
1361 		return (sysent[SYS_shmdt].sy_call(td, &ap));
1362 	}
1363 	case 3: {	/* shmget */
1364 		struct shmget_args ap;
1365 
1366 		ap.key = uap->a2;
1367 		ap.size = uap->a3;
1368 		ap.shmflg = uap->a4;
1369 		return (sysent[SYS_shmget].sy_call(td, &ap));
1370 	}
1371 	case 4: {	/* shmctl */
1372 		struct freebsd32_shmctl_args ap;
1373 
1374 		ap.shmid = uap->a2;
1375 		ap.cmd = uap->a3;
1376 		ap.buf = PTRIN(uap->a4);
1377 		return (freebsd32_shmctl(td, &ap));
1378 	}
1379 	case 1:		/* oshmctl */
1380 	default:
1381 		return (EINVAL);
1382 	}
1383 }
1384 
1385 struct ipc_perm32 {
1386 	uint16_t	cuid;
1387 	uint16_t	cgid;
1388 	uint16_t	uid;
1389 	uint16_t	gid;
1390 	uint16_t	mode;
1391 	uint16_t	seq;
1392 	uint32_t	key;
1393 };
1394 struct shmid_ds32 {
1395 	struct ipc_perm32 shm_perm;
1396 	int32_t		shm_segsz;
1397 	int32_t		shm_lpid;
1398 	int32_t		shm_cpid;
1399 	int16_t		shm_nattch;
1400 	int32_t		shm_atime;
1401 	int32_t		shm_dtime;
1402 	int32_t		shm_ctime;
1403 	uint32_t	shm_internal;
1404 };
1405 struct shm_info32 {
1406 	int32_t		used_ids;
1407 	uint32_t	shm_tot;
1408 	uint32_t	shm_rss;
1409 	uint32_t	shm_swp;
1410 	uint32_t	swap_attempts;
1411 	uint32_t	swap_successes;
1412 };
1413 struct shminfo32 {
1414 	uint32_t	shmmax;
1415 	uint32_t	shmmin;
1416 	uint32_t	shmmni;
1417 	uint32_t	shmseg;
1418 	uint32_t	shmall;
1419 };
1420 
1421 int
1422 freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
1423 {
1424 	int error = 0;
1425 	union {
1426 		struct shmid_ds shmid_ds;
1427 		struct shm_info shm_info;
1428 		struct shminfo shminfo;
1429 	} u;
1430 	union {
1431 		struct shmid_ds32 shmid_ds32;
1432 		struct shm_info32 shm_info32;
1433 		struct shminfo32 shminfo32;
1434 	} u32;
1435 	size_t sz;
1436 
1437 	if (uap->cmd == IPC_SET) {
1438 		if ((error = copyin(uap->buf, &u32.shmid_ds32,
1439 		    sizeof(u32.shmid_ds32))))
1440 			goto done;
1441 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cuid);
1442 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cgid);
1443 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.uid);
1444 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.gid);
1445 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.mode);
1446 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.seq);
1447 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.key);
1448 		CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1449 		CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1450 		CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1451 		CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1452 		CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1453 		CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1454 		CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1455 		PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal);
1456 	}
1457 
1458 	error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1459 	if (error)
1460 		goto done;
1461 
1462 	/* Cases in which we need to copyout */
1463 	switch (uap->cmd) {
1464 	case IPC_INFO:
1465 		CP(u.shminfo, u32.shminfo32, shmmax);
1466 		CP(u.shminfo, u32.shminfo32, shmmin);
1467 		CP(u.shminfo, u32.shminfo32, shmmni);
1468 		CP(u.shminfo, u32.shminfo32, shmseg);
1469 		CP(u.shminfo, u32.shminfo32, shmall);
1470 		error = copyout(&u32.shminfo32, uap->buf,
1471 		    sizeof(u32.shminfo32));
1472 		break;
1473 	case SHM_INFO:
1474 		CP(u.shm_info, u32.shm_info32, used_ids);
1475 		CP(u.shm_info, u32.shm_info32, shm_rss);
1476 		CP(u.shm_info, u32.shm_info32, shm_tot);
1477 		CP(u.shm_info, u32.shm_info32, shm_swp);
1478 		CP(u.shm_info, u32.shm_info32, swap_attempts);
1479 		CP(u.shm_info, u32.shm_info32, swap_successes);
1480 		error = copyout(&u32.shm_info32, uap->buf,
1481 		    sizeof(u32.shm_info32));
1482 		break;
1483 	case SHM_STAT:
1484 	case IPC_STAT:
1485 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cuid);
1486 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cgid);
1487 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.uid);
1488 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.gid);
1489 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.mode);
1490 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.seq);
1491 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.key);
1492 		CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1493 		CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1494 		CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1495 		CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1496 		CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1497 		CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1498 		CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1499 		PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal);
1500 		error = copyout(&u32.shmid_ds32, uap->buf,
1501 		    sizeof(u32.shmid_ds32));
1502 		break;
1503 	}
1504 
1505 done:
1506 	if (error) {
1507 		/* Invalidate the return value */
1508 		td->td_retval[0] = -1;
1509 	}
1510 	return (error);
1511 }
1512 
1513 int
1514 freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1515 {
1516 	struct pread_args ap;
1517 
1518 	ap.fd = uap->fd;
1519 	ap.buf = uap->buf;
1520 	ap.nbyte = uap->nbyte;
1521 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1522 	return (pread(td, &ap));
1523 }
1524 
1525 int
1526 freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1527 {
1528 	struct pwrite_args ap;
1529 
1530 	ap.fd = uap->fd;
1531 	ap.buf = uap->buf;
1532 	ap.nbyte = uap->nbyte;
1533 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1534 	return (pwrite(td, &ap));
1535 }
1536 
1537 int
1538 freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1539 {
1540 	int error;
1541 	struct lseek_args ap;
1542 	off_t pos;
1543 
1544 	ap.fd = uap->fd;
1545 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1546 	ap.whence = uap->whence;
1547 	error = lseek(td, &ap);
1548 	/* Expand the quad return into two parts for eax and edx */
1549 	pos = *(off_t *)(td->td_retval);
1550 	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1551 	td->td_retval[1] = pos >> 32;		/* %edx */
1552 	return error;
1553 }
1554 
1555 int
1556 freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1557 {
1558 	struct truncate_args ap;
1559 
1560 	ap.path = uap->path;
1561 	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1562 	return (truncate(td, &ap));
1563 }
1564 
1565 int
1566 freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1567 {
1568 	struct ftruncate_args ap;
1569 
1570 	ap.fd = uap->fd;
1571 	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1572 	return (ftruncate(td, &ap));
1573 }
1574 
1575 struct sf_hdtr32 {
1576 	uint32_t headers;
1577 	int hdr_cnt;
1578 	uint32_t trailers;
1579 	int trl_cnt;
1580 };
1581 
1582 static int
1583 freebsd32_do_sendfile(struct thread *td,
1584     struct freebsd32_sendfile_args *uap, int compat)
1585 {
1586 	struct sendfile_args ap;
1587 	struct sf_hdtr32 hdtr32;
1588 	struct sf_hdtr hdtr;
1589 	struct uio *hdr_uio, *trl_uio;
1590 	struct iovec32 *iov32;
1591 	int error;
1592 
1593 	hdr_uio = trl_uio = NULL;
1594 
1595 	ap.fd = uap->fd;
1596 	ap.s = uap->s;
1597 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1598 	ap.nbytes = uap->nbytes;
1599 	ap.hdtr = (struct sf_hdtr *)uap->hdtr;		/* XXX not used */
1600 	ap.sbytes = uap->sbytes;
1601 	ap.flags = uap->flags;
1602 
1603 	if (uap->hdtr != NULL) {
1604 		error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
1605 		if (error)
1606 			goto out;
1607 		PTRIN_CP(hdtr32, hdtr, headers);
1608 		CP(hdtr32, hdtr, hdr_cnt);
1609 		PTRIN_CP(hdtr32, hdtr, trailers);
1610 		CP(hdtr32, hdtr, trl_cnt);
1611 
1612 		if (hdtr.headers != NULL) {
1613 			iov32 = PTRIN(hdtr32.headers);
1614 			error = freebsd32_copyinuio(iov32,
1615 			    hdtr32.hdr_cnt, &hdr_uio);
1616 			if (error)
1617 				goto out;
1618 		}
1619 		if (hdtr.trailers != NULL) {
1620 			iov32 = PTRIN(hdtr32.trailers);
1621 			error = freebsd32_copyinuio(iov32,
1622 			    hdtr32.trl_cnt, &trl_uio);
1623 			if (error)
1624 				goto out;
1625 		}
1626 	}
1627 
1628 	error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
1629 out:
1630 	if (hdr_uio)
1631 		free(hdr_uio, M_IOV);
1632 	if (trl_uio)
1633 		free(trl_uio, M_IOV);
1634 	return (error);
1635 }
1636 
1637 #ifdef COMPAT_FREEBSD4
1638 int
1639 freebsd4_freebsd32_sendfile(struct thread *td,
1640     struct freebsd4_freebsd32_sendfile_args *uap)
1641 {
1642 	return (freebsd32_do_sendfile(td,
1643 	    (struct freebsd32_sendfile_args *)uap, 1));
1644 }
1645 #endif
1646 
1647 int
1648 freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1649 {
1650 
1651 	return (freebsd32_do_sendfile(td, uap, 0));
1652 }
1653 
1654 struct stat32 {
1655 	dev_t	st_dev;
1656 	ino_t	st_ino;
1657 	mode_t	st_mode;
1658 	nlink_t	st_nlink;
1659 	uid_t	st_uid;
1660 	gid_t	st_gid;
1661 	dev_t	st_rdev;
1662 	struct timespec32 st_atimespec;
1663 	struct timespec32 st_mtimespec;
1664 	struct timespec32 st_ctimespec;
1665 	off_t	st_size;
1666 	int64_t	st_blocks;
1667 	u_int32_t st_blksize;
1668 	u_int32_t st_flags;
1669 	u_int32_t st_gen;
1670 	struct timespec32 st_birthtimespec;
1671 	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1672 	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1673 };
1674 
1675 
1676 CTASSERT(sizeof(struct stat32) == 96);
1677 
1678 static void
1679 copy_stat( struct stat *in, struct stat32 *out)
1680 {
1681 	CP(*in, *out, st_dev);
1682 	CP(*in, *out, st_ino);
1683 	CP(*in, *out, st_mode);
1684 	CP(*in, *out, st_nlink);
1685 	CP(*in, *out, st_uid);
1686 	CP(*in, *out, st_gid);
1687 	CP(*in, *out, st_rdev);
1688 	TS_CP(*in, *out, st_atimespec);
1689 	TS_CP(*in, *out, st_mtimespec);
1690 	TS_CP(*in, *out, st_ctimespec);
1691 	CP(*in, *out, st_size);
1692 	CP(*in, *out, st_blocks);
1693 	CP(*in, *out, st_blksize);
1694 	CP(*in, *out, st_flags);
1695 	CP(*in, *out, st_gen);
1696 }
1697 
1698 int
1699 freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1700 {
1701 	struct stat sb;
1702 	struct stat32 sb32;
1703 	int error;
1704 
1705 	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1706 	if (error)
1707 		return (error);
1708 	copy_stat(&sb, &sb32);
1709 	error = copyout(&sb32, uap->ub, sizeof (sb32));
1710 	return (error);
1711 }
1712 
1713 int
1714 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1715 {
1716 	struct stat ub;
1717 	struct stat32 ub32;
1718 	int error;
1719 
1720 	error = kern_fstat(td, uap->fd, &ub);
1721 	if (error)
1722 		return (error);
1723 	copy_stat(&ub, &ub32);
1724 	error = copyout(&ub32, uap->ub, sizeof(ub32));
1725 	return (error);
1726 }
1727 
1728 int
1729 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1730 {
1731 	struct stat sb;
1732 	struct stat32 sb32;
1733 	int error;
1734 
1735 	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1736 	if (error)
1737 		return (error);
1738 	copy_stat(&sb, &sb32);
1739 	error = copyout(&sb32, uap->ub, sizeof (sb32));
1740 	return (error);
1741 }
1742 
1743 /*
1744  * MPSAFE
1745  */
1746 int
1747 freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1748 {
1749 	int error, name[CTL_MAXNAME];
1750 	size_t j, oldlen;
1751 
1752 	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1753 		return (EINVAL);
1754  	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1755  	if (error)
1756 		return (error);
1757 	mtx_lock(&Giant);
1758 	if (uap->oldlenp)
1759 		oldlen = fuword32(uap->oldlenp);
1760 	else
1761 		oldlen = 0;
1762 	error = userland_sysctl(td, name, uap->namelen,
1763 		uap->old, &oldlen, 1,
1764 		uap->new, uap->newlen, &j, SCTL_MASK32);
1765 	if (error && error != ENOMEM)
1766 		goto done2;
1767 	if (uap->oldlenp)
1768 		suword32(uap->oldlenp, j);
1769 done2:
1770 	mtx_unlock(&Giant);
1771 	return (error);
1772 }
1773 
1774 struct sigaction32 {
1775 	u_int32_t	sa_u;
1776 	int		sa_flags;
1777 	sigset_t	sa_mask;
1778 };
1779 
1780 CTASSERT(sizeof(struct sigaction32) == 24);
1781 
1782 int
1783 freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1784 {
1785 	struct sigaction32 s32;
1786 	struct sigaction sa, osa, *sap;
1787 	int error;
1788 
1789 	if (uap->act) {
1790 		error = copyin(uap->act, &s32, sizeof(s32));
1791 		if (error)
1792 			return (error);
1793 		sa.sa_handler = PTRIN(s32.sa_u);
1794 		CP(s32, sa, sa_flags);
1795 		CP(s32, sa, sa_mask);
1796 		sap = &sa;
1797 	} else
1798 		sap = NULL;
1799 	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1800 	if (error == 0 && uap->oact != NULL) {
1801 		s32.sa_u = PTROUT(osa.sa_handler);
1802 		CP(osa, s32, sa_flags);
1803 		CP(osa, s32, sa_mask);
1804 		error = copyout(&s32, uap->oact, sizeof(s32));
1805 	}
1806 	return (error);
1807 }
1808 
1809 #ifdef COMPAT_FREEBSD4
1810 int
1811 freebsd4_freebsd32_sigaction(struct thread *td,
1812 			     struct freebsd4_freebsd32_sigaction_args *uap)
1813 {
1814 	struct sigaction32 s32;
1815 	struct sigaction sa, osa, *sap;
1816 	int error;
1817 
1818 	if (uap->act) {
1819 		error = copyin(uap->act, &s32, sizeof(s32));
1820 		if (error)
1821 			return (error);
1822 		sa.sa_handler = PTRIN(s32.sa_u);
1823 		CP(s32, sa, sa_flags);
1824 		CP(s32, sa, sa_mask);
1825 		sap = &sa;
1826 	} else
1827 		sap = NULL;
1828 	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1829 	if (error == 0 && uap->oact != NULL) {
1830 		s32.sa_u = PTROUT(osa.sa_handler);
1831 		CP(osa, s32, sa_flags);
1832 		CP(osa, s32, sa_mask);
1833 		error = copyout(&s32, uap->oact, sizeof(s32));
1834 	}
1835 	return (error);
1836 }
1837 #endif
1838 
1839 #ifdef COMPAT_43
1840 struct osigaction32 {
1841 	u_int32_t	sa_u;
1842 	osigset_t	sa_mask;
1843 	int		sa_flags;
1844 };
1845 
1846 #define	ONSIG	32
1847 
1848 int
1849 ofreebsd32_sigaction(struct thread *td,
1850 			     struct ofreebsd32_sigaction_args *uap)
1851 {
1852 	struct osigaction32 s32;
1853 	struct sigaction sa, osa, *sap;
1854 	int error;
1855 
1856 	if (uap->signum <= 0 || uap->signum >= ONSIG)
1857 		return (EINVAL);
1858 
1859 	if (uap->nsa) {
1860 		error = copyin(uap->nsa, &s32, sizeof(s32));
1861 		if (error)
1862 			return (error);
1863 		sa.sa_handler = PTRIN(s32.sa_u);
1864 		CP(s32, sa, sa_flags);
1865 		OSIG2SIG(s32.sa_mask, sa.sa_mask);
1866 		sap = &sa;
1867 	} else
1868 		sap = NULL;
1869 	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1870 	if (error == 0 && uap->osa != NULL) {
1871 		s32.sa_u = PTROUT(osa.sa_handler);
1872 		CP(osa, s32, sa_flags);
1873 		SIG2OSIG(osa.sa_mask, s32.sa_mask);
1874 		error = copyout(&s32, uap->osa, sizeof(s32));
1875 	}
1876 	return (error);
1877 }
1878 
1879 int
1880 ofreebsd32_sigprocmask(struct thread *td,
1881 			       struct ofreebsd32_sigprocmask_args *uap)
1882 {
1883 	sigset_t set, oset;
1884 	int error;
1885 
1886 	OSIG2SIG(uap->mask, set);
1887 	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
1888 	SIG2OSIG(oset, td->td_retval[0]);
1889 	return (error);
1890 }
1891 
1892 int
1893 ofreebsd32_sigpending(struct thread *td,
1894 			      struct ofreebsd32_sigpending_args *uap)
1895 {
1896 	struct proc *p = td->td_proc;
1897 	sigset_t siglist;
1898 
1899 	PROC_LOCK(p);
1900 	siglist = p->p_siglist;
1901 	SIGSETOR(siglist, td->td_siglist);
1902 	PROC_UNLOCK(p);
1903 	SIG2OSIG(siglist, td->td_retval[0]);
1904 	return (0);
1905 }
1906 
1907 struct sigvec32 {
1908 	u_int32_t	sv_handler;
1909 	int		sv_mask;
1910 	int		sv_flags;
1911 };
1912 
1913 int
1914 ofreebsd32_sigvec(struct thread *td,
1915 			  struct ofreebsd32_sigvec_args *uap)
1916 {
1917 	struct sigvec32 vec;
1918 	struct sigaction sa, osa, *sap;
1919 	int error;
1920 
1921 	if (uap->signum <= 0 || uap->signum >= ONSIG)
1922 		return (EINVAL);
1923 
1924 	if (uap->nsv) {
1925 		error = copyin(uap->nsv, &vec, sizeof(vec));
1926 		if (error)
1927 			return (error);
1928 		sa.sa_handler = PTRIN(vec.sv_handler);
1929 		OSIG2SIG(vec.sv_mask, sa.sa_mask);
1930 		sa.sa_flags = vec.sv_flags;
1931 		sa.sa_flags ^= SA_RESTART;
1932 		sap = &sa;
1933 	} else
1934 		sap = NULL;
1935 	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1936 	if (error == 0 && uap->osv != NULL) {
1937 		vec.sv_handler = PTROUT(osa.sa_handler);
1938 		SIG2OSIG(osa.sa_mask, vec.sv_mask);
1939 		vec.sv_flags = osa.sa_flags;
1940 		vec.sv_flags &= ~SA_NOCLDWAIT;
1941 		vec.sv_flags ^= SA_RESTART;
1942 		error = copyout(&vec, uap->osv, sizeof(vec));
1943 	}
1944 	return (error);
1945 }
1946 
1947 int
1948 ofreebsd32_sigblock(struct thread *td,
1949 			    struct ofreebsd32_sigblock_args *uap)
1950 {
1951 	struct proc *p = td->td_proc;
1952 	sigset_t set;
1953 
1954 	OSIG2SIG(uap->mask, set);
1955 	SIG_CANTMASK(set);
1956 	PROC_LOCK(p);
1957 	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1958 	SIGSETOR(td->td_sigmask, set);
1959 	PROC_UNLOCK(p);
1960 	return (0);
1961 }
1962 
1963 int
1964 ofreebsd32_sigsetmask(struct thread *td,
1965 			      struct ofreebsd32_sigsetmask_args *uap)
1966 {
1967 	struct proc *p = td->td_proc;
1968 	sigset_t set;
1969 
1970 	OSIG2SIG(uap->mask, set);
1971 	SIG_CANTMASK(set);
1972 	PROC_LOCK(p);
1973 	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1974 	SIGSETLO(td->td_sigmask, set);
1975 	signotify(td);
1976 	PROC_UNLOCK(p);
1977 	return (0);
1978 }
1979 
1980 int
1981 ofreebsd32_sigsuspend(struct thread *td,
1982 			      struct ofreebsd32_sigsuspend_args *uap)
1983 {
1984 	struct proc *p = td->td_proc;
1985 	sigset_t mask;
1986 
1987 	PROC_LOCK(p);
1988 	td->td_oldsigmask = td->td_sigmask;
1989 	td->td_pflags |= TDP_OLDMASK;
1990 	OSIG2SIG(uap->mask, mask);
1991 	SIG_CANTMASK(mask);
1992 	SIGSETLO(td->td_sigmask, mask);
1993 	signotify(td);
1994 	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
1995 		/* void */;
1996 	PROC_UNLOCK(p);
1997 	/* always return EINTR rather than ERESTART... */
1998 	return (EINTR);
1999 }
2000 
2001 struct sigstack32 {
2002 	u_int32_t	ss_sp;
2003 	int		ss_onstack;
2004 };
2005 
2006 int
2007 ofreebsd32_sigstack(struct thread *td,
2008 			    struct ofreebsd32_sigstack_args *uap)
2009 {
2010 	struct sigstack32 s32;
2011 	struct sigstack nss, oss;
2012 	int error = 0;
2013 
2014 	if (uap->nss != NULL) {
2015 		error = copyin(uap->nss, &s32, sizeof(s32));
2016 		if (error)
2017 			return (error);
2018 		nss.ss_sp = PTRIN(s32.ss_sp);
2019 		CP(s32, nss, ss_onstack);
2020 	}
2021 	oss.ss_sp = td->td_sigstk.ss_sp;
2022 	oss.ss_onstack = sigonstack(cpu_getstack(td));
2023 	if (uap->nss != NULL) {
2024 		td->td_sigstk.ss_sp = nss.ss_sp;
2025 		td->td_sigstk.ss_size = 0;
2026 		td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK;
2027 		td->td_pflags |= TDP_ALTSTACK;
2028 	}
2029 	if (uap->oss != NULL) {
2030 		s32.ss_sp = PTROUT(oss.ss_sp);
2031 		CP(oss, s32, ss_onstack);
2032 		error = copyout(&s32, uap->oss, sizeof(s32));
2033 	}
2034 	return (error);
2035 }
2036 #endif
2037 
2038 int
2039 freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
2040 {
2041 	struct timespec32 rmt32, rqt32;
2042 	struct timespec rmt, rqt;
2043 	int error;
2044 
2045 	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
2046 	if (error)
2047 		return (error);
2048 
2049 	CP(rqt32, rqt, tv_sec);
2050 	CP(rqt32, rqt, tv_nsec);
2051 
2052 	if (uap->rmtp &&
2053 	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
2054 		return (EFAULT);
2055 	error = kern_nanosleep(td, &rqt, &rmt);
2056 	if (error && uap->rmtp) {
2057 		int error2;
2058 
2059 		CP(rmt, rmt32, tv_sec);
2060 		CP(rmt, rmt32, tv_nsec);
2061 
2062 		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
2063 		if (error2)
2064 			error = error2;
2065 	}
2066 	return (error);
2067 }
2068 
2069 int
2070 freebsd32_clock_gettime(struct thread *td,
2071 			struct freebsd32_clock_gettime_args *uap)
2072 {
2073 	struct timespec	ats;
2074 	struct timespec32 ats32;
2075 	int error;
2076 
2077 	error = kern_clock_gettime(td, uap->clock_id, &ats);
2078 	if (error == 0) {
2079 		CP(ats, ats32, tv_sec);
2080 		CP(ats, ats32, tv_nsec);
2081 		error = copyout(&ats32, uap->tp, sizeof(ats32));
2082 	}
2083 	return (error);
2084 }
2085 
2086 int
2087 freebsd32_clock_settime(struct thread *td,
2088 			struct freebsd32_clock_settime_args *uap)
2089 {
2090 	struct timespec	ats;
2091 	struct timespec32 ats32;
2092 	int error;
2093 
2094 	error = copyin(uap->tp, &ats32, sizeof(ats32));
2095 	if (error)
2096 		return (error);
2097 	CP(ats32, ats, tv_sec);
2098 	CP(ats32, ats, tv_nsec);
2099 
2100 	return (kern_clock_settime(td, uap->clock_id, &ats));
2101 }
2102 
2103 int
2104 freebsd32_clock_getres(struct thread *td,
2105 		       struct freebsd32_clock_getres_args *uap)
2106 {
2107 	struct timespec	ts;
2108 	struct timespec32 ts32;
2109 	int error;
2110 
2111 	if (uap->tp == NULL)
2112 		return (0);
2113 	error = kern_clock_getres(td, uap->clock_id, &ts);
2114 	if (error == 0) {
2115 		CP(ts, ts32, tv_sec);
2116 		CP(ts, ts32, tv_nsec);
2117 		error = copyout(&ts32, uap->tp, sizeof(ts32));
2118 	}
2119 	return (error);
2120 }
2121 
2122 int
2123 freebsd32_thr_new(struct thread *td,
2124 		  struct freebsd32_thr_new_args *uap)
2125 {
2126 	struct thr_param32 param32;
2127 	struct thr_param param;
2128 	int error;
2129 
2130 	if (uap->param_size < 0 ||
2131 	    uap->param_size > sizeof(struct thr_param32))
2132 		return (EINVAL);
2133 	bzero(&param, sizeof(struct thr_param));
2134 	bzero(&param32, sizeof(struct thr_param32));
2135 	error = copyin(uap->param, &param32, uap->param_size);
2136 	if (error != 0)
2137 		return (error);
2138 	param.start_func = PTRIN(param32.start_func);
2139 	param.arg = PTRIN(param32.arg);
2140 	param.stack_base = PTRIN(param32.stack_base);
2141 	param.stack_size = param32.stack_size;
2142 	param.tls_base = PTRIN(param32.tls_base);
2143 	param.tls_size = param32.tls_size;
2144 	param.child_tid = PTRIN(param32.child_tid);
2145 	param.parent_tid = PTRIN(param32.parent_tid);
2146 	param.flags = param32.flags;
2147 	param.rtp = PTRIN(param32.rtp);
2148 	param.spare[0] = PTRIN(param32.spare[0]);
2149 	param.spare[1] = PTRIN(param32.spare[1]);
2150 	param.spare[2] = PTRIN(param32.spare[2]);
2151 
2152 	return (kern_thr_new(td, &param));
2153 }
2154 
2155 int
2156 freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
2157 {
2158 	struct timespec32 ts32;
2159 	struct timespec ts, *tsp;
2160 	int error;
2161 
2162 	error = 0;
2163 	tsp = NULL;
2164 	if (uap->timeout != NULL) {
2165 		error = copyin((const void *)uap->timeout, (void *)&ts32,
2166 		    sizeof(struct timespec32));
2167 		if (error != 0)
2168 			return (error);
2169 		ts.tv_sec = ts32.tv_sec;
2170 		ts.tv_nsec = ts32.tv_nsec;
2171 		tsp = &ts;
2172 	}
2173 	return (kern_thr_suspend(td, tsp));
2174 }
2175 
2176 void
2177 siginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst)
2178 {
2179 	bzero(dst, sizeof(*dst));
2180 	dst->si_signo = src->si_signo;
2181 	dst->si_errno = src->si_errno;
2182 	dst->si_code = src->si_code;
2183 	dst->si_pid = src->si_pid;
2184 	dst->si_uid = src->si_uid;
2185 	dst->si_status = src->si_status;
2186 	dst->si_addr = dst->si_addr;
2187 	dst->si_value.sigval_int = src->si_value.sival_int;
2188 	dst->si_timerid = src->si_timerid;
2189 	dst->si_overrun = src->si_overrun;
2190 }
2191 
2192 int
2193 freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
2194 {
2195 	struct timespec32 ts32;
2196 	struct timespec ts;
2197 	struct timespec *timeout;
2198 	sigset_t set;
2199 	ksiginfo_t ksi;
2200 	struct siginfo32 si32;
2201 	int error;
2202 
2203 	if (uap->timeout) {
2204 		error = copyin(uap->timeout, &ts32, sizeof(ts32));
2205 		if (error)
2206 			return (error);
2207 		ts.tv_sec = ts32.tv_sec;
2208 		ts.tv_nsec = ts32.tv_nsec;
2209 		timeout = &ts;
2210 	} else
2211 		timeout = NULL;
2212 
2213 	error = copyin(uap->set, &set, sizeof(set));
2214 	if (error)
2215 		return (error);
2216 
2217 	error = kern_sigtimedwait(td, set, &ksi, timeout);
2218 	if (error)
2219 		return (error);
2220 
2221 	if (uap->info) {
2222 		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2223 		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2224 	}
2225 
2226 	if (error == 0)
2227 		td->td_retval[0] = ksi.ksi_signo;
2228 	return (error);
2229 }
2230 
2231 /*
2232  * MPSAFE
2233  */
2234 int
2235 freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
2236 {
2237 	ksiginfo_t ksi;
2238 	struct siginfo32 si32;
2239 	sigset_t set;
2240 	int error;
2241 
2242 	error = copyin(uap->set, &set, sizeof(set));
2243 	if (error)
2244 		return (error);
2245 
2246 	error = kern_sigtimedwait(td, set, &ksi, NULL);
2247 	if (error)
2248 		return (error);
2249 
2250 	if (uap->info) {
2251 		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2252 		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2253 	}
2254 	if (error == 0)
2255 		td->td_retval[0] = ksi.ksi_signo;
2256 	return (error);
2257 }
2258 
2259 #if 0
2260 
2261 int
2262 freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
2263 {
2264 	int error;
2265 	struct yyy32 *p32, s32;
2266 	struct yyy *p = NULL, s;
2267 
2268 	if (uap->zzz) {
2269 		error = copyin(uap->zzz, &s32, sizeof(s32));
2270 		if (error)
2271 			return (error);
2272 		/* translate in */
2273 		p = &s;
2274 	}
2275 	error = kern_xxx(td, p);
2276 	if (error)
2277 		return (error);
2278 	if (uap->zzz) {
2279 		/* translate out */
2280 		error = copyout(&s32, p32, sizeof(s32));
2281 	}
2282 	return (error);
2283 }
2284 
2285 #endif
2286