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