[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/freebsd32/freebsd32_misc.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  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: src/sys/compat/freebsd32/freebsd32_misc.c,v 1.86 2008/12/29 12:58:45 ed Exp $");
 29 
 30 #include "opt_compat.h"
 31 
 32 #include <sys/param.h>
 33 #include <sys/bus.h>
 34 #include <sys/clock.h>
 35 #include <sys/exec.h>
 36 #include <sys/fcntl.h>
 37 #include <sys/filedesc.h>
 38 #include <sys/imgact.h>
 39 #include <sys/jail.h>
 40 #include <sys/kernel.h>
 41 #include <sys/limits.h>
 42 #include <sys/lock.h>
 43 #include <sys/malloc.h>
 44 #include <sys/file.h>           /* Must come after sys/malloc.h */
 45 #include <sys/mbuf.h>
 46 #include <sys/mman.h>
 47 #include <sys/module.h>
 48 #include <sys/mount.h>
 49 #include <sys/mutex.h>
 50 #include <sys/namei.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/thr.h>
 70 #include <sys/unistd.h>
 71 #include <sys/ucontext.h>
 72 #include <sys/vnode.h>
 73 #include <sys/wait.h>
 74 #include <sys/ipc.h>
 75 #include <sys/msg.h>
 76 #include <sys/sem.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 <security/audit/audit.h>
 90 
 91 #include <compat/freebsd32/freebsd32_util.h>
 92 #include <compat/freebsd32/freebsd32.h>
 93 #include <compat/freebsd32/freebsd32_ipc.h>
 94 #include <compat/freebsd32/freebsd32_signal.h>
 95 #include <compat/freebsd32/freebsd32_proto.h>
 96 
 97 CTASSERT(sizeof(struct timeval32) == 8);
 98 CTASSERT(sizeof(struct timespec32) == 8);
 99 CTASSERT(sizeof(struct itimerval32) == 16);
100 CTASSERT(sizeof(struct statfs32) == 256);
101 CTASSERT(sizeof(struct rusage32) == 72);
102 CTASSERT(sizeof(struct sigaltstack32) == 12);
103 CTASSERT(sizeof(struct kevent32) == 20);
104 CTASSERT(sizeof(struct iovec32) == 8);
105 CTASSERT(sizeof(struct msghdr32) == 28);
106 CTASSERT(sizeof(struct stat32) == 96);
107 CTASSERT(sizeof(struct sigaction32) == 24);
108 
109 static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
110 static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
111 
112 int
113 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
114 {
115         int error, status;
116         struct rusage32 ru32;
117         struct rusage ru, *rup;
118 
119         if (uap->rusage != NULL)
120                 rup = &ru;
121         else
122                 rup = NULL;
123         error = kern_wait(td, uap->pid, &status, uap->options, rup);
124         if (error)
125                 return (error);
126         if (uap->status != NULL)
127                 error = copyout(&status, uap->status, sizeof(status));
128         if (uap->rusage != NULL && error == 0) {
129                 TV_CP(ru, ru32, ru_utime);
130                 TV_CP(ru, ru32, ru_stime);
131                 CP(ru, ru32, ru_maxrss);
132                 CP(ru, ru32, ru_ixrss);
133                 CP(ru, ru32, ru_idrss);
134                 CP(ru, ru32, ru_isrss);
135                 CP(ru, ru32, ru_minflt);
136                 CP(ru, ru32, ru_majflt);
137                 CP(ru, ru32, ru_nswap);
138                 CP(ru, ru32, ru_inblock);
139                 CP(ru, ru32, ru_oublock);
140                 CP(ru, ru32, ru_msgsnd);
141                 CP(ru, ru32, ru_msgrcv);
142                 CP(ru, ru32, ru_nsignals);
143                 CP(ru, ru32, ru_nvcsw);
144                 CP(ru, ru32, ru_nivcsw);
145                 error = copyout(&ru32, uap->rusage, sizeof(ru32));
146         }
147         return (error);
148 }
149 
150 #ifdef COMPAT_FREEBSD4
151 static void
152 copy_statfs(struct statfs *in, struct statfs32 *out)
153 {
154 
155         statfs_scale_blocks(in, INT32_MAX);
156         bzero(out, sizeof(*out));
157         CP(*in, *out, f_bsize);
158         out->f_iosize = MIN(in->f_iosize, INT32_MAX);
159         CP(*in, *out, f_blocks);
160         CP(*in, *out, f_bfree);
161         CP(*in, *out, f_bavail);
162         out->f_files = MIN(in->f_files, INT32_MAX);
163         out->f_ffree = MIN(in->f_ffree, INT32_MAX);
164         CP(*in, *out, f_fsid);
165         CP(*in, *out, f_owner);
166         CP(*in, *out, f_type);
167         CP(*in, *out, f_flags);
168         out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
169         out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
170         strlcpy(out->f_fstypename,
171               in->f_fstypename, MFSNAMELEN);
172         strlcpy(out->f_mntonname,
173               in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
174         out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
175         out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
176         strlcpy(out->f_mntfromname,
177               in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
178 }
179 #endif
180 
181 #ifdef COMPAT_FREEBSD4
182 int
183 freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
184 {
185         struct statfs *buf, *sp;
186         struct statfs32 stat32;
187         size_t count, size;
188         int error;
189 
190         count = uap->bufsize / sizeof(struct statfs32);
191         size = count * sizeof(struct statfs);
192         error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
193         if (size > 0) {
194                 count = td->td_retval[0];
195                 sp = buf;
196                 while (count > 0 && error == 0) {
197                         copy_statfs(sp, &stat32);
198                         error = copyout(&stat32, uap->buf, sizeof(stat32));
199                         sp++;
200                         uap->buf++;
201                         count--;
202                 }
203                 free(buf, M_TEMP);
204         }
205         return (error);
206 }
207 #endif
208 
209 int
210 freebsd32_sigaltstack(struct thread *td,
211                       struct freebsd32_sigaltstack_args *uap)
212 {
213         struct sigaltstack32 s32;
214         struct sigaltstack ss, oss, *ssp;
215         int error;
216 
217         if (uap->ss != NULL) {
218                 error = copyin(uap->ss, &s32, sizeof(s32));
219                 if (error)
220                         return (error);
221                 PTRIN_CP(s32, ss, ss_sp);
222                 CP(s32, ss, ss_size);
223                 CP(s32, ss, ss_flags);
224                 ssp = &ss;
225         } else
226                 ssp = NULL;
227         error = kern_sigaltstack(td, ssp, &oss);
228         if (error == 0 && uap->oss != NULL) {
229                 PTROUT_CP(oss, s32, ss_sp);
230                 CP(oss, s32, ss_size);
231                 CP(oss, s32, ss_flags);
232                 error = copyout(&s32, uap->oss, sizeof(s32));
233         }
234         return (error);
235 }
236 
237 /*
238  * Custom version of exec_copyin_args() so that we can translate
239  * the pointers.
240  */
241 static int
242 freebsd32_exec_copyin_args(struct image_args *args, char *fname,
243     enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
244 {
245         char *argp, *envp;
246         u_int32_t *p32, arg;
247         size_t length;
248         int error;
249 
250         bzero(args, sizeof(*args));
251         if (argv == NULL)
252                 return (EFAULT);
253 
254         /*
255          * Allocate temporary demand zeroed space for argument and
256          *      environment strings
257          */
258         args->buf = (char *) kmem_alloc_wait(exec_map,
259             PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
260         if (args->buf == NULL)
261                 return (ENOMEM);
262         args->begin_argv = args->buf;
263         args->endp = args->begin_argv;
264         args->stringspace = ARG_MAX;
265 
266         /*
267          * Copy the file name.
268          */
269         if (fname != NULL) {
270                 args->fname = args->buf + ARG_MAX;
271                 error = (segflg == UIO_SYSSPACE) ?
272                     copystr(fname, args->fname, PATH_MAX, &length) :
273                     copyinstr(fname, args->fname, PATH_MAX, &length);
274                 if (error != 0)
275                         goto err_exit;
276         } else
277                 args->fname = NULL;
278 
279         /*
280          * extract arguments first
281          */
282         p32 = argv;
283         for (;;) {
284                 error = copyin(p32++, &arg, sizeof(arg));
285                 if (error)
286                         goto err_exit;
287                 if (arg == 0)
288                         break;
289                 argp = PTRIN(arg);
290                 error = copyinstr(argp, args->endp, args->stringspace, &length);
291                 if (error) {
292                         if (error == ENAMETOOLONG)
293                                 error = E2BIG;
294                         goto err_exit;
295                 }
296                 args->stringspace -= length;
297                 args->endp += length;
298                 args->argc++;
299         }
300                         
301         args->begin_envv = args->endp;
302 
303         /*
304          * extract environment strings
305          */
306         if (envv) {
307                 p32 = envv;
308                 for (;;) {
309                         error = copyin(p32++, &arg, sizeof(arg));
310                         if (error)
311                                 goto err_exit;
312                         if (arg == 0)
313                                 break;
314                         envp = PTRIN(arg);
315                         error = copyinstr(envp, args->endp, args->stringspace,
316                             &length);
317                         if (error) {
318                                 if (error == ENAMETOOLONG)
319                                         error = E2BIG;
320                                 goto err_exit;
321                         }
322                         args->stringspace -= length;
323                         args->endp += length;
324                         args->envc++;
325                 }
326         }
327 
328         return (0);
329 
330 err_exit:
331         kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
332             PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
333         args->buf = NULL;
334         return (error);
335 }
336 
337 int
338 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
339 {
340         struct image_args eargs;
341         int error;
342 
343         error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
344             uap->argv, uap->envv);
345         if (error == 0)
346                 error = kern_execve(td, &eargs, NULL);
347         return (error);
348 }
349 
350 int
351 freebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
352 {
353         struct image_args eargs;
354         int error;
355 
356         error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE,
357             uap->argv, uap->envv);
358         if (error == 0) {
359                 eargs.fd = uap->fd;
360                 error = kern_execve(td, &eargs, NULL);
361         }
362         return (error);
363 }
364 
365 #ifdef __ia64__
366 static int
367 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
368                        int prot, int fd, off_t pos)
369 {
370         vm_map_t map;
371         vm_map_entry_t entry;
372         int rv;
373 
374         map = &td->td_proc->p_vmspace->vm_map;
375         if (fd != -1)
376                 prot |= VM_PROT_WRITE;
377 
378         if (vm_map_lookup_entry(map, start, &entry)) {
379                 if ((entry->protection & prot) != prot) {
380                         rv = vm_map_protect(map,
381                                             trunc_page(start),
382                                             round_page(end),
383                                             entry->protection | prot,
384                                             FALSE);
385                         if (rv != KERN_SUCCESS)
386                                 return (EINVAL);
387                 }
388         } else {
389                 vm_offset_t addr = trunc_page(start);
390                 rv = vm_map_find(map, 0, 0,
391                                  &addr, PAGE_SIZE, FALSE, prot,
392                                  VM_PROT_ALL, 0);
393                 if (rv != KERN_SUCCESS)
394                         return (EINVAL);
395         }
396 
397         if (fd != -1) {
398                 struct pread_args r;
399                 r.fd = fd;
400                 r.buf = (void *) start;
401                 r.nbyte = end - start;
402                 r.offset = pos;
403                 return (pread(td, &r));
404         } else {
405                 while (start < end) {
406                         subyte((void *) start, 0);
407                         start++;
408                 }
409                 return (0);
410         }
411 }
412 #endif
413 
414 int
415 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
416 {
417         struct mmap_args ap;
418         vm_offset_t addr = (vm_offset_t) uap->addr;
419         vm_size_t len    = uap->len;
420         int prot         = uap->prot;
421         int flags        = uap->flags;
422         int fd           = uap->fd;
423         off_t pos        = (uap->poslo
424                             | ((off_t)uap->poshi << 32));
425 #ifdef __ia64__
426         vm_size_t pageoff;
427         int error;
428 
429         /*
430          * Attempt to handle page size hassles.
431          */
432         pageoff = (pos & PAGE_MASK);
433         if (flags & MAP_FIXED) {
434                 vm_offset_t start, end;
435                 start = addr;
436                 end = addr + len;
437 
438                 if (start != trunc_page(start)) {
439                         error = freebsd32_mmap_partial(td, start,
440                                                        round_page(start), prot,
441                                                        fd, pos);
442                         if (fd != -1)
443                                 pos += round_page(start) - start;
444                         start = round_page(start);
445                 }
446                 if (end != round_page(end)) {
447                         vm_offset_t t = trunc_page(end);
448                         error = freebsd32_mmap_partial(td, t, end,
449                                                   prot, fd,
450                                                   pos + t - start);
451                         end = trunc_page(end);
452                 }
453                 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
454                         /*
455                          * We can't map this region at all. The specified
456                          * address doesn't have the same alignment as the file
457                          * position. Fake the mapping by simply reading the
458                          * entire region into memory. First we need to make
459                          * sure the region exists.
460                          */
461                         vm_map_t map;
462                         struct pread_args r;
463                         int rv;
464 
465                         prot |= VM_PROT_WRITE;
466                         map = &td->td_proc->p_vmspace->vm_map;
467                         rv = vm_map_remove(map, start, end);
468                         if (rv != KERN_SUCCESS)
469                                 return (EINVAL);
470                         rv = vm_map_find(map, 0, 0,
471                                          &start, end - start, FALSE,
472                                          prot, VM_PROT_ALL, 0);
473                         if (rv != KERN_SUCCESS)
474                                 return (EINVAL);
475                         r.fd = fd;
476                         r.buf = (void *) start;
477                         r.nbyte = end - start;
478                         r.offset = pos;
479                         error = pread(td, &r);
480                         if (error)
481                                 return (error);
482 
483                         td->td_retval[0] = addr;
484                         return (0);
485                 }
486                 if (end == start) {
487                         /*
488                          * After dealing with the ragged ends, there
489                          * might be none left.
490                          */
491                         td->td_retval[0] = addr;
492                         return (0);
493                 }
494                 addr = start;
495                 len = end - start;
496         }
497 #endif
498 
499         ap.addr = (void *) addr;
500         ap.len = len;
501         ap.prot = prot;
502         ap.flags = flags;
503         ap.fd = fd;
504         ap.pos = pos;
505 
506         return (mmap(td, &ap));
507 }
508 
509 #ifdef COMPAT_FREEBSD6
510 int
511 freebsd6_freebsd32_mmap(struct thread *td, struct freebsd6_freebsd32_mmap_args *uap)
512 {
513         struct freebsd32_mmap_args ap;
514 
515         ap.addr = uap->addr;
516         ap.len = uap->len;
517         ap.prot = uap->prot;
518         ap.flags = uap->flags;
519         ap.fd = uap->fd;
520         ap.poslo = uap->poslo;
521         ap.poshi = uap->poshi;
522 
523         return (freebsd32_mmap(td, &ap));
524 }
525 #endif
526 
527 int
528 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
529 {
530         struct itimerval itv, oitv, *itvp;      
531         struct itimerval32 i32;
532         int error;
533 
534         if (uap->itv != NULL) {
535                 error = copyin(uap->itv, &i32, sizeof(i32));
536                 if (error)
537                         return (error);
538                 TV_CP(i32, itv, it_interval);
539                 TV_CP(i32, itv, it_value);
540                 itvp = &itv;
541         } else
542                 itvp = NULL;
543         error = kern_setitimer(td, uap->which, itvp, &oitv);
544         if (error || uap->oitv == NULL)
545                 return (error);
546         TV_CP(oitv, i32, it_interval);
547         TV_CP(oitv, i32, it_value);
548         return (copyout(&i32, uap->oitv, sizeof(i32)));
549 }
550 
551 int
552 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
553 {
554         struct itimerval itv;
555         struct itimerval32 i32;
556         int error;
557 
558         error = kern_getitimer(td, uap->which, &itv);
559         if (error || uap->itv == NULL)
560                 return (error);
561         TV_CP(itv, i32, it_interval);
562         TV_CP(itv, i32, it_value);
563         return (copyout(&i32, uap->itv, sizeof(i32)));
564 }
565 
566 int
567 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
568 {
569         struct timeval32 tv32;
570         struct timeval tv, *tvp;
571         int error;
572 
573         if (uap->tv != NULL) {
574                 error = copyin(uap->tv, &tv32, sizeof(tv32));
575                 if (error)
576                         return (error);
577                 CP(tv32, tv, tv_sec);
578                 CP(tv32, tv, tv_usec);
579                 tvp = &tv;
580         } else
581                 tvp = NULL;
582         /*
583          * XXX big-endian needs to convert the fd_sets too.
584          * XXX Do pointers need PTRIN()?
585          */
586         return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
587 }
588 
589 /*
590  * Copy 'count' items into the destination list pointed to by uap->eventlist.
591  */
592 static int
593 freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
594 {
595         struct freebsd32_kevent_args *uap;
596         struct kevent32 ks32[KQ_NEVENTS];
597         int i, error = 0;
598 
599         KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
600         uap = (struct freebsd32_kevent_args *)arg;
601 
602         for (i = 0; i < count; i++) {
603                 CP(kevp[i], ks32[i], ident);
604                 CP(kevp[i], ks32[i], filter);
605                 CP(kevp[i], ks32[i], flags);
606                 CP(kevp[i], ks32[i], fflags);
607                 CP(kevp[i], ks32[i], data);
608                 PTROUT_CP(kevp[i], ks32[i], udata);
609         }
610         error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
611         if (error == 0)
612                 uap->eventlist += count;
613         return (error);
614 }
615 
616 /*
617  * Copy 'count' items from the list pointed to by uap->changelist.
618  */
619 static int
620 freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
621 {
622         struct freebsd32_kevent_args *uap;
623         struct kevent32 ks32[KQ_NEVENTS];
624         int i, error = 0;
625 
626         KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
627         uap = (struct freebsd32_kevent_args *)arg;
628 
629         error = copyin(uap->changelist, ks32, count * sizeof *ks32);
630         if (error)
631                 goto done;
632         uap->changelist += count;
633 
634         for (i = 0; i < count; i++) {
635                 CP(ks32[i], kevp[i], ident);
636                 CP(ks32[i], kevp[i], filter);
637                 CP(ks32[i], kevp[i], flags);
638                 CP(ks32[i], kevp[i], fflags);
639                 CP(ks32[i], kevp[i], data);
640                 PTRIN_CP(ks32[i], kevp[i], udata);
641         }
642 done:
643         return (error);
644 }
645 
646 int
647 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
648 {
649         struct timespec32 ts32;
650         struct timespec ts, *tsp;
651         struct kevent_copyops k_ops = { uap,
652                                         freebsd32_kevent_copyout,
653                                         freebsd32_kevent_copyin};
654         int error;
655 
656 
657         if (uap->timeout) {
658                 error = copyin(uap->timeout, &ts32, sizeof(ts32));
659                 if (error)
660                         return (error);
661                 CP(ts32, ts, tv_sec);
662                 CP(ts32, ts, tv_nsec);
663                 tsp = &ts;
664         } else
665                 tsp = NULL;
666         error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
667             &k_ops, tsp);
668         return (error);
669 }
670 
671 int
672 freebsd32_gettimeofday(struct thread *td,
673                        struct freebsd32_gettimeofday_args *uap)
674 {
675         struct timeval atv;
676         struct timeval32 atv32;
677         struct timezone rtz;
678         int error = 0;
679 
680         if (uap->tp) {
681                 microtime(&atv);
682                 CP(atv, atv32, tv_sec);
683                 CP(atv, atv32, tv_usec);
684                 error = copyout(&atv32, uap->tp, sizeof (atv32));
685         }
686         if (error == 0 && uap->tzp != NULL) {
687                 rtz.tz_minuteswest = tz_minuteswest;
688                 rtz.tz_dsttime = tz_dsttime;
689                 error = copyout(&rtz, uap->tzp, sizeof (rtz));
690         }
691         return (error);
692 }
693 
694 int
695 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
696 {
697         struct rusage32 s32;
698         struct rusage s;
699         int error;
700 
701         error = kern_getrusage(td, uap->who, &s);
702         if (error)
703                 return (error);
704         if (uap->rusage != NULL) {
705                 TV_CP(s, s32, ru_utime);
706                 TV_CP(s, s32, ru_stime);
707                 CP(s, s32, ru_maxrss);
708                 CP(s, s32, ru_ixrss);
709                 CP(s, s32, ru_idrss);
710                 CP(s, s32, ru_isrss);
711                 CP(s, s32, ru_minflt);
712                 CP(s, s32, ru_majflt);
713                 CP(s, s32, ru_nswap);
714                 CP(s, s32, ru_inblock);
715                 CP(s, s32, ru_oublock);
716                 CP(s, s32, ru_msgsnd);
717                 CP(s, s32, ru_msgrcv);
718                 CP(s, s32, ru_nsignals);
719                 CP(s, s32, ru_nvcsw);
720                 CP(s, s32, ru_nivcsw);
721                 error = copyout(&s32, uap->rusage, sizeof(s32));
722         }
723         return (error);
724 }
725 
726 static int
727 freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
728 {
729         struct iovec32 iov32;
730         struct iovec *iov;
731         struct uio *uio;
732         u_int iovlen;
733         int error, i;
734 
735         *uiop = NULL;
736         if (iovcnt > UIO_MAXIOV)
737                 return (EINVAL);
738         iovlen = iovcnt * sizeof(struct iovec);
739         uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
740         iov = (struct iovec *)(uio + 1);
741         for (i = 0; i < iovcnt; i++) {
742                 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
743                 if (error) {
744                         free(uio, M_IOV);
745                         return (error);
746                 }
747                 iov[i].iov_base = PTRIN(iov32.iov_base);
748                 iov[i].iov_len = iov32.iov_len;
749         }
750         uio->uio_iov = iov;
751         uio->uio_iovcnt = iovcnt;
752         uio->uio_segflg = UIO_USERSPACE;
753         uio->uio_offset = -1;
754         uio->uio_resid = 0;
755         for (i = 0; i < iovcnt; i++) {
756                 if (iov->iov_len > INT_MAX - uio->uio_resid) {
757                         free(uio, M_IOV);
758                         return (EINVAL);
759                 }
760                 uio->uio_resid += iov->iov_len;
761                 iov++;
762         }
763         *uiop = uio;
764         return (0);
765 }
766 
767 int
768 freebsd32_readv(struct thread *td, struct freebsd32_readv_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_readv(td, uap->fd, auio);
777         free(auio, M_IOV);
778         return (error);
779 }
780 
781 int
782 freebsd32_writev(struct thread *td, struct freebsd32_writev_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_writev(td, uap->fd, auio);
791         free(auio, M_IOV);
792         return (error);
793 }
794 
795 int
796 freebsd32_preadv(struct thread *td, struct freebsd32_preadv_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_preadv(td, uap->fd, auio, uap->offset);
805         free(auio, M_IOV);
806         return (error);
807 }
808 
809 int
810 freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
811 {
812         struct uio *auio;
813         int error;
814 
815         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
816         if (error)
817                 return (error);
818         error = kern_pwritev(td, uap->fd, auio, uap->offset);
819         free(auio, M_IOV);
820         return (error);
821 }
822 
823 static int
824 freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
825     int error)
826 {
827         struct iovec32 iov32;
828         struct iovec *iov;