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