]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/compat/freebsd32/freebsd32_misc.c
This commit was generated by cvs2svn to compensate for changes in r104862,
[FreeBSD/FreeBSD.git] / sys / compat / freebsd32 / freebsd32_misc.c
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  * $FreeBSD$
27  */
28
29 #include "opt_compat.h"
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/bus.h>
34 #include <sys/dkstat.h>
35 #include <sys/exec.h>
36 #include <sys/fcntl.h>
37 #include <sys/filedesc.h>
38 #include <sys/imgact.h>
39 #include <sys/kernel.h>
40 #include <sys/lock.h>
41 #include <sys/malloc.h>
42 #include <sys/file.h>           /* Must come after sys/malloc.h */
43 #include <sys/mman.h>
44 #include <sys/module.h>
45 #include <sys/mount.h>
46 #include <sys/mutex.h>
47 #include <sys/namei.h>
48 #include <sys/param.h>
49 #include <sys/proc.h>
50 #include <sys/reboot.h>
51 #include <sys/resource.h>
52 #include <sys/resourcevar.h>
53 #include <sys/selinfo.h>
54 #include <sys/pipe.h>           /* Must come after sys/selinfo.h */
55 #include <sys/signal.h>
56 #include <sys/signalvar.h>
57 #include <sys/socket.h>
58 #include <sys/socketvar.h>
59 #include <sys/stat.h>
60 #include <sys/sysctl.h>
61 #include <sys/sysent.h>
62 #include <sys/sysproto.h>
63 #include <sys/systm.h>
64 #include <sys/unistd.h>
65 #include <sys/user.h>
66 #include <sys/utsname.h>
67 #include <sys/vnode.h>
68
69 #include <vm/vm.h>
70 #include <vm/vm_kern.h>
71 #include <vm/vm_param.h>
72 #include <vm/pmap.h>
73 #include <vm/vm_map.h>
74 #include <vm/vm_object.h>
75 #include <vm/vm_extern.h>
76
77 #include <ia64/ia32/ia32_util.h>
78 #include <ia64/ia32/ia32.h>
79 #include <ia64/ia32/ia32_proto.h>
80
81 static const char ia32_emul_path[] = "/compat/ia32";
82 /*
83  * [ taken from the linux emulator ]
84  * Search an alternate path before passing pathname arguments on
85  * to system calls. Useful for keeping a separate 'emulation tree'.
86  *
87  * If cflag is set, we check if an attempt can be made to create
88  * the named file, i.e. we check if the directory it should
89  * be in exists.
90  */
91 int
92 ia32_emul_find(td, sgp, prefix, path, pbuf, cflag)
93         struct thread   *td;
94         caddr_t         *sgp;           /* Pointer to stackgap memory */
95         const char      *prefix;
96         char            *path;
97         char            **pbuf;
98         int             cflag;
99 {
100         int                     error;
101         size_t                  len, sz;
102         char                    *buf, *cp, *ptr;
103         struct ucred            *ucred;
104         struct nameidata        nd;
105         struct nameidata        ndroot;
106         struct vattr            vat;
107         struct vattr            vatroot;
108
109         buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
110         *pbuf = path;
111
112         for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
113                 continue;
114
115         sz = MAXPATHLEN - (ptr - buf);
116
117         /*
118          * If sgp is not given then the path is already in kernel space
119          */
120         if (sgp == NULL)
121                 error = copystr(path, ptr, sz, &len);
122         else
123                 error = copyinstr(path, ptr, sz, &len);
124
125         if (error) {
126                 free(buf, M_TEMP);
127                 return error;
128         }
129
130         if (*ptr != '/') {
131                 free(buf, M_TEMP);
132                 return EINVAL;
133         }
134
135         /*
136          *  We know that there is a / somewhere in this pathname.
137          *  Search backwards for it, to find the file's parent dir
138          *  to see if it exists in the alternate tree. If it does,
139          *  and we want to create a file (cflag is set). We don't
140          *  need to worry about the root comparison in this case.
141          */
142
143         if (cflag) {
144                 for (cp = &ptr[len] - 1; *cp != '/'; cp--)
145                         ;
146                 *cp = '\0';
147
148                 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
149
150                 if ((error = namei(&nd)) != 0) {
151                         free(buf, M_TEMP);
152                         return error;
153                 }
154
155                 *cp = '/';
156         } else {
157                 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
158
159                 if ((error = namei(&nd)) != 0) {
160                         free(buf, M_TEMP);
161                         return error;
162                 }
163
164                 /*
165                  * We now compare the vnode of the ia32_root to the one
166                  * vnode asked. If they resolve to be the same, then we
167                  * ignore the match so that the real root gets used.
168                  * This avoids the problem of traversing "../.." to find the
169                  * root directory and never finding it, because "/" resolves
170                  * to the emulation root directory. This is expensive :-(
171                  */
172                 NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path,
173                     td);
174
175                 if ((error = namei(&ndroot)) != 0) {
176                         /* Cannot happen! */
177                         free(buf, M_TEMP);
178                         vrele(nd.ni_vp);
179                         return error;
180                 }
181
182                 ucred = td->td_ucred;
183                 if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
184                         goto bad;
185                 }
186
187                 if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
188                     td)) != 0) {
189                         goto bad;
190                 }
191
192                 if (vat.va_fsid == vatroot.va_fsid &&
193                     vat.va_fileid == vatroot.va_fileid) {
194                         error = ENOENT;
195                         goto bad;
196                 }
197
198         }
199         if (sgp == NULL)
200                 *pbuf = buf;
201         else {
202                 sz = &ptr[len] - buf;
203                 *pbuf = stackgap_alloc(sgp, sz + 1);
204                 error = copyout(buf, *pbuf, sz);
205                 free(buf, M_TEMP);
206         }
207
208         vrele(nd.ni_vp);
209         if (!cflag)
210                 vrele(ndroot.ni_vp);
211
212         return error;
213
214 bad:
215         vrele(ndroot.ni_vp);
216         vrele(nd.ni_vp);
217         free(buf, M_TEMP);
218         return error;
219 }
220
221 int
222 ia32_open(struct thread *td, struct ia32_open_args *uap)
223 {
224         caddr_t sg;
225
226         sg = stackgap_init();
227         CHECKALTEXIST(td, &sg, uap->path);
228
229         return open(td, (struct open_args *) uap);
230 }
231
232 int
233 ia32_wait4(struct thread *td, struct ia32_wait4_args *uap)
234 {
235         int error;
236         caddr_t sg;
237         struct rusage32 *rusage32, ru32;
238         struct rusage *rusage = NULL, ru;
239
240         rusage32 = SCARG(uap, rusage);
241         if (rusage32) {
242                 sg = stackgap_init();
243                 rusage = stackgap_alloc(&sg, sizeof(struct rusage));
244                 SCARG(uap, rusage) = (struct rusage32 *)rusage;
245         }
246         error = wait4(td, (struct wait_args *)uap);
247         if (error)
248                 return (error);
249         if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
250                 TV_CP(ru, ru32, ru_utime);
251                 TV_CP(ru, ru32, ru_stime);
252                 CP(ru, ru32, ru_maxrss);
253                 CP(ru, ru32, ru_ixrss);
254                 CP(ru, ru32, ru_idrss);
255                 CP(ru, ru32, ru_isrss);
256                 CP(ru, ru32, ru_minflt);
257                 CP(ru, ru32, ru_majflt);
258                 CP(ru, ru32, ru_nswap);
259                 CP(ru, ru32, ru_inblock);
260                 CP(ru, ru32, ru_oublock);
261                 CP(ru, ru32, ru_msgsnd);
262                 CP(ru, ru32, ru_msgrcv);
263                 CP(ru, ru32, ru_nsignals);
264                 CP(ru, ru32, ru_nvcsw);
265                 CP(ru, ru32, ru_nivcsw);
266                 error = copyout(&ru32, rusage32, sizeof(ru32));
267         }
268         return (error);
269 }
270
271 static void
272 copy_statfs(struct statfs *in, struct statfs32 *out)
273 {
274         CP(*in, *out, f_bsize);
275         CP(*in, *out, f_iosize);
276         CP(*in, *out, f_blocks);
277         CP(*in, *out, f_bfree);
278         CP(*in, *out, f_bavail);
279         CP(*in, *out, f_files);
280         CP(*in, *out, f_ffree);
281         CP(*in, *out, f_fsid);
282         CP(*in, *out, f_owner);
283         CP(*in, *out, f_type);
284         CP(*in, *out, f_flags);
285         CP(*in, *out, f_flags);
286         CP(*in, *out, f_syncwrites);
287         CP(*in, *out, f_asyncwrites);
288         bcopy(in->f_fstypename,
289               out->f_fstypename, MFSNAMELEN);
290         bcopy(in->f_mntonname,
291               out->f_mntonname, MNAMELEN);
292         CP(*in, *out, f_syncreads);
293         CP(*in, *out, f_asyncreads);
294         bcopy(in->f_mntfromname,
295               out->f_mntfromname, MNAMELEN);
296 }
297
298 int
299 ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap)
300 {
301         int error;
302         caddr_t sg;
303         struct statfs32 *sp32, stat32;
304         struct statfs *sp = NULL, stat;
305         int maxcount, count, i;
306
307         sp32 = SCARG(uap, buf);
308         maxcount = SCARG(uap, bufsize) / sizeof(struct statfs32);
309
310         if (sp32) {
311                 sg = stackgap_init();
312                 sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
313                 SCARG(uap, buf) = (struct statfs32 *)sp;
314         }
315         error = getfsstat(td, (struct getfsstat_args *) uap);
316         if (sp32 && !error) {
317                 count = td->td_retval[0];
318                 for (i = 0; i < count; i++) {
319                         error = copyin(&sp[i], &stat, sizeof(stat));
320                         if (error)
321                                 return (error);
322                         copy_statfs(&stat, &stat32);
323                         error = copyout(&stat32, &sp32[i], sizeof(stat32));
324                         if (error)
325                                 return (error);
326                 }
327         }
328         return (error);
329 }
330
331 int
332 ia32_access(struct thread *td, struct ia32_access_args *uap)
333 {
334         caddr_t sg;
335
336         sg = stackgap_init();
337         CHECKALTEXIST(td, &sg, uap->path);
338
339         return access(td, (struct access_args *)uap);
340 }
341
342 int
343 ia32_chflags(struct thread *td, struct ia32_chflags_args *uap)
344 {
345         caddr_t sg;
346
347         sg = stackgap_init();
348         CHECKALTEXIST(td, &sg, uap->path);
349
350         return chflags(td, (struct chflags_args *)uap);
351 }
352
353 struct sigaltstack32 {
354         u_int32_t       ss_sp;
355         u_int32_t       ss_size;
356         int             ss_flags;
357 };
358
359 int
360 ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap)
361 {
362         int error;
363         caddr_t sg;
364         struct sigaltstack32 *p32, *op32, s32;
365         struct sigaltstack *p = NULL, *op = NULL, s;
366
367         p32 = SCARG(uap, ss);
368         if (p32) {
369                 sg = stackgap_init();
370                 p = stackgap_alloc(&sg, sizeof(struct sigaltstack));
371                 SCARG(uap, ss) = (struct sigaltstack32 *)p;
372                 error = copyin(p32, &s32, sizeof(s32));
373                 if (error)
374                         return (error);
375                 PTRIN_CP(s32, s, ss_sp);
376                 CP(s32, s, ss_size);
377                 CP(s32, s, ss_flags);
378                 error = copyout(&s, p, sizeof(s));
379                 if (error)
380                         return (error);
381         }
382         op32 = SCARG(uap, oss);
383         if (op32) {
384                 sg = stackgap_init();
385                 op = stackgap_alloc(&sg, sizeof(struct sigaltstack));
386                 SCARG(uap, oss) = (struct sigaltstack32 *)op;
387         }
388         error = sigaltstack(td, (struct sigaltstack_args *) uap);
389         if (error)
390                 return (error);
391         if (op32) {
392                 error = copyin(op, &s, sizeof(s));
393                 if (error)
394                         return (error);
395                 PTROUT_CP(s, s32, ss_sp);
396                 CP(s, s32, ss_size);
397                 CP(s, s32, ss_flags);
398                 error = copyout(&s32, op32, sizeof(s32));
399         }
400         return (error);
401 }
402
403 int
404 ia32_execve(struct thread *td, struct ia32_execve_args *uap)
405 {
406         int error;
407         caddr_t sg;
408         struct execve_args ap;
409         u_int32_t *p32, arg;
410         char **p;
411         int count;
412
413         sg = stackgap_init();
414         CHECKALTEXIST(td, &sg, SCARG(uap, fname));
415         SCARG(&ap, fname) = SCARG(uap, fname);
416
417         if (SCARG(uap, argv)) {
418                 count = 0;
419                 p32 = SCARG(uap, argv);
420                 do {
421                         error = copyin(p32++, &arg, sizeof(arg));
422                         if (error)
423                                 return error;
424                         count++;
425                 } while (arg != 0);
426                 p = stackgap_alloc(&sg, count * sizeof(char *));
427                 SCARG(&ap, argv) = p;
428                 p32 = SCARG(uap, argv);
429                 do {
430                         error = copyin(p32++, &arg, sizeof(arg));
431                         if (error)
432                                 return error;
433                         *p++ = PTRIN(arg);
434                 } while (arg != 0);
435         }
436         if (SCARG(uap, envv)) {
437                 count = 0;
438                 p32 = SCARG(uap, envv);
439                 do {
440                         error = copyin(p32++, &arg, sizeof(arg));
441                         if (error)
442                                 return error;
443                         count++;
444                 } while (arg != 0);
445                 p = stackgap_alloc(&sg, count * sizeof(char *));
446                 SCARG(&ap, envv) = p;
447                 p32 = SCARG(uap, envv);
448                 do {
449                         error = copyin(p32++, &arg, sizeof(arg));
450                         if (error)
451                                 return error;
452                         *p++ = PTRIN(arg);
453                 } while (arg != 0);
454         }
455
456         return execve(td, &ap);
457 }
458
459 static int
460 ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
461                   int prot, int fd, off_t pos)
462 {
463         vm_map_t map;
464         vm_map_entry_t entry;
465         int rv;
466
467         map = &td->td_proc->p_vmspace->vm_map;
468         if (fd != -1)
469                 prot |= VM_PROT_WRITE;
470
471         if (vm_map_lookup_entry(map, start, &entry)) {
472                 if ((entry->protection & prot) != prot) {
473                         rv = vm_map_protect(map,
474                                             trunc_page(start),
475                                             round_page(end),
476                                             entry->protection | prot,
477                                             FALSE);
478                         if (rv != KERN_SUCCESS)
479                                 return (EINVAL);
480                 }
481         } else {
482                 vm_offset_t addr = trunc_page(start);
483                 rv = vm_map_find(map, 0, 0,
484                                  &addr, PAGE_SIZE, FALSE, prot,
485                                  VM_PROT_ALL, 0);
486                 if (rv != KERN_SUCCESS)
487                         return (EINVAL);
488         }
489
490         if (fd != -1) {
491                 struct pread_args r;
492                 SCARG(&r, fd) = fd;
493                 SCARG(&r, buf) = (void *) start;
494                 SCARG(&r, nbyte) = end - start;
495                 SCARG(&r, offset) = pos;
496                 return (pread(td, &r));
497         } else {
498                 while (start < end) {
499                         subyte((void *) start, 0);
500                         start++;
501                 }
502                 return (0);
503         }
504 }
505
506 int
507 ia32_mmap(struct thread *td, struct ia32_mmap_args *uap)
508 {
509         struct mmap_args ap;
510         vm_offset_t addr = (vm_offset_t) SCARG(uap, addr);
511         vm_size_t len    = SCARG(uap, len);
512         int prot         = SCARG(uap, prot);
513         int flags        = SCARG(uap, flags);
514         int fd           = SCARG(uap, fd);
515         off_t pos        = (SCARG(uap, poslo)
516                             | ((off_t)SCARG(uap, poshi) << 32));
517         vm_size_t pageoff;
518         int error;
519
520         /*
521          * Attempt to handle page size hassles.
522          */
523         pageoff = (pos & PAGE_MASK);
524         if (flags & MAP_FIXED) {
525                 vm_offset_t start, end;
526                 start = addr;
527                 end = addr + len;
528
529                 if (start != trunc_page(start)) {
530                         error = ia32_mmap_partial(td, start, round_page(start),
531                                                   prot, fd, pos);
532                         if (fd != -1)
533                                 pos += round_page(start) - start;
534                         start = round_page(start);
535                 }
536                 if (end != round_page(end)) {
537                         vm_offset_t t = trunc_page(end);
538                         error = ia32_mmap_partial(td, t, end,
539                                                   prot, fd,
540                                                   pos + t - start);
541                         end = trunc_page(end);
542                 }
543                 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
544                         /*
545                          * We can't map this region at all. The specified
546                          * address doesn't have the same alignment as the file
547                          * position. Fake the mapping by simply reading the
548                          * entire region into memory. First we need to make
549                          * sure the region exists.
550                          */
551                         vm_map_t map;
552                         struct pread_args r;
553                         int rv;
554
555                         prot |= VM_PROT_WRITE;
556                         map = &td->td_proc->p_vmspace->vm_map;
557                         rv = vm_map_remove(map, start, end);
558                         if (rv != KERN_SUCCESS)
559                                 return (EINVAL);
560                         rv = vm_map_find(map, 0, 0,
561                                          &start, end - start, FALSE,
562                                          prot, VM_PROT_ALL, 0);
563                         if (rv != KERN_SUCCESS)
564                                 return (EINVAL);
565                         SCARG(&r, fd) = fd;
566                         SCARG(&r, buf) = (void *) start;
567                         SCARG(&r, nbyte) = end - start;
568                         SCARG(&r, offset) = pos;
569                         error = pread(td, &r);
570                         if (error)
571                                 return (error);
572
573                         td->td_retval[0] = addr;
574                         return (0);
575                 }
576                 if (end == start) {
577                         /*
578                          * After dealing with the ragged ends, there
579                          * might be none left.
580                          */
581                         td->td_retval[0] = addr;
582                         return (0);
583                 }
584                 addr = start;
585                 len = end - start;
586         }
587
588         SCARG(&ap, addr) = (void *) addr;
589         SCARG(&ap, len) = len;
590         SCARG(&ap, prot) = prot;
591         SCARG(&ap, flags) = flags;
592         SCARG(&ap, fd) = fd;
593         SCARG(&ap, pos) = pos;
594
595         return (mmap(td, &ap));
596 }
597
598 struct itimerval32 {
599         struct timeval32 it_interval;
600         struct timeval32 it_value;
601 };
602
603 int
604 ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
605 {
606         int error;
607         caddr_t sg;
608         struct itimerval32 *p32, *op32, s32;
609         struct itimerval *p = NULL, *op = NULL, s;
610
611         p32 = SCARG(uap, itv);
612         if (p32) {
613                 sg = stackgap_init();
614                 p = stackgap_alloc(&sg, sizeof(struct itimerval));
615                 SCARG(uap, itv) = (struct itimerval32 *)p;
616                 error = copyin(p32, &s32, sizeof(s32));
617                 if (error)
618                         return (error);
619                 TV_CP(s32, s, it_interval);
620                 TV_CP(s32, s, it_value);
621                 error = copyout(&s, p, sizeof(s));
622                 if (error)
623                         return (error);
624         }
625         op32 = SCARG(uap, oitv);
626         if (op32) {
627                 sg = stackgap_init();
628                 op = stackgap_alloc(&sg, sizeof(struct itimerval));
629                 SCARG(uap, oitv) = (struct itimerval32 *)op;
630         }
631         error = setitimer(td, (struct setitimer_args *) uap);
632         if (error)
633                 return (error);
634         if (op32) {
635                 error = copyin(op, &s, sizeof(s));
636                 if (error)
637                         return (error);
638                 TV_CP(s, s32, it_interval);
639                 TV_CP(s, s32, it_value);
640                 error = copyout(&s32, op32, sizeof(s32));
641         }
642         return (error);
643 }
644
645 int
646 ia32_select(struct thread *td, struct ia32_select_args *uap)
647 {
648         int error;
649         caddr_t sg;
650         struct timeval32 *p32, s32;
651         struct timeval *p = NULL, s;
652
653         p32 = SCARG(uap, tv);
654         if (p32) {
655                 sg = stackgap_init();
656                 p = stackgap_alloc(&sg, sizeof(struct timeval));
657                 SCARG(uap, tv) = (struct timeval32 *)p;
658                 error = copyin(p32, &s32, sizeof(s32));
659                 if (error)
660                         return (error);
661                 CP(s32, s, tv_sec);
662                 CP(s32, s, tv_usec);
663                 error = copyout(&s, p, sizeof(s));
664                 if (error)
665                         return (error);
666         }
667         /*
668          * XXX big-endian needs to convert the fd_sets too.
669          */
670         return (select(td, (struct select_args *) uap));
671 }
672
673 int
674 ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
675 {
676         int error;
677         caddr_t sg;
678         struct timeval32 *p32, s32;
679         struct timeval *p = NULL, s;
680
681         p32 = SCARG(uap, tp);
682         if (p32) {
683                 sg = stackgap_init();
684                 p = stackgap_alloc(&sg, sizeof(struct timeval));
685                 SCARG(uap, tp) = (struct timeval32 *)p;
686         }
687         error = gettimeofday(td, (struct gettimeofday_args *) uap);
688         if (error)
689                 return (error);
690         if (p32) {
691                 error = copyin(p, &s, sizeof(s));
692                 if (error)
693                         return (error);
694                 CP(s, s32, tv_sec);
695                 CP(s, s32, tv_usec);
696                 error = copyout(&s32, p32, sizeof(s32));
697                 if (error)
698                         return (error);
699         }
700         return (error);
701 }
702
703 int
704 ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
705 {
706         int error;
707         caddr_t sg;
708         struct rusage32 *p32, s32;
709         struct rusage *p = NULL, s;
710
711         p32 = SCARG(uap, rusage);
712         if (p32) {
713                 sg = stackgap_init();
714                 p = stackgap_alloc(&sg, sizeof(struct rusage));
715                 SCARG(uap, rusage) = (struct rusage32 *)p;
716         }
717         error = getrusage(td, (struct getrusage_args *) uap);
718         if (error)
719                 return (error);
720         if (p32) {
721                 error = copyin(p, &s, sizeof(s));
722                 if (error)
723                         return (error);
724                 TV_CP(s, s32, ru_utime);
725                 TV_CP(s, s32, ru_stime);
726                 CP(s, s32, ru_maxrss);
727                 CP(s, s32, ru_ixrss);
728                 CP(s, s32, ru_idrss);
729                 CP(s, s32, ru_isrss);
730                 CP(s, s32, ru_minflt);
731                 CP(s, s32, ru_majflt);
732                 CP(s, s32, ru_nswap);
733                 CP(s, s32, ru_inblock);
734                 CP(s, s32, ru_oublock);
735                 CP(s, s32, ru_msgsnd);
736                 CP(s, s32, ru_msgrcv);
737                 CP(s, s32, ru_nsignals);
738                 CP(s, s32, ru_nvcsw);
739                 CP(s, s32, ru_nivcsw);
740                 error = copyout(&s32, p32, sizeof(s32));
741         }
742         return (error);
743 }
744
745 struct iovec32 {
746         u_int32_t iov_base;
747         int     iov_len;
748 };
749 #define STACKGAPLEN     400
750
751 int
752 ia32_readv(struct thread *td, struct ia32_readv_args *uap)
753 {
754         int error, osize, nsize, i;
755         caddr_t sg;
756         struct readv_args /* {
757                 syscallarg(int) fd;
758                 syscallarg(struct iovec *) iovp;
759                 syscallarg(u_int) iovcnt;
760         } */ a;
761         struct iovec32 *oio;
762         struct iovec *nio;
763
764         sg = stackgap_init();
765
766         if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec)))
767                 return (EINVAL);
768
769         osize = SCARG(uap, iovcnt) * sizeof (struct iovec32);
770         nsize = SCARG(uap, iovcnt) * sizeof (struct iovec);
771
772         oio = malloc(osize, M_TEMP, M_WAITOK);
773         nio = malloc(nsize, M_TEMP, M_WAITOK);
774
775         error = 0;
776         if ((error = copyin(SCARG(uap, iovp), oio, osize)))
777                 goto punt;
778         for (i = 0; i < SCARG(uap, iovcnt); i++) {
779                 nio[i].iov_base = PTRIN(oio[i].iov_base);
780                 nio[i].iov_len = oio[i].iov_len;
781         }
782
783         SCARG(&a, fd) = SCARG(uap, fd);
784         SCARG(&a, iovp) = stackgap_alloc(&sg, nsize);
785         SCARG(&a, iovcnt) = SCARG(uap, iovcnt);
786
787         if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize)))
788                 goto punt;
789         error = readv(td, &a);
790
791 punt:
792         free(oio, M_TEMP);
793         free(nio, M_TEMP);
794         return (error);
795 }
796
797 int
798 ia32_writev(struct thread *td, struct ia32_writev_args *uap)
799 {
800         int error, i, nsize, osize;
801         caddr_t sg;
802         struct writev_args /* {
803                 syscallarg(int) fd;
804                 syscallarg(struct iovec *) iovp;
805                 syscallarg(u_int) iovcnt;
806         } */ a;
807         struct iovec32 *oio;
808         struct iovec *nio;
809
810         sg = stackgap_init();
811
812         if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec)))
813                 return (EINVAL);
814
815         osize = SCARG(uap, iovcnt) * sizeof (struct iovec32);
816         nsize = SCARG(uap, iovcnt) * sizeof (struct iovec);
817
818         oio = malloc(osize, M_TEMP, M_WAITOK);
819         nio = malloc(nsize, M_TEMP, M_WAITOK);
820
821         error = 0;
822         if ((error = copyin(SCARG(uap, iovp), oio, osize)))
823                 goto punt;
824         for (i = 0; i < SCARG(uap, iovcnt); i++) {
825                 nio[i].iov_base = PTRIN(oio[i].iov_base);
826                 nio[i].iov_len = oio[i].iov_len;
827         }
828
829         SCARG(&a, fd) = SCARG(uap, fd);
830         SCARG(&a, iovp) = stackgap_alloc(&sg, nsize);
831         SCARG(&a, iovcnt) = SCARG(uap, iovcnt);
832
833         if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize)))
834                 goto punt;
835         error = writev(td, &a);
836
837 punt:
838         free(oio, M_TEMP);
839         free(nio, M_TEMP);
840         return (error);
841 }
842
843 int
844 ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
845 {
846         int error;
847         caddr_t sg;
848         struct timeval32 *p32, s32;
849         struct timeval *p = NULL, s;
850
851         p32 = SCARG(uap, tv);
852         if (p32) {
853                 sg = stackgap_init();
854                 p = stackgap_alloc(&sg, sizeof(struct timeval));
855                 SCARG(uap, tv) = (struct timeval32 *)p;
856                 error = copyin(p32, &s32, sizeof(s32));
857                 if (error)
858                         return (error);
859                 CP(s32, s, tv_sec);
860                 CP(s32, s, tv_usec);
861                 error = copyout(&s, p, sizeof(s));
862                 if (error)
863                         return (error);
864         }
865         return (settimeofday(td, (struct settimeofday_args *) uap));
866 }
867
868 int
869 ia32_utimes(struct thread *td, struct ia32_utimes_args *uap)
870 {
871         int error;
872         caddr_t sg;
873         struct timeval32 *p32, s32[2];
874         struct timeval *p = NULL, s[2];
875
876         p32 = SCARG(uap, tptr);
877         if (p32) {
878                 sg = stackgap_init();
879                 p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
880                 SCARG(uap, tptr) = (struct timeval32 *)p;
881                 error = copyin(p32, s32, sizeof(s32));
882                 if (error)
883                         return (error);
884                 CP(s32[0], s[0], tv_sec);
885                 CP(s32[0], s[0], tv_usec);
886                 CP(s32[1], s[1], tv_sec);
887                 CP(s32[1], s[1], tv_usec);
888                 error = copyout(s, p, sizeof(s));
889                 if (error)
890                         return (error);
891         }
892         return (utimes(td, (struct utimes_args *) uap));
893 }
894
895 int
896 ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
897 {
898         int error;
899         caddr_t sg;
900         struct timeval32 *p32, *op32, s32;
901         struct timeval *p = NULL, *op = NULL, s;
902
903         p32 = SCARG(uap, delta);
904         if (p32) {
905                 sg = stackgap_init();
906                 p = stackgap_alloc(&sg, sizeof(struct timeval));
907                 SCARG(uap, delta) = (struct timeval32 *)p;
908                 error = copyin(p32, &s32, sizeof(s32));
909                 if (error)
910                         return (error);
911                 CP(s32, s, tv_sec);
912                 CP(s32, s, tv_usec);
913                 error = copyout(&s, p, sizeof(s));
914                 if (error)
915                         return (error);
916         }
917         op32 = SCARG(uap, olddelta);
918         if (op32) {
919                 sg = stackgap_init();
920                 op = stackgap_alloc(&sg, sizeof(struct timeval));
921                 SCARG(uap, olddelta) = (struct timeval32 *)op;
922         }
923         error = utimes(td, (struct utimes_args *) uap);
924         if (error)
925                 return error;
926         if (op32) {
927                 error = copyin(op, &s, sizeof(s));
928                 if (error)
929                         return (error);
930                 CP(s, s32, tv_sec);
931                 CP(s, s32, tv_usec);
932                 error = copyout(&s32, op32, sizeof(s32));
933         }
934         return (error);
935 }
936
937 int
938 ia32_statfs(struct thread *td, struct ia32_statfs_args *uap)
939 {
940         int error;
941         caddr_t sg;
942         struct statfs32 *p32, s32;
943         struct statfs *p = NULL, s;
944
945         p32 = SCARG(uap, buf);
946         if (p32) {
947                 sg = stackgap_init();
948                 p = stackgap_alloc(&sg, sizeof(struct statfs));
949                 SCARG(uap, buf) = (struct statfs32 *)p;
950         }
951         error = statfs(td, (struct statfs_args *) uap);
952         if (error)
953                 return (error);
954         if (p32) {
955                 error = copyin(p, &s, sizeof(s));
956                 if (error)
957                         return (error);
958                 copy_statfs(&s, &s32);
959                 error = copyout(&s32, p32, sizeof(s32));
960         }
961         return (error);
962 }
963
964 int
965 ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
966 {
967         int error;
968         caddr_t sg;
969         struct statfs32 *p32, s32;
970         struct statfs *p = NULL, s;
971
972         p32 = SCARG(uap, buf);
973         if (p32) {
974                 sg = stackgap_init();
975                 p = stackgap_alloc(&sg, sizeof(struct statfs));
976                 SCARG(uap, buf) = (struct statfs32 *)p;
977         }
978         error = fstatfs(td, (struct fstatfs_args *) uap);
979         if (error)
980                 return (error);
981         if (p32) {
982                 error = copyin(p, &s, sizeof(s));
983                 if (error)
984                         return (error);
985                 copy_statfs(&s, &s32);
986                 error = copyout(&s32, p32, sizeof(s32));
987         }
988         return (error);
989 }
990
991 int
992 ia32_semsys(struct thread *td, struct ia32_semsys_args *uap)
993 {
994         /*
995          * Vector through to semsys if it is loaded.
996          */
997         return sysent[169].sy_call(td, uap);
998 }
999
1000 int
1001 ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
1002 {
1003         /*
1004          * Vector through to msgsys if it is loaded.
1005          */
1006         return sysent[170].sy_call(td, uap);
1007 }
1008
1009 int
1010 ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
1011 {
1012         /*
1013          * Vector through to shmsys if it is loaded.
1014          */
1015         return sysent[171].sy_call(td, uap);
1016 }
1017
1018 int
1019 ia32_pread(struct thread *td, struct ia32_pread_args *uap)
1020 {
1021         struct pread_args ap;
1022
1023         SCARG(&ap, fd) = SCARG(uap, fd);
1024         SCARG(&ap, buf) = SCARG(uap, buf);
1025         SCARG(&ap, nbyte) = SCARG(uap, nbyte);
1026         SCARG(&ap, offset) = (SCARG(uap, offsetlo)
1027                               | ((off_t)SCARG(uap, offsethi) << 32));
1028         return (pread(td, &ap));
1029 }
1030
1031 int
1032 ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
1033 {
1034         struct pwrite_args ap;
1035
1036         SCARG(&ap, fd) = SCARG(uap, fd);
1037         SCARG(&ap, buf) = SCARG(uap, buf);
1038         SCARG(&ap, nbyte) = SCARG(uap, nbyte);
1039         SCARG(&ap, offset) = (SCARG(uap, offsetlo)
1040                               | ((off_t)SCARG(uap, offsethi) << 32));
1041         return (pwrite(td, &ap));
1042 }
1043
1044 int
1045 ia32_lseek(struct thread *td, struct ia32_lseek_args *uap)
1046 {
1047         int error;
1048         struct lseek_args ap;
1049         off_t pos;
1050
1051         SCARG(&ap, fd) = SCARG(uap, fd);
1052         SCARG(&ap, offset) = (SCARG(uap, offsetlo)
1053                               | ((off_t)SCARG(uap, offsethi) << 32));
1054         SCARG(&ap, whence) = SCARG(uap, whence);
1055         error = lseek(td, &ap);
1056         /* Expand the quad return into two parts for eax and edx */
1057         pos = *(off_t *)(td->td_retval);
1058         td->td_retval[0] = pos & 0xffffffff;    /* %eax */
1059         td->td_retval[1] = pos >> 32;           /* %edx */
1060         return error;
1061 }
1062
1063 int
1064 ia32_truncate(struct thread *td, struct ia32_truncate_args *uap)
1065 {
1066         struct truncate_args ap;
1067
1068         SCARG(&ap, path) = SCARG(uap, path);
1069         SCARG(&ap, length) = (SCARG(uap, lengthlo)
1070                               | ((off_t)SCARG(uap, lengthhi) << 32));
1071         return (truncate(td, &ap));
1072 }
1073
1074 int
1075 ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
1076 {
1077         struct ftruncate_args ap;
1078
1079         SCARG(&ap, fd) = SCARG(uap, fd);
1080         SCARG(&ap, length) = (SCARG(uap, lengthlo)
1081                               | ((off_t)SCARG(uap, lengthhi) << 32));
1082         return (ftruncate(td, &ap));
1083 }
1084
1085 #ifdef COMPAT_FREEBSD4
1086 int
1087 freebsd4_ia32_sendfile(struct thread *td,
1088     struct freebsd4_ia32_sendfile_args *uap)
1089 {
1090         struct freebsd4_sendfile_args ap;
1091
1092         SCARG(&ap, fd) = SCARG(uap, fd);
1093         SCARG(&ap, s) = SCARG(uap, s);
1094         SCARG(&ap, offset) = (SCARG(uap, offsetlo)
1095                               | ((off_t)SCARG(uap, offsethi) << 32));
1096         SCARG(&ap, nbytes) = SCARG(uap, nbytes);        /* XXX check */
1097         SCARG(&ap, hdtr) = SCARG(uap, hdtr);            /* XXX check */
1098         SCARG(&ap, sbytes) = SCARG(uap, sbytes);        /* XXX FIXME!! */
1099         SCARG(&ap, flags) = SCARG(uap, flags);
1100         return (freebsd4_sendfile(td, &ap));
1101 }
1102 #endif
1103
1104 int
1105 ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
1106 {
1107         struct sendfile_args ap;
1108
1109         SCARG(&ap, fd) = SCARG(uap, fd);
1110         SCARG(&ap, s) = SCARG(uap, s);
1111         SCARG(&ap, offset) = (SCARG(uap, offsetlo)
1112                               | ((off_t)SCARG(uap, offsethi) << 32));
1113         SCARG(&ap, nbytes) = SCARG(uap, nbytes);        /* XXX check */
1114         SCARG(&ap, hdtr) = SCARG(uap, hdtr);            /* XXX check */
1115         SCARG(&ap, sbytes) = SCARG(uap, sbytes);        /* XXX FIXME!! */
1116         SCARG(&ap, flags) = SCARG(uap, flags);
1117         return (sendfile(td, &ap));
1118 }
1119
1120 struct stat32 {
1121         udev_t  st_dev;
1122         ino_t   st_ino;
1123         mode_t  st_mode;
1124         nlink_t st_nlink;
1125         uid_t   st_uid;
1126         gid_t   st_gid;
1127         udev_t  st_rdev;
1128         struct timespec32 st_atimespec;
1129         struct timespec32 st_mtimespec;
1130         struct timespec32 st_ctimespec;
1131         off_t   st_size;
1132         int64_t st_blocks;
1133         u_int32_t st_blksize;
1134         u_int32_t st_flags;
1135         u_int32_t st_gen;
1136 };
1137
1138 static void
1139 copy_stat( struct stat *in, struct stat32 *out)
1140 {
1141         CP(*in, *out, st_dev);
1142         CP(*in, *out, st_ino);
1143         CP(*in, *out, st_mode);
1144         CP(*in, *out, st_nlink);
1145         CP(*in, *out, st_uid);
1146         CP(*in, *out, st_gid);
1147         CP(*in, *out, st_rdev);
1148         TS_CP(*in, *out, st_atimespec);
1149         TS_CP(*in, *out, st_mtimespec);
1150         TS_CP(*in, *out, st_ctimespec);
1151         CP(*in, *out, st_size);
1152         CP(*in, *out, st_blocks);
1153         CP(*in, *out, st_blksize);
1154         CP(*in, *out, st_flags);
1155         CP(*in, *out, st_gen);
1156 }
1157
1158 int
1159 ia32_stat(struct thread *td, struct ia32_stat_args *uap)
1160 {
1161         int error;
1162         caddr_t sg;
1163         struct stat32 *p32, s32;
1164         struct stat *p = NULL, s;
1165
1166         p32 = SCARG(uap, ub);
1167         if (p32) {
1168                 sg = stackgap_init();
1169                 p = stackgap_alloc(&sg, sizeof(struct stat));
1170                 SCARG(uap, ub) = (struct stat32 *)p;
1171         }
1172         error = stat(td, (struct stat_args *) uap);
1173         if (error)
1174                 return (error);
1175         if (p32) {
1176                 error = copyin(p, &s, sizeof(s));
1177                 if (error)
1178                         return (error);
1179                 copy_stat(&s, &s32);
1180                 error = copyout(&s32, p32, sizeof(s32));
1181         }
1182         return (error);
1183 }
1184
1185 int
1186 ia32_fstat(struct thread *td, struct ia32_fstat_args *uap)
1187 {
1188         int error;
1189         caddr_t sg;
1190         struct stat32 *p32, s32;
1191         struct stat *p = NULL, s;
1192
1193         p32 = SCARG(uap, ub);
1194         if (p32) {
1195                 sg = stackgap_init();
1196                 p = stackgap_alloc(&sg, sizeof(struct stat));
1197                 SCARG(uap, ub) = (struct stat32 *)p;
1198         }
1199         error = fstat(td, (struct fstat_args *) uap);
1200         if (error)
1201                 return (error);
1202         if (p32) {
1203                 error = copyin(p, &s, sizeof(s));
1204                 if (error)
1205                         return (error);
1206                 copy_stat(&s, &s32);
1207                 error = copyout(&s32, p32, sizeof(s32));
1208         }
1209         return (error);
1210 }
1211
1212 int
1213 ia32_lstat(struct thread *td, struct ia32_lstat_args *uap)
1214 {
1215         int error;
1216         caddr_t sg;
1217         struct stat32 *p32, s32;
1218         struct stat *p = NULL, s;
1219
1220         p32 = SCARG(uap, ub);
1221         if (p32) {
1222                 sg = stackgap_init();
1223                 p = stackgap_alloc(&sg, sizeof(struct stat));
1224                 SCARG(uap, ub) = (struct stat32 *)p;
1225         }
1226         error = lstat(td, (struct lstat_args *) uap);
1227         if (error)
1228                 return (error);
1229         if (p32) {
1230                 error = copyin(p, &s, sizeof(s));
1231                 if (error)
1232                         return (error);
1233                 copy_stat(&s, &s32);
1234                 error = copyout(&s32, p32, sizeof(s32));
1235         }
1236         return (error);
1237 }
1238
1239 /*
1240  * MPSAFE
1241  */
1242 int
1243 ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
1244 {
1245         int error, name[CTL_MAXNAME];
1246         size_t j, oldlen;
1247
1248         if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1249                 return (EINVAL);
1250
1251         error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1252         if (error)
1253                 return (error);
1254
1255         mtx_lock(&Giant);
1256
1257         if (uap->oldlenp)
1258                 oldlen = fuword32(uap->oldlenp);
1259         else
1260                 oldlen = 0;
1261         error = userland_sysctl(td, name, uap->namelen,
1262                 uap->old, &oldlen, 1,
1263                 uap->new, uap->newlen, &j);
1264         if (error && error != ENOMEM)
1265                 goto done2;
1266         if (uap->oldlenp) {
1267                 suword32(uap->oldlenp, j);
1268         }
1269 done2:
1270         mtx_unlock(&Giant);
1271         return (error);
1272 }
1273
1274 struct sigaction32 {
1275         u_int32_t       sa_u;
1276         int             sa_flags;
1277         sigset_t        sa_mask;
1278 };
1279
1280 int
1281 ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
1282 {
1283         int error;
1284         caddr_t sg;
1285         struct sigaction32 *p32, *op32, s32;
1286         struct sigaction *p = NULL, *op = NULL, s;
1287
1288         p32 = SCARG(uap, act);
1289         if (p32) {
1290                 sg = stackgap_init();
1291                 p = stackgap_alloc(&sg, sizeof(struct sigaction));
1292                 SCARG(uap, act) = (struct sigaction32 *)p;
1293                 error = copyin(p32, &s32, sizeof(s32));
1294                 if (error)
1295                         return (error);
1296                 s.sa_handler = PTRIN(s32.sa_u);
1297                 CP(s32, s, sa_flags);
1298                 CP(s32, s, sa_mask);
1299                 error = copyout(&s, p, sizeof(s));
1300                 if (error)
1301                         return (error);
1302         }
1303         op32 = SCARG(uap, oact);
1304         if (op32) {
1305                 sg = stackgap_init();
1306                 op = stackgap_alloc(&sg, sizeof(struct sigaction));
1307                 SCARG(uap, oact) = (struct sigaction32 *)op;
1308         }
1309         error = sigaction(td, (struct sigaction_args *) uap);
1310         if (error)
1311                 return (error);
1312         if (op32) {
1313                 error = copyin(op, &s, sizeof(s));
1314                 if (error)
1315                         return (error);
1316                 s32.sa_u = PTROUT(s.sa_handler);
1317                 CP(s, s32, sa_flags);
1318                 CP(s, s32, sa_mask);
1319                 error = copyout(&s32, op32, sizeof(s32));
1320         }
1321         return (error);
1322 }
1323
1324 #if 0
1325
1326 int
1327 ia32_xxx(struct thread *td, struct ia32_xxx_args *uap)
1328 {
1329         int error;
1330         caddr_t sg;
1331         struct yyy32 *p32, s32;
1332         struct yyy *p = NULL, s;
1333
1334         p32 = SCARG(uap, zzz);
1335         if (p32) {
1336                 sg = stackgap_init();
1337                 p = stackgap_alloc(&sg, sizeof(struct yyy));
1338                 SCARG(uap, zzz) = (struct yyy32 *)p;
1339                 error = copyin(p32, &s32, sizeof(s32));
1340                 if (error)
1341                         return (error);
1342                 /* translate in */
1343                 error = copyout(&s, p, sizeof(s));
1344                 if (error)
1345                         return (error);
1346         }
1347         error = xxx(td, (struct xxx_args *) uap);
1348         if (error)
1349                 return (error);
1350         if (p32) {
1351                 error = copyin(p, &s, sizeof(s));
1352                 if (error)
1353                         return (error);
1354                 /* translate out */
1355                 error = copyout(&s32, p32, sizeof(s32));
1356         }
1357         return (error);
1358 }
1359
1360 #endif