[BACK]Return to linux_misc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / compat / linux / common

Annotation of src/sys/compat/linux/common/linux_misc.c, Revision 1.151.2.4

1.151.2.4! yamt        1: /*     $NetBSD: linux_misc.c,v 1.151.2.3 2006/06/26 12:46:18 yamt Exp $        */
1.47      erh         2:
                      3: /*-
1.56      thorpej     4:  * Copyright (c) 1995, 1998, 1999 The NetBSD Foundation, Inc.
1.47      erh         5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
1.56      thorpej     8:  * by Frank van der Linden and Eric Haszlakiewicz; by Jason R. Thorpe
                      9:  * of the Numerical Aerospace Simulation Facility, NASA Ames Research Center.
1.47      erh        10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
1.1       fvdl       38:  */
                     39:
                     40: /*
                     41:  * Linux compatibility module. Try to deal with various Linux system calls.
                     42:  */
                     43:
1.47      erh        44: /*
                     45:  * These functions have been moved to multiarch to allow
1.135     perry      46:  * selection of which machines include them to be
1.47      erh        47:  * determined by the individual files.linux_<arch> files.
                     48:  *
                     49:  * Function in multiarch:
                     50:  *     linux_sys_break                 : linux_break.c
                     51:  *     linux_sys_alarm                 : linux_misc_notalpha.c
1.57      thorpej    52:  *     linux_sys_getresgid             : linux_misc_notalpha.c
1.47      erh        53:  *     linux_sys_nice                  : linux_misc_notalpha.c
                     54:  *     linux_sys_readdir               : linux_misc_notalpha.c
1.57      thorpej    55:  *     linux_sys_setresgid             : linux_misc_notalpha.c
1.47      erh        56:  *     linux_sys_time                  : linux_misc_notalpha.c
                     57:  *     linux_sys_utime                 : linux_misc_notalpha.c
                     58:  *     linux_sys_waitpid               : linux_misc_notalpha.c
                     59:  *     linux_sys_old_mmap              : linux_oldmmap.c
                     60:  *     linux_sys_oldolduname           : linux_oldolduname.c
                     61:  *     linux_sys_oldselect             : linux_oldselect.c
                     62:  *     linux_sys_olduname              : linux_olduname.c
                     63:  *     linux_sys_pipe                  : linux_pipe.c
                     64:  */
1.95      lukem      65:
                     66: #include <sys/cdefs.h>
1.151.2.4! yamt       67: __KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.151.2.3 2006/06/26 12:46:18 yamt Exp $");
1.47      erh        68:
1.1       fvdl       69: #include <sys/param.h>
                     70: #include <sys/systm.h>
                     71: #include <sys/namei.h>
                     72: #include <sys/proc.h>
1.29      mycroft    73: #include <sys/dirent.h>
1.1       fvdl       74: #include <sys/file.h>
                     75: #include <sys/stat.h>
                     76: #include <sys/filedesc.h>
                     77: #include <sys/ioctl.h>
                     78: #include <sys/kernel.h>
                     79: #include <sys/malloc.h>
                     80: #include <sys/mbuf.h>
                     81: #include <sys/mman.h>
                     82: #include <sys/mount.h>
1.67      erh        83: #include <sys/reboot.h>
1.1       fvdl       84: #include <sys/resource.h>
                     85: #include <sys/resourcevar.h>
                     86: #include <sys/signal.h>
                     87: #include <sys/signalvar.h>
                     88: #include <sys/socket.h>
                     89: #include <sys/time.h>
                     90: #include <sys/times.h>
                     91: #include <sys/vnode.h>
                     92: #include <sys/uio.h>
                     93: #include <sys/wait.h>
                     94: #include <sys/utsname.h>
                     95: #include <sys/unistd.h>
1.75      jdolecek   96: #include <sys/swap.h>          /* for SWAP_ON */
                     97: #include <sys/sysctl.h>                /* for KERN_DOMAINNAME */
1.151.2.2  yamt       98: #include <sys/kauth.h>
1.1       fvdl       99:
1.73      jdolecek  100: #include <sys/ptrace.h>
                    101: #include <machine/ptrace.h>
                    102:
1.116     thorpej   103: #include <sys/sa.h>
1.1       fvdl      104: #include <sys/syscallargs.h>
                    105:
1.143     manu      106: #include <compat/linux/common/linux_machdep.h>
1.49      christos  107: #include <compat/linux/common/linux_types.h>
                    108: #include <compat/linux/common/linux_signal.h>
                    109:
1.1       fvdl      110: #include <compat/linux/linux_syscallargs.h>
1.49      christos  111:
                    112: #include <compat/linux/common/linux_fcntl.h>
                    113: #include <compat/linux/common/linux_mmap.h>
                    114: #include <compat/linux/common/linux_dirent.h>
                    115: #include <compat/linux/common/linux_util.h>
                    116: #include <compat/linux/common/linux_misc.h>
1.150     manu      117: #ifndef COMPAT_LINUX32
                    118: #include <compat/linux/common/linux_limit.h>
                    119: #endif
1.62      tron      120: #include <compat/linux/common/linux_ptrace.h>
1.67      erh       121: #include <compat/linux/common/linux_reboot.h>
1.84      manu      122: #include <compat/linux/common/linux_emuldata.h>
1.49      christos  123:
1.150     manu      124: #ifndef COMPAT_LINUX32
1.73      jdolecek  125: const int linux_ptrace_request_map[] = {
1.62      tron      126:        LINUX_PTRACE_TRACEME,   PT_TRACE_ME,
                    127:        LINUX_PTRACE_PEEKTEXT,  PT_READ_I,
                    128:        LINUX_PTRACE_PEEKDATA,  PT_READ_D,
                    129:        LINUX_PTRACE_POKETEXT,  PT_WRITE_I,
                    130:        LINUX_PTRACE_POKEDATA,  PT_WRITE_D,
                    131:        LINUX_PTRACE_CONT,      PT_CONTINUE,
                    132:        LINUX_PTRACE_KILL,      PT_KILL,
                    133:        LINUX_PTRACE_ATTACH,    PT_ATTACH,
                    134:        LINUX_PTRACE_DETACH,    PT_DETACH,
1.150     manu      135: # ifdef PT_STEP
1.73      jdolecek  136:        LINUX_PTRACE_SINGLESTEP,        PT_STEP,
1.150     manu      137: # endif
1.62      tron      138:        -1
                    139: };
1.1       fvdl      140:
1.132     jdolecek  141: const struct linux_mnttypes linux_fstypes[] = {
1.101     christos  142:        { MOUNT_FFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    143:        { MOUNT_NFS,            LINUX_NFS_SUPER_MAGIC           },
                    144:        { MOUNT_MFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    145:        { MOUNT_MSDOS,          LINUX_MSDOS_SUPER_MAGIC         },
                    146:        { MOUNT_LFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    147:        { MOUNT_FDESC,          LINUX_DEFAULT_SUPER_MAGIC       },
                    148:        { MOUNT_PORTAL,         LINUX_DEFAULT_SUPER_MAGIC       },
                    149:        { MOUNT_NULL,           LINUX_DEFAULT_SUPER_MAGIC       },
1.135     perry     150:        { MOUNT_OVERLAY,        LINUX_DEFAULT_SUPER_MAGIC       },
1.101     christos  151:        { MOUNT_UMAP,           LINUX_DEFAULT_SUPER_MAGIC       },
                    152:        { MOUNT_KERNFS,         LINUX_DEFAULT_SUPER_MAGIC       },
                    153:        { MOUNT_PROCFS,         LINUX_PROC_SUPER_MAGIC          },
                    154:        { MOUNT_AFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    155:        { MOUNT_CD9660,         LINUX_ISOFS_SUPER_MAGIC         },
                    156:        { MOUNT_UNION,          LINUX_DEFAULT_SUPER_MAGIC       },
                    157:        { MOUNT_ADOSFS,         LINUX_ADFS_SUPER_MAGIC          },
                    158:        { MOUNT_EXT2FS,         LINUX_EXT2_SUPER_MAGIC          },
                    159:        { MOUNT_CFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    160:        { MOUNT_CODA,           LINUX_CODA_SUPER_MAGIC          },
                    161:        { MOUNT_FILECORE,       LINUX_DEFAULT_SUPER_MAGIC       },
                    162:        { MOUNT_NTFS,           LINUX_DEFAULT_SUPER_MAGIC       },
1.134     christos  163:        { MOUNT_SMBFS,          LINUX_SMB_SUPER_MAGIC           },
1.140     jmmv      164:        { MOUNT_PTYFS,          LINUX_DEVPTS_SUPER_MAGIC        },
                    165:        { MOUNT_TMPFS,          LINUX_DEFAULT_SUPER_MAGIC       }
1.101     christos  166: };
1.132     jdolecek  167: const int linux_fstypes_cnt = sizeof(linux_fstypes) / sizeof(linux_fstypes[0]);
1.101     christos  168:
1.150     manu      169: # ifdef DEBUG_LINUX
1.104     christos  170: #define DPRINTF(a)     uprintf a
1.150     manu      171: # else
1.104     christos  172: #define DPRINTF(a)
1.150     manu      173: # endif
1.104     christos  174:
1.47      erh       175: /* Local linux_misc.c functions: */
1.150     manu      176: # ifndef __amd64__
1.123     christos  177: static void bsd_to_linux_statfs __P((const struct statvfs *,
                    178:     struct linux_statfs *));
1.150     manu      179: # endif
1.118     christos  180: static void linux_to_bsd_mmap_args __P((struct sys_mmap_args *,
                    181:     const struct linux_sys_mmap_args *));
1.128     jdolecek  182: static int linux_mmap __P((struct lwp *, struct linux_sys_mmap_args *,
                    183:     register_t *, off_t));
                    184:
1.26      christos  185:
1.1       fvdl      186: /*
                    187:  * The information on a terminated (or stopped) process needs
                    188:  * to be converted in order for Linux binaries to get a valid signal
                    189:  * number out of it.
                    190:  */
1.47      erh       191: void
1.52      christos  192: bsd_to_linux_wstat(st)
                    193:        int *st;
1.1       fvdl      194: {
1.21      mycroft   195:
1.52      christos  196:        int sig;
                    197:
                    198:        if (WIFSIGNALED(*st)) {
                    199:                sig = WTERMSIG(*st);
                    200:                if (sig >= 0 && sig < NSIG)
1.105     christos  201:                        *st= (*st& ~0177) | native_to_linux_signo[sig];
1.52      christos  202:        } else if (WIFSTOPPED(*st)) {
                    203:                sig = WSTOPSIG(*st);
                    204:                if (sig >= 0 && sig < NSIG)
1.105     christos  205:                        *st = (*st & ~0xff00) |
                    206:                            (native_to_linux_signo[sig] << 8);
1.52      christos  207:        }
1.1       fvdl      208: }
                    209:
                    210: /*
1.133     erh       211:  * wait4(2).  Passed on to the NetBSD call, surrounded by code to
                    212:  * reserve some space for a NetBSD-style wait status, and converting
                    213:  * it to what Linux wants.
1.1       fvdl      214:  */
                    215: int
1.116     thorpej   216: linux_sys_wait4(l, v, retval)
                    217:        struct lwp *l;
1.20      thorpej   218:        void *v;
                    219:        register_t *retval;
                    220: {
1.21      mycroft   221:        struct linux_sys_wait4_args /* {
1.1       fvdl      222:                syscallarg(int) pid;
                    223:                syscallarg(int *) status;
                    224:                syscallarg(int) options;
                    225:                syscallarg(struct rusage *) rusage;
1.20      thorpej   226:        } */ *uap = v;
1.116     thorpej   227:        struct proc *p = l->l_proc;
1.21      mycroft   228:        struct sys_wait4_args w4a;
1.55      thorpej   229:        int error, *status, tstat, options, linux_options;
1.1       fvdl      230:        caddr_t sg;
                    231:
1.16      fvdl      232:        if (SCARG(uap, status) != NULL) {
1.102     christos  233:                sg = stackgap_init(p, 0);
                    234:                status = (int *) stackgap_alloc(p, &sg, sizeof *status);
1.16      fvdl      235:        } else
                    236:                status = NULL;
1.1       fvdl      237:
1.55      thorpej   238:        linux_options = SCARG(uap, options);
                    239:        options = 0;
1.133     erh       240:        if (linux_options & ~(LINUX_WAIT4_KNOWNFLAGS))
1.55      thorpej   241:                return (EINVAL);
                    242:
                    243:        if (linux_options & LINUX_WAIT4_WNOHANG)
                    244:                options |= WNOHANG;
                    245:        if (linux_options & LINUX_WAIT4_WUNTRACED)
                    246:                options |= WUNTRACED;
1.93      thorpej   247:        if (linux_options & LINUX_WAIT4_WALL)
                    248:                options |= WALLSIG;
1.55      thorpej   249:        if (linux_options & LINUX_WAIT4_WCLONE)
                    250:                options |= WALTSIG;
1.150     manu      251: # ifdef DIAGNOSTIC
1.133     erh       252:        if (linux_options & LINUX_WAIT4_WNOTHREAD)
                    253:                printf("WARNING: %s: linux process %d.%d called "
                    254:                       "waitpid with __WNOTHREAD set!",
                    255:                       __FILE__, p->p_pid, l->l_lid);
                    256:
1.150     manu      257: # endif
1.55      thorpej   258:
1.1       fvdl      259:        SCARG(&w4a, pid) = SCARG(uap, pid);
                    260:        SCARG(&w4a, status) = status;
1.55      thorpej   261:        SCARG(&w4a, options) = options;
1.1       fvdl      262:        SCARG(&w4a, rusage) = SCARG(uap, rusage);
                    263:
1.116     thorpej   264:        if ((error = sys_wait4(l, &w4a, retval)))
1.1       fvdl      265:                return error;
                    266:
1.80      jdolecek  267:        sigdelset(&p->p_sigctx.ps_siglist, SIGCHLD);
1.18      fvdl      268:
1.16      fvdl      269:        if (status != NULL) {
                    270:                if ((error = copyin(status, &tstat, sizeof tstat)))
                    271:                        return error;
                    272:
                    273:                bsd_to_linux_wstat(&tstat);
                    274:                return copyout(&tstat, SCARG(uap, status), sizeof tstat);
                    275:        }
1.1       fvdl      276:
1.16      fvdl      277:        return 0;
1.1       fvdl      278: }
                    279:
                    280: /*
                    281:  * Linux brk(2). The check if the new address is >= the old one is
                    282:  * done in the kernel in Linux. NetBSD does it in the library.
                    283:  */
                    284: int
1.116     thorpej   285: linux_sys_brk(l, v, retval)
                    286:        struct lwp *l;
1.20      thorpej   287:        void *v;
                    288:        register_t *retval;
                    289: {
1.21      mycroft   290:        struct linux_sys_brk_args /* {
1.1       fvdl      291:                syscallarg(char *) nsize;
1.20      thorpej   292:        } */ *uap = v;
1.116     thorpej   293:        struct proc *p = l->l_proc;
1.1       fvdl      294:        char *nbrk = SCARG(uap, nsize);
1.21      mycroft   295:        struct sys_obreak_args oba;
1.1       fvdl      296:        struct vmspace *vm = p->p_vmspace;
1.85      manu      297:        struct linux_emuldata *ed = (struct linux_emuldata*)p->p_emuldata;
1.84      manu      298:
1.1       fvdl      299:        SCARG(&oba, nsize) = nbrk;
                    300:
1.116     thorpej   301:        if ((caddr_t) nbrk > vm->vm_daddr && sys_obreak(l, &oba, retval) == 0)
1.127     jdolecek  302:                ed->s->p_break = (char*)nbrk;
1.135     perry     303:        else
1.127     jdolecek  304:                nbrk = ed->s->p_break;
1.85      manu      305:
                    306:        retval[0] = (register_t)nbrk;
1.1       fvdl      307:
                    308:        return 0;
                    309: }
                    310:
1.150     manu      311: # ifndef __amd64__
1.1       fvdl      312: /*
1.131     jdolecek  313:  * Convert NetBSD statvfs structure to Linux statfs structure.
                    314:  * Linux doesn't have f_flag, and we can't set f_frsize due
                    315:  * to glibc statvfs() bug (see below).
1.2       fvdl      316:  */
                    317: static void
                    318: bsd_to_linux_statfs(bsp, lsp)
1.123     christos  319:        const struct statvfs *bsp;
1.2       fvdl      320:        struct linux_statfs *lsp;
                    321: {
1.101     christos  322:        int i;
                    323:
1.132     jdolecek  324:        for (i = 0; i < linux_fstypes_cnt; i++) {
                    325:                if (strcmp(bsp->f_fstypename, linux_fstypes[i].bsd) == 0) {
                    326:                        lsp->l_ftype = linux_fstypes[i].linux;
1.101     christos  327:                        break;
1.132     jdolecek  328:                }
                    329:        }
1.101     christos  330:
1.132     jdolecek  331:        if (i == linux_fstypes_cnt) {
1.104     christos  332:                DPRINTF(("unhandled fstype in linux emulation: %s\n",
                    333:                    bsp->f_fstypename));
1.101     christos  334:                lsp->l_ftype = LINUX_DEFAULT_SUPER_MAGIC;
                    335:        }
1.21      mycroft   336:
1.131     jdolecek  337:        /*
                    338:         * The sizes are expressed in number of blocks. The block
                    339:         * size used for the size is f_frsize for POSIX-compliant
                    340:         * statvfs. Linux statfs uses f_bsize as the block size
                    341:         * (f_frsize used to not be available in Linux struct statfs).
                    342:         * However, glibc 2.3.3 statvfs() wrapper fails to adjust the block
                    343:         * counts for different f_frsize if f_frsize is provided by the kernel.
                    344:         * POSIX conforming apps thus get wrong size if f_frsize
                    345:         * is different to f_bsize. Thus, we just pretend we don't
                    346:         * support f_frsize.
                    347:         */
                    348:
1.129     jdolecek  349:        lsp->l_fbsize = bsp->f_frsize;
1.131     jdolecek  350:        lsp->l_ffrsize = 0;                     /* compat */
1.2       fvdl      351:        lsp->l_fblocks = bsp->f_blocks;
                    352:        lsp->l_fbfree = bsp->f_bfree;
                    353:        lsp->l_fbavail = bsp->f_bavail;
                    354:        lsp->l_ffiles = bsp->f_files;
                    355:        lsp->l_fffree = bsp->f_ffree;
1.101     christos  356:        /* Linux sets the fsid to 0..., we don't */
1.123     christos  357:        lsp->l_ffsid.val[0] = bsp->f_fsidx.__fsid_val[0];
                    358:        lsp->l_ffsid.val[1] = bsp->f_fsidx.__fsid_val[1];
1.129     jdolecek  359:        lsp->l_fnamelen = bsp->f_namemax;
1.101     christos  360:        (void)memset(lsp->l_fspare, 0, sizeof(lsp->l_fspare));
1.2       fvdl      361: }
                    362:
                    363: /*
                    364:  * Implement the fs stat functions. Straightforward.
1.1       fvdl      365:  */
                    366: int
1.116     thorpej   367: linux_sys_statfs(l, v, retval)
                    368:        struct lwp *l;
1.20      thorpej   369:        void *v;
                    370:        register_t *retval;
                    371: {
1.21      mycroft   372:        struct linux_sys_statfs_args /* {
1.53      christos  373:                syscallarg(const char *) path;
1.1       fvdl      374:                syscallarg(struct linux_statfs *) sp;
1.20      thorpej   375:        } */ *uap = v;
1.116     thorpej   376:        struct proc *p = l->l_proc;
1.151.2.2  yamt      377:        struct statvfs *btmp, *bsp;
1.2       fvdl      378:        struct linux_statfs ltmp;
1.124     christos  379:        struct sys_statvfs1_args bsa;
1.2       fvdl      380:        caddr_t sg;
                    381:        int error;
                    382:
1.102     christos  383:        sg = stackgap_init(p, 0);
1.151.2.2  yamt      384:        bsp = stackgap_alloc(p, &sg, sizeof (struct statvfs));
1.2       fvdl      385:
1.147     christos  386:        CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
1.2       fvdl      387:
                    388:        SCARG(&bsa, path) = SCARG(uap, path);
                    389:        SCARG(&bsa, buf) = bsp;
1.125     christos  390:        SCARG(&bsa, flags) = ST_WAIT;
1.2       fvdl      391:
1.125     christos  392:        if ((error = sys_statvfs1(l, &bsa, retval)))
1.2       fvdl      393:                return error;
                    394:
1.151.2.2  yamt      395:        btmp = STATVFSBUF_GET();
                    396:        error = copyin(bsp, btmp, sizeof(*btmp));
                    397:        if (error) {
                    398:                goto out;
                    399:        }
                    400:        bsd_to_linux_statfs(btmp, &ltmp);
                    401:        error = copyout(&ltmp, SCARG(uap, sp), sizeof ltmp);
                    402: out:
                    403:        STATVFSBUF_PUT(btmp);
                    404:        return error;
1.1       fvdl      405: }
                    406:
                    407: int
1.116     thorpej   408: linux_sys_fstatfs(l, v, retval)
                    409:        struct lwp *l;
1.20      thorpej   410:        void *v;
                    411:        register_t *retval;
                    412: {
1.21      mycroft   413:        struct linux_sys_fstatfs_args /* {
1.2       fvdl      414:                syscallarg(int) fd;
1.1       fvdl      415:                syscallarg(struct linux_statfs *) sp;
1.20      thorpej   416:        } */ *uap = v;
1.116     thorpej   417:        struct proc *p = l->l_proc;
1.151.2.2  yamt      418:        struct statvfs *btmp, *bsp;
1.2       fvdl      419:        struct linux_statfs ltmp;
1.125     christos  420:        struct sys_fstatvfs1_args bsa;
1.2       fvdl      421:        caddr_t sg;
                    422:        int error;
                    423:
1.102     christos  424:        sg = stackgap_init(p, 0);
1.151.2.2  yamt      425:        bsp = stackgap_alloc(p, &sg, sizeof (struct statvfs));
1.2       fvdl      426:
                    427:        SCARG(&bsa, fd) = SCARG(uap, fd);
                    428:        SCARG(&bsa, buf) = bsp;
1.125     christos  429:        SCARG(&bsa, flags) = ST_WAIT;
1.2       fvdl      430:
1.125     christos  431:        if ((error = sys_fstatvfs1(l, &bsa, retval)))
1.2       fvdl      432:                return error;
                    433:
1.151.2.2  yamt      434:        btmp = STATVFSBUF_GET();
                    435:        error = copyin(bsp, btmp, sizeof(*btmp));
                    436:        if (error) {
                    437:                goto out;
                    438:        }
                    439:        bsd_to_linux_statfs(btmp, &ltmp);
                    440:        error = copyout(&ltmp, SCARG(uap, sp), sizeof ltmp);
                    441: out:
                    442:        STATVFSBUF_PUT(btmp);
                    443:        return error;
1.1       fvdl      444: }
1.150     manu      445: # endif /* !__amd64__ */
1.82      fvdl      446:
1.1       fvdl      447: /*
                    448:  * uname(). Just copy the info from the various strings stored in the
                    449:  * kernel, and put it in the Linux utsname structure. That structure
                    450:  * is almost the same as the NetBSD one, only it has fields 65 characters
                    451:  * long, and an extra domainname field.
                    452:  */
                    453: int
1.116     thorpej   454: linux_sys_uname(l, v, retval)
                    455:        struct lwp *l;
1.20      thorpej   456:        void *v;
                    457:        register_t *retval;
                    458: {
1.21      mycroft   459:        struct linux_sys_uname_args /* {
1.1       fvdl      460:                syscallarg(struct linux_utsname *) up;
1.20      thorpej   461:        } */ *uap = v;
1.15      mycroft   462:        struct linux_utsname luts;
1.1       fvdl      463:
1.82      fvdl      464:        strncpy(luts.l_sysname, linux_sysname, sizeof(luts.l_sysname));
1.15      mycroft   465:        strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
1.82      fvdl      466:        strncpy(luts.l_release, linux_release, sizeof(luts.l_release));
                    467:        strncpy(luts.l_version, linux_version, sizeof(luts.l_version));
1.150     manu      468: # ifdef LINUX_UNAME_ARCH
1.142     manu      469:        strncpy(luts.l_machine, LINUX_UNAME_ARCH, sizeof(luts.l_machine));
1.150     manu      470: # else
1.15      mycroft   471:        strncpy(luts.l_machine, machine, sizeof(luts.l_machine));
1.150     manu      472: # endif
1.15      mycroft   473:        strncpy(luts.l_domainname, domainname, sizeof(luts.l_domainname));
                    474:
                    475:        return copyout(&luts, SCARG(uap, up), sizeof(luts));
                    476: }
                    477:
1.47      erh       478: /* Used directly on: alpha, mips, ppc, sparc, sparc64 */
                    479: /* Used indirectly on: arm, i386, m68k */
1.1       fvdl      480:
                    481: /*
1.47      erh       482:  * New type Linux mmap call.
                    483:  * Only called directly on machines with >= 6 free regs.
1.1       fvdl      484:  */
                    485: int
1.116     thorpej   486: linux_sys_mmap(l, v, retval)
                    487:        struct lwp *l;
1.20      thorpej   488:        void *v;
                    489:        register_t *retval;
                    490: {
1.21      mycroft   491:        struct linux_sys_mmap_args /* {
1.47      erh       492:                syscallarg(unsigned long) addr;
                    493:                syscallarg(size_t) len;
                    494:                syscallarg(int) prot;
                    495:                syscallarg(int) flags;
                    496:                syscallarg(int) fd;
1.94      manu      497:                syscallarg(linux_off_t) offset;
1.20      thorpej   498:        } */ *uap = v;
1.118     christos  499:
1.115     christos  500:        if (SCARG(uap, offset) & PAGE_MASK)
                    501:                return EINVAL;
                    502:
1.128     jdolecek  503:        return linux_mmap(l, uap, retval, SCARG(uap, offset));
1.118     christos  504: }
                    505:
                    506: /*
                    507:  * Guts of most architectures' mmap64() implementations.  This shares
                    508:  * its list of arguments with linux_sys_mmap().
                    509:  *
                    510:  * The difference in linux_sys_mmap2() is that "offset" is actually
                    511:  * (offset / pagesize), not an absolute byte count.  This translation
                    512:  * to pagesize offsets is done inside glibc between the mmap64() call
                    513:  * point, and the actual syscall.
                    514:  */
                    515: int
                    516: linux_sys_mmap2(l, v, retval)
                    517:        struct lwp *l;
                    518:        void *v;
                    519:        register_t *retval;
                    520: {
                    521:        struct linux_sys_mmap2_args /* {
                    522:                syscallarg(unsigned long) addr;
                    523:                syscallarg(size_t) len;
                    524:                syscallarg(int) prot;
                    525:                syscallarg(int) flags;
                    526:                syscallarg(int) fd;
                    527:                syscallarg(linux_off_t) offset;
                    528:        } */ *uap = v;
1.128     jdolecek  529:
                    530:        return linux_mmap(l, uap, retval,
                    531:            ((off_t)SCARG(uap, offset)) << PAGE_SHIFT);
                    532: }
                    533:
                    534: /*
                    535:  * Massage arguments and call system mmap(2).
                    536:  */
                    537: static int
                    538: linux_mmap(l, uap, retval, offset)
                    539:        struct lwp *l;
                    540:        struct linux_sys_mmap_args *uap;
                    541:        register_t *retval;
                    542:        off_t offset;
                    543: {
1.118     christos  544:        struct sys_mmap_args cma;
1.128     jdolecek  545:        int error;
                    546:        size_t mmoff=0;
                    547:
                    548:        if (SCARG(uap, flags) & LINUX_MAP_GROWSDOWN) {
                    549:                /*
                    550:                 * Request for stack-like memory segment. On linux, this
                    551:                 * works by mmap()ping (small) segment, which is automatically
                    552:                 * extended when page fault happens below the currently
                    553:                 * allocated area. We emulate this by allocating (typically
                    554:                 * bigger) segment sized at current stack size limit, and
                    555:                 * offsetting the requested and returned address accordingly.
                    556:                 * Since physical pages are only allocated on-demand, this
                    557:                 * is effectively identical.
                    558:                 */
                    559:                rlim_t ssl = l->l_proc->p_rlimit[RLIMIT_STACK].rlim_cur;
                    560:
                    561:                if (SCARG(uap, len) < ssl) {
                    562:                        /* Compute the address offset */
                    563:                        mmoff = round_page(ssl) - SCARG(uap, len);
                    564:
                    565:                        if (SCARG(uap, addr))
                    566:                                SCARG(uap, addr) -= mmoff;
                    567:
                    568:                        SCARG(uap, len) = (size_t) ssl;
                    569:                }
                    570:        }
1.118     christos  571:
                    572:        linux_to_bsd_mmap_args(&cma, uap);
1.128     jdolecek  573:        SCARG(&cma, pos) = offset;
                    574:
                    575:        error = sys_mmap(l, &cma, retval);
                    576:        if (error)
                    577:                return (error);
                    578:
                    579:        /* Shift the returned address for stack-like segment if necessary */
                    580:        if (SCARG(uap, flags) & LINUX_MAP_GROWSDOWN && mmoff)
                    581:                retval[0] += mmoff;
1.118     christos  582:
1.128     jdolecek  583:        return (0);
1.118     christos  584: }
                    585:
                    586: static void
                    587: linux_to_bsd_mmap_args(cma, uap)
                    588:        struct sys_mmap_args *cma;
                    589:        const struct linux_sys_mmap_args *uap;
                    590: {
1.119     christos  591:        int flags = MAP_TRYFIXED, fl = SCARG(uap, flags);
1.135     perry     592:
1.103     christos  593:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_SHARED, MAP_SHARED);
                    594:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_PRIVATE, MAP_PRIVATE);
                    595:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_FIXED, MAP_FIXED);
                    596:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_ANON, MAP_ANON);
1.47      erh       597:        /* XXX XAX ERH: Any other flags here?  There are more defined... */
                    598:
1.118     christos  599:        SCARG(cma, addr) = (void *)SCARG(uap, addr);
                    600:        SCARG(cma, len) = SCARG(uap, len);
                    601:        SCARG(cma, prot) = SCARG(uap, prot);
                    602:        if (SCARG(cma, prot) & VM_PROT_WRITE) /* XXX */
                    603:                SCARG(cma, prot) |= VM_PROT_READ;
                    604:        SCARG(cma, flags) = flags;
                    605:        SCARG(cma, fd) = flags & MAP_ANON ? -1 : SCARG(uap, fd);
                    606:        SCARG(cma, pad) = 0;
1.97      christos  607: }
                    608:
1.148     yamt      609: #define        LINUX_MREMAP_MAYMOVE    1
                    610: #define        LINUX_MREMAP_FIXED      2
                    611:
1.34      mycroft   612: int
1.116     thorpej   613: linux_sys_mremap(l, v, retval)
                    614:        struct lwp *l;
1.34      mycroft   615:        void *v;
                    616:        register_t *retval;
                    617: {
                    618:        struct linux_sys_mremap_args /* {
                    619:                syscallarg(void *) old_address;
                    620:                syscallarg(size_t) old_size;
                    621:                syscallarg(size_t) new_size;
                    622:                syscallarg(u_long) flags;
                    623:        } */ *uap = v;
1.148     yamt      624:
                    625:        struct proc *p;
                    626:        struct vm_map *map;
                    627:        vaddr_t oldva;
                    628:        vaddr_t newva;
                    629:        size_t oldsize;
                    630:        size_t newsize;
                    631:        int flags;
                    632:        int uvmflags;
1.42      thorpej   633:        int error;
                    634:
1.148     yamt      635:        flags = SCARG(uap, flags);
                    636:        oldva = (vaddr_t)SCARG(uap, old_address);
                    637:        oldsize = round_page(SCARG(uap, old_size));
                    638:        newsize = round_page(SCARG(uap, new_size));
1.149     yamt      639:        if ((flags & ~(LINUX_MREMAP_FIXED|LINUX_MREMAP_MAYMOVE)) != 0) {
                    640:                error = EINVAL;
                    641:                goto done;
                    642:        }
1.148     yamt      643:        if ((flags & LINUX_MREMAP_FIXED) != 0) {
1.149     yamt      644:                if ((flags & LINUX_MREMAP_MAYMOVE) == 0) {
                    645:                        error = EINVAL;
                    646:                        goto done;
                    647:                }
1.148     yamt      648: #if 0 /* notyet */
                    649:                newva = SCARG(uap, new_address);
                    650:                uvmflags = UVM_MREMAP_FIXED;
                    651: #else /* notyet */
                    652:                error = EOPNOTSUPP;
                    653:                goto done;
                    654: #endif /* notyet */
                    655:        } else if ((flags & LINUX_MREMAP_MAYMOVE) != 0) {
                    656:                uvmflags = 0;
                    657:        } else {
                    658:                newva = oldva;
                    659:                uvmflags = UVM_MREMAP_FIXED;
1.42      thorpej   660:        }
1.148     yamt      661:        p = l->l_proc;
                    662:        map = &p->p_vmspace->vm_map;
                    663:        error = uvm_mremap(map, oldva, oldsize, map, &newva, newsize, p,
                    664:            uvmflags);
1.42      thorpej   665:
1.148     yamt      666: done:
                    667:        *retval = (error != 0) ? 0 : (register_t)newva;
                    668:        return error;
1.24      fvdl      669: }
                    670:
                    671: int
1.116     thorpej   672: linux_sys_msync(l, v, retval)
                    673:        struct lwp *l;
1.24      fvdl      674:        void *v;
                    675:        register_t *retval;
                    676: {
                    677:        struct linux_sys_msync_args /* {
                    678:                syscallarg(caddr_t) addr;
                    679:                syscallarg(int) len;
                    680:                syscallarg(int) fl;
                    681:        } */ *uap = v;
                    682:
1.36      fvdl      683:        struct sys___msync13_args bma;
1.24      fvdl      684:
                    685:        /* flags are ignored */
                    686:        SCARG(&bma, addr) = SCARG(uap, addr);
                    687:        SCARG(&bma, len) = SCARG(uap, len);
1.36      fvdl      688:        SCARG(&bma, flags) = SCARG(uap, fl);
1.24      fvdl      689:
1.116     thorpej   690:        return sys___msync13(l, &bma, retval);
1.103     christos  691: }
                    692:
                    693: int
1.116     thorpej   694: linux_sys_mprotect(l, v, retval)
                    695:        struct lwp *l;
1.103     christos  696:        void *v;
                    697:        register_t *retval;
                    698: {
                    699:        struct linux_sys_mprotect_args /* {
                    700:                syscallarg(const void *) start;
                    701:                syscallarg(unsigned long) len;
                    702:                syscallarg(int) prot;
                    703:        } */ *uap = v;
                    704:        struct vm_map_entry *entry;
1.141     chs       705:        struct vm_map *map;
                    706:        struct proc *p;
                    707:        vaddr_t end, start, len, stacklim;
                    708:        int prot, grows;
1.103     christos  709:
1.141     chs       710:        start = (vaddr_t)SCARG(uap, start);
1.103     christos  711:        len = round_page(SCARG(uap, len));
1.141     chs       712:        prot = SCARG(uap, prot);
                    713:        grows = prot & (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP);
                    714:        prot &= ~grows;
1.103     christos  715:        end = start + len;
                    716:
1.141     chs       717:        if (start & PAGE_MASK)
                    718:                return EINVAL;
1.103     christos  719:        if (end < start)
                    720:                return EINVAL;
1.141     chs       721:        if (end == start)
1.103     christos  722:                return 0;
                    723:
1.141     chs       724:        if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
                    725:                return EINVAL;
                    726:        if (grows == (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP))
1.103     christos  727:                return EINVAL;
                    728:
1.141     chs       729:        p = l->l_proc;
                    730:        map = &p->p_vmspace->vm_map;
1.103     christos  731:        vm_map_lock(map);
1.150     manu      732: # ifdef notdef
1.103     christos  733:        VM_MAP_RANGE_CHECK(map, start, end);
1.150     manu      734: # endif
1.103     christos  735:        if (!uvm_map_lookup_entry(map, start, &entry) || entry->start > start) {
                    736:                vm_map_unlock(map);
1.126     jdolecek  737:                return ENOMEM;
1.103     christos  738:        }
1.141     chs       739:
                    740:        /*
                    741:         * Approximate the behaviour of PROT_GROWS{DOWN,UP}.
                    742:         */
                    743:
                    744:        stacklim = (vaddr_t)p->p_limit->pl_rlimit[RLIMIT_STACK].rlim_cur;
                    745:        if (grows & LINUX_PROT_GROWSDOWN) {
                    746:                if (USRSTACK - stacklim <= start && start < USRSTACK) {
                    747:                        start = USRSTACK - stacklim;
                    748:                } else {
                    749:                        start = entry->start;
                    750:                }
                    751:        } else if (grows & LINUX_PROT_GROWSUP) {
                    752:                if (USRSTACK <= end && end < USRSTACK + stacklim) {
                    753:                        end = USRSTACK + stacklim;
                    754:                } else {
                    755:                        end = entry->end;
                    756:                }
                    757:        }
1.103     christos  758:        vm_map_unlock(map);
                    759:        return uvm_map_protect(map, start, end, prot, FALSE);
1.1       fvdl      760: }
                    761:
                    762: /*
                    763:  * This code is partly stolen from src/lib/libc/compat-43/times.c
                    764:  */
                    765:
1.113     jdolecek  766: #define        CONVTCK(r)      (r.tv_sec * hz + r.tv_usec / (1000000 / hz))
1.1       fvdl      767:
                    768: int
1.116     thorpej   769: linux_sys_times(l, v, retval)
                    770:        struct lwp *l;
1.20      thorpej   771:        void *v;
                    772:        register_t *retval;
                    773: {
1.21      mycroft   774:        struct linux_sys_times_args /* {
1.1       fvdl      775:                syscallarg(struct times *) tms;
1.20      thorpej   776:        } */ *uap = v;
1.116     thorpej   777:        struct proc *p = l->l_proc;
1.1       fvdl      778:        struct timeval t;
1.151.2.3  yamt      779:        int error;
1.1       fvdl      780:
1.112     jdolecek  781:        if (SCARG(uap, tms)) {
                    782:                struct linux_tms ltms;
                    783:                struct rusage ru;
                    784:
                    785:                calcru(p, &ru.ru_utime, &ru.ru_stime, NULL);
                    786:                ltms.ltms_utime = CONVTCK(ru.ru_utime);
                    787:                ltms.ltms_stime = CONVTCK(ru.ru_stime);
1.1       fvdl      788:
1.112     jdolecek  789:                ltms.ltms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime);
                    790:                ltms.ltms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime);
1.1       fvdl      791:
1.112     jdolecek  792:                if ((error = copyout(&ltms, SCARG(uap, tms), sizeof ltms)))
                    793:                        return error;
                    794:        }
1.1       fvdl      795:
1.151.2.3  yamt      796:        getmicrouptime(&t);
1.1       fvdl      797:
                    798:        retval[0] = ((linux_clock_t)(CONVTCK(t)));
                    799:        return 0;
                    800: }
1.113     jdolecek  801:
                    802: #undef CONVTCK
1.1       fvdl      803:
                    804: /*
                    805:  * Linux 'readdir' call. This code is mostly taken from the
                    806:  * SunOS getdents call (see compat/sunos/sunos_misc.c), though
                    807:  * an attempt has been made to keep it a little cleaner (failing
                    808:  * miserably, because of the cruft needed if count 1 is passed).
                    809:  *
1.17      fvdl      810:  * The d_off field should contain the offset of the next valid entry,
                    811:  * but in Linux it has the offset of the entry itself. We emulate
                    812:  * that bug here.
                    813:  *
1.1       fvdl      814:  * Read in BSD-style entries, convert them, and copy them out.
                    815:  *
                    816:  * Note that this doesn't handle union-mounted filesystems.
                    817:  */
                    818: int
1.116     thorpej   819: linux_sys_getdents(l, v, retval)
                    820:        struct lwp *l;
1.20      thorpej   821:        void *v;
                    822:        register_t *retval;
                    823: {
1.47      erh       824:        struct linux_sys_getdents_args /* {
1.1       fvdl      825:                syscallarg(int) fd;
1.47      erh       826:                syscallarg(struct linux_dirent *) dent;
1.1       fvdl      827:                syscallarg(unsigned int) count;
1.20      thorpej   828:        } */ *uap = v;
1.69      augustss  829:        struct dirent *bdp;
1.1       fvdl      830:        struct vnode *vp;
1.138     christos  831:        caddr_t inp, tbuf;              /* BSD-format */
1.26      christos  832:        int len, reclen;                /* BSD-format */
1.51      fvdl      833:        caddr_t outp;                   /* Linux-format */
1.26      christos  834:        int resid, linux_reclen = 0;    /* Linux-format */
1.1       fvdl      835:        struct file *fp;
                    836:        struct uio auio;
                    837:        struct iovec aiov;
                    838:        struct linux_dirent idb;
                    839:        off_t off;              /* true file offset */
1.17      fvdl      840:        int buflen, error, eofflag, nbytes, oldcall;
1.1       fvdl      841:        struct vattr va;
1.40      fvdl      842:        off_t *cookiebuf = NULL, *cookie;
1.22      mycroft   843:        int ncookies;
1.1       fvdl      844:
1.54      thorpej   845:        /* getvnode() will use the descriptor for us */
1.151.2.4! yamt      846:        if ((error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
1.1       fvdl      847:                return (error);
                    848:
1.54      thorpej   849:        if ((fp->f_flag & FREAD) == 0) {
                    850:                error = EBADF;
                    851:                goto out1;
                    852:        }
1.1       fvdl      853:
1.5       mycroft   854:        vp = (struct vnode *)fp->f_data;
1.54      thorpej   855:        if (vp->v_type != VDIR) {
                    856:                error = EINVAL;
                    857:                goto out1;
                    858:        }
1.1       fvdl      859:
1.151.2.4! yamt      860:        if ((error = VOP_GETATTR(vp, &va, l->l_cred, l)))
1.54      thorpej   861:                goto out1;
1.1       fvdl      862:
                    863:        nbytes = SCARG(uap, count);
1.17      fvdl      864:        if (nbytes == 1) {      /* emulating old, broken behaviour */
1.107     christos  865:                nbytes = sizeof (idb);
1.5       mycroft   866:                buflen = max(va.va_blocksize, nbytes);
1.17      fvdl      867:                oldcall = 1;
1.5       mycroft   868:        } else {
                    869:                buflen = min(MAXBSIZE, nbytes);
1.33      fvdl      870:                if (buflen < va.va_blocksize)
                    871:                        buflen = va.va_blocksize;
1.17      fvdl      872:                oldcall = 0;
1.1       fvdl      873:        }
1.138     christos  874:        tbuf = malloc(buflen, M_TEMP, M_WAITOK);
1.33      fvdl      875:
1.39      fvdl      876:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.1       fvdl      877:        off = fp->f_offset;
                    878: again:
1.138     christos  879:        aiov.iov_base = tbuf;
1.1       fvdl      880:        aiov.iov_len = buflen;
                    881:        auio.uio_iov = &aiov;
                    882:        auio.uio_iovcnt = 1;
                    883:        auio.uio_rw = UIO_READ;
                    884:        auio.uio_resid = buflen;
                    885:        auio.uio_offset = off;
1.151     yamt      886:        UIO_SETUP_SYSSPACE(&auio);
1.1       fvdl      887:        /*
                    888:          * First we read into the malloc'ed buffer, then
                    889:          * we massage it into user space, one record at a time.
                    890:          */
1.39      fvdl      891:        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
                    892:            &ncookies);
1.1       fvdl      893:        if (error)
                    894:                goto out;
                    895:
1.138     christos  896:        inp = tbuf;
1.51      fvdl      897:        outp = (caddr_t)SCARG(uap, dent);
1.1       fvdl      898:        resid = nbytes;
1.35      fvdl      899:        if ((len = buflen - auio.uio_resid) == 0)
1.1       fvdl      900:                goto eof;
                    901:
1.22      mycroft   902:        for (cookie = cookiebuf; len > 0; len -= reclen) {
1.5       mycroft   903:                bdp = (struct dirent *)inp;
                    904:                reclen = bdp->d_reclen;
1.1       fvdl      905:                if (reclen & 3)
                    906:                        panic("linux_readdir");
                    907:                if (bdp->d_fileno == 0) {
                    908:                        inp += reclen;  /* it is a hole; squish it out */
1.136     christos  909:                        if (cookie)
                    910:                                off = *cookie++;
                    911:                        else
                    912:                                off += reclen;
1.1       fvdl      913:                        continue;
                    914:                }
1.21      mycroft   915:                linux_reclen = LINUX_RECLEN(&idb, bdp->d_namlen);
                    916:                if (reclen > len || resid < linux_reclen) {
1.1       fvdl      917:                        /* entry too big for buffer, so just stop */
                    918:                        outp++;
                    919:                        break;
                    920:                }
                    921:                /*
                    922:                 * Massage in place to make a Linux-shaped dirent (otherwise
                    923:                 * we have to worry about touching user memory outside of
                    924:                 * the copyout() call).
                    925:                 */
1.107     christos  926:                idb.d_ino = bdp->d_fileno;
1.17      fvdl      927:                /*
1.21      mycroft   928:                 * The old readdir() call misuses the offset and reclen fields.
1.17      fvdl      929:                 */
1.22      mycroft   930:                if (oldcall) {
                    931:                        idb.d_off = (linux_off_t)linux_reclen;
                    932:                        idb.d_reclen = (u_short)bdp->d_namlen;
                    933:                } else {
1.109     tron      934:                        if (sizeof (idb.d_off) <= 4 && (off >> 32) != 0) {
1.33      fvdl      935:                                compat_offseterr(vp, "linux_getdents");
                    936:                                error = EINVAL;
                    937:                                goto out;
                    938:                        }
1.22      mycroft   939:                        idb.d_off = (linux_off_t)off;
1.107     christos  940:                        idb.d_reclen = (u_short)linux_reclen;
                    941:                }
                    942:                strcpy(idb.d_name, bdp->d_name);
                    943:                if ((error = copyout((caddr_t)&idb, outp, linux_reclen)))
                    944:                        goto out;
                    945:                /* advance past this real entry */
                    946:                inp += reclen;
1.136     christos  947:                if (cookie)
                    948:                        off = *cookie++; /* each entry points to itself */
                    949:                else
                    950:                        off += reclen;
1.107     christos  951:                /* advance output past Linux-shaped entry */
                    952:                outp += linux_reclen;
                    953:                resid -= linux_reclen;
                    954:                if (oldcall)
                    955:                        break;
                    956:        }
                    957:
                    958:        /* if we squished out the whole block, try again */
                    959:        if (outp == (caddr_t)SCARG(uap, dent))
                    960:                goto again;
                    961:        fp->f_offset = off;     /* update the vnode offset */
                    962:
                    963:        if (oldcall)
                    964:                nbytes = resid + linux_reclen;
                    965:
                    966: eof:
                    967:        *retval = nbytes - resid;
                    968: out:
                    969:        VOP_UNLOCK(vp, 0);
                    970:        if (cookiebuf)
                    971:                free(cookiebuf, M_TEMP);
1.138     christos  972:        free(tbuf, M_TEMP);
1.107     christos  973: out1:
1.147     christos  974:        FILE_UNUSE(fp, l);
1.1       fvdl      975:        return error;
                    976: }
                    977:
                    978: /*
1.17      fvdl      979:  * Even when just using registers to pass arguments to syscalls you can
                    980:  * have 5 of them on the i386. So this newer version of select() does
                    981:  * this.
1.1       fvdl      982:  */
                    983: int
1.116     thorpej   984: linux_sys_select(l, v, retval)
                    985:        struct lwp *l;
1.20      thorpej   986:        void *v;
                    987:        register_t *retval;
                    988: {
1.21      mycroft   989:        struct linux_sys_select_args /* {
1.17      fvdl      990:                syscallarg(int) nfds;
                    991:                syscallarg(fd_set *) readfds;
                    992:                syscallarg(fd_set *) writefds;
                    993:                syscallarg(fd_set *) exceptfds;
                    994:                syscallarg(struct timeval *) timeout;
1.20      thorpej   995:        } */ *uap = v;
                    996:
1.116     thorpej   997:        return linux_select1(l, retval, SCARG(uap, nfds), SCARG(uap, readfds),
1.17      fvdl      998:            SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
                    999: }
                   1000:
                   1001: /*
                   1002:  * Common code for the old and new versions of select(). A couple of
                   1003:  * things are important:
                   1004:  * 1) return the amount of time left in the 'timeout' parameter
                   1005:  * 2) select never returns ERESTART on Linux, always return EINTR
                   1006:  */
                   1007: int
1.116     thorpej  1008: linux_select1(l, retval, nfds, readfds, writefds, exceptfds, timeout)
                   1009:        struct lwp *l;
1.17      fvdl     1010:        register_t *retval;
                   1011:        int nfds;
                   1012:        fd_set *readfds, *writefds, *exceptfds;
                   1013:        struct timeval *timeout;
                   1014: {
1.21      mycroft  1015:        struct sys_select_args bsa;
1.116     thorpej  1016:        struct proc *p = l->l_proc;
1.13      mycroft  1017:        struct timeval tv0, tv1, utv, *tvp;
                   1018:        caddr_t sg;
1.1       fvdl     1019:        int error;
                   1020:
1.17      fvdl     1021:        SCARG(&bsa, nd) = nfds;
                   1022:        SCARG(&bsa, in) = readfds;
                   1023:        SCARG(&bsa, ou) = writefds;
                   1024:        SCARG(&bsa, ex) = exceptfds;
                   1025:        SCARG(&bsa, tv) = timeout;
1.1       fvdl     1026:
1.7       fvdl     1027:        /*
                   1028:         * Store current time for computation of the amount of
                   1029:         * time left.
                   1030:         */
1.17      fvdl     1031:        if (timeout) {
                   1032:                if ((error = copyin(timeout, &utv, sizeof(utv))))
1.13      mycroft  1033:                        return error;
                   1034:                if (itimerfix(&utv)) {
                   1035:                        /*
                   1036:                         * The timeval was invalid.  Convert it to something
                   1037:                         * valid that will act as it does under Linux.
                   1038:                         */
1.102     christos 1039:                        sg = stackgap_init(p, 0);
                   1040:                        tvp = stackgap_alloc(p, &sg, sizeof(utv));
1.13      mycroft  1041:                        utv.tv_sec += utv.tv_usec / 1000000;
                   1042:                        utv.tv_usec %= 1000000;
                   1043:                        if (utv.tv_usec < 0) {
                   1044:                                utv.tv_sec -= 1;
                   1045:                                utv.tv_usec += 1000000;
                   1046:                        }
                   1047:                        if (utv.tv_sec < 0)
                   1048:                                timerclear(&utv);
                   1049:                        if ((error = copyout(&utv, tvp, sizeof(utv))))
                   1050:                                return error;
                   1051:                        SCARG(&bsa, tv) = tvp;
                   1052:                }
1.7       fvdl     1053:                microtime(&tv0);
1.13      mycroft  1054:        }
1.7       fvdl     1055:
1.116     thorpej  1056:        error = sys_select(l, &bsa, retval);
1.10      mycroft  1057:        if (error) {
                   1058:                /*
                   1059:                 * See fs/select.c in the Linux kernel.  Without this,
                   1060:                 * Maelstrom doesn't work.
                   1061:                 */
                   1062:                if (error == ERESTART)
                   1063:                        error = EINTR;
1.7       fvdl     1064:                return error;
1.10      mycroft  1065:        }
1.7       fvdl     1066:
1.17      fvdl     1067:        if (timeout) {
1.14      mycroft  1068:                if (*retval) {
1.7       fvdl     1069:                        /*
1.13      mycroft  1070:                         * Compute how much time was left of the timeout,
1.7       fvdl     1071:                         * by subtracting the current time and the time
                   1072:                         * before we started the call, and subtracting
                   1073:                         * that result from the user-supplied value.
                   1074:                         */
                   1075:                        microtime(&tv1);
                   1076:                        timersub(&tv1, &tv0, &tv1);
                   1077:                        timersub(&utv, &tv1, &utv);
1.14      mycroft  1078:                        if (utv.tv_sec < 0)
                   1079:                                timerclear(&utv);
                   1080:                } else
                   1081:                        timerclear(&utv);
1.17      fvdl     1082:                if ((error = copyout(&utv, timeout, sizeof(utv))))
1.7       fvdl     1083:                        return error;
                   1084:        }
1.13      mycroft  1085:
1.7       fvdl     1086:        return 0;
1.1       fvdl     1087: }
                   1088:
                   1089: /*
                   1090:  * Get the process group of a certain process. Look it up
                   1091:  * and return the value.
                   1092:  */
                   1093: int
1.116     thorpej  1094: linux_sys_getpgid(l, v, retval)
                   1095:        struct lwp *l;
1.20      thorpej  1096:        void *v;
                   1097:        register_t *retval;
                   1098: {
1.21      mycroft  1099:        struct linux_sys_getpgid_args /* {
1.1       fvdl     1100:                syscallarg(int) pid;
1.20      thorpej  1101:        } */ *uap = v;
1.116     thorpej  1102:        struct proc *p = l->l_proc;
1.1       fvdl     1103:        struct proc *targp;
                   1104:
1.26      christos 1105:        if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != p->p_pid) {
1.1       fvdl     1106:                if ((targp = pfind(SCARG(uap, pid))) == 0)
                   1107:                        return ESRCH;
1.26      christos 1108:        }
1.1       fvdl     1109:        else
                   1110:                targp = p;
                   1111:
                   1112:        retval[0] = targp->p_pgid;
1.6       fvdl     1113:        return 0;
                   1114: }
                   1115:
                   1116: /*
                   1117:  * Set the 'personality' (emulation mode) for the current process. Only
                   1118:  * accept the Linux personality here (0). This call is needed because
                   1119:  * the Linux ELF crt0 issues it in an ugly kludge to make sure that
                   1120:  * ELF binaries run in Linux mode, not SVR4 mode.
                   1121:  */
                   1122: int
1.116     thorpej  1123: linux_sys_personality(l, v, retval)
                   1124:        struct lwp *l;
1.20      thorpej  1125:        void *v;
                   1126:        register_t *retval;
                   1127: {
1.21      mycroft  1128:        struct linux_sys_personality_args /* {
1.6       fvdl     1129:                syscallarg(int) per;
1.20      thorpej  1130:        } */ *uap = v;
                   1131:
1.6       fvdl     1132:        if (SCARG(uap, per) != 0)
                   1133:                return EINVAL;
                   1134:        retval[0] = 0;
1.1       fvdl     1135:        return 0;
1.18      fvdl     1136: }
1.150     manu     1137: #endif /* !COMPAT_LINUX32 */
1.18      fvdl     1138:
1.150     manu     1139: #if defined(__i386__) || defined(__m68k__) || defined(COMPAT_LINUX32)
1.18      fvdl     1140: /*
                   1141:  * The calls are here because of type conversions.
                   1142:  */
                   1143: int
1.116     thorpej  1144: linux_sys_setreuid16(l, v, retval)
                   1145:        struct lwp *l;
1.20      thorpej  1146:        void *v;
                   1147:        register_t *retval;
                   1148: {
1.78      fvdl     1149:        struct linux_sys_setreuid16_args /* {
1.18      fvdl     1150:                syscallarg(int) ruid;
                   1151:                syscallarg(int) euid;
1.20      thorpej  1152:        } */ *uap = v;
1.28      mycroft  1153:        struct sys_setreuid_args bsa;
1.135     perry    1154:
1.18      fvdl     1155:        SCARG(&bsa, ruid) = ((linux_uid_t)SCARG(uap, ruid) == (linux_uid_t)-1) ?
                   1156:                (uid_t)-1 : SCARG(uap, ruid);
                   1157:        SCARG(&bsa, euid) = ((linux_uid_t)SCARG(uap, euid) == (linux_uid_t)-1) ?
                   1158:                (uid_t)-1 : SCARG(uap, euid);
                   1159:
1.116     thorpej  1160:        return sys_setreuid(l, &bsa, retval);
1.18      fvdl     1161: }
                   1162:
                   1163: int
1.116     thorpej  1164: linux_sys_setregid16(l, v, retval)
                   1165:        struct lwp *l;
1.20      thorpej  1166:        void *v;
                   1167:        register_t *retval;
                   1168: {
1.78      fvdl     1169:        struct linux_sys_setregid16_args /* {
1.18      fvdl     1170:                syscallarg(int) rgid;
                   1171:                syscallarg(int) egid;
1.20      thorpej  1172:        } */ *uap = v;
1.28      mycroft  1173:        struct sys_setregid_args bsa;
1.135     perry    1174:
1.18      fvdl     1175:        SCARG(&bsa, rgid) = ((linux_gid_t)SCARG(uap, rgid) == (linux_gid_t)-1) ?
                   1176:                (uid_t)-1 : SCARG(uap, rgid);
                   1177:        SCARG(&bsa, egid) = ((linux_gid_t)SCARG(uap, egid) == (linux_gid_t)-1) ?
                   1178:                (uid_t)-1 : SCARG(uap, egid);
                   1179:
1.116     thorpej  1180:        return sys_setregid(l, &bsa, retval);
1.63      abs      1181: }
1.81      fvdl     1182:
                   1183: int
1.116     thorpej  1184: linux_sys_setresuid16(l, v, retval)
                   1185:        struct lwp *l;
1.81      fvdl     1186:        void *v;
                   1187:        register_t *retval;
                   1188: {
                   1189:        struct linux_sys_setresuid16_args /* {
                   1190:                syscallarg(uid_t) ruid;
                   1191:                syscallarg(uid_t) euid;
                   1192:                syscallarg(uid_t) suid;
                   1193:        } */ *uap = v;
                   1194:        struct linux_sys_setresuid16_args lsa;
                   1195:
                   1196:        SCARG(&lsa, ruid) = ((linux_uid_t)SCARG(uap, ruid) == (linux_uid_t)-1) ?
                   1197:                (uid_t)-1 : SCARG(uap, ruid);
                   1198:        SCARG(&lsa, euid) = ((linux_uid_t)SCARG(uap, euid) == (linux_uid_t)-1) ?
                   1199:                (uid_t)-1 : SCARG(uap, euid);
                   1200:        SCARG(&lsa, suid) = ((linux_uid_t)SCARG(uap, suid) == (linux_uid_t)-1) ?
                   1201:                (uid_t)-1 : SCARG(uap, suid);
                   1202:
1.116     thorpej  1203:        return linux_sys_setresuid(l, &lsa, retval);
1.81      fvdl     1204: }
                   1205:
                   1206: int
1.116     thorpej  1207: linux_sys_setresgid16(l, v, retval)
                   1208:        struct lwp *l;
1.81      fvdl     1209:        void *v;
                   1210:        register_t *retval;
                   1211: {
                   1212:        struct linux_sys_setresgid16_args /* {
                   1213:                syscallarg(gid_t) rgid;
                   1214:                syscallarg(gid_t) egid;
                   1215:                syscallarg(gid_t) sgid;
                   1216:        } */ *uap = v;
                   1217:        struct linux_sys_setresgid16_args lsa;
                   1218:
                   1219:        SCARG(&lsa, rgid) = ((linux_gid_t)SCARG(uap, rgid) == (linux_gid_t)-1) ?
                   1220:                (gid_t)-1 : SCARG(uap, rgid);
                   1221:        SCARG(&lsa, egid) = ((linux_gid_t)SCARG(uap, egid) == (linux_gid_t)-1) ?
                   1222:                (gid_t)-1 : SCARG(uap, egid);
                   1223:        SCARG(&lsa, sgid) = ((linux_gid_t)SCARG(uap, sgid) == (linux_gid_t)-1) ?
                   1224:                (gid_t)-1 : SCARG(uap, sgid);
                   1225:
1.116     thorpej  1226:        return linux_sys_setresgid(l, &lsa, retval);
1.81      fvdl     1227: }
                   1228:
                   1229: int
1.116     thorpej  1230: linux_sys_getgroups16(l, v, retval)
                   1231:        struct lwp *l;
1.81      fvdl     1232:        void *v;
                   1233:        register_t *retval;
                   1234: {
                   1235:        struct linux_sys_getgroups16_args /* {
                   1236:                syscallarg(int) gidsetsize;
                   1237:                syscallarg(linux_gid_t *) gidset;
                   1238:        } */ *uap = v;
1.116     thorpej  1239:        struct proc *p = l->l_proc;
1.135     perry    1240:        caddr_t sg;
1.81      fvdl     1241:        int n, error, i;
                   1242:        struct sys_getgroups_args bsa;
                   1243:        gid_t *bset, *kbset;
                   1244:        linux_gid_t *lset;
1.151.2.4! yamt     1245:        kauth_cred_t pc = l->l_cred;
1.81      fvdl     1246:
                   1247:        n = SCARG(uap, gidsetsize);
                   1248:        if (n < 0)
                   1249:                return EINVAL;
                   1250:        error = 0;
                   1251:        bset = kbset = NULL;
                   1252:        lset = NULL;
                   1253:        if (n > 0) {
1.151.2.2  yamt     1254:                n = min(kauth_cred_ngroups(pc), n);
1.102     christos 1255:                sg = stackgap_init(p, 0);
                   1256:                bset = stackgap_alloc(p, &sg, n * sizeof (gid_t));
1.81      fvdl     1257:                kbset = malloc(n * sizeof (gid_t), M_TEMP, M_WAITOK);
                   1258:                lset = malloc(n * sizeof (linux_gid_t), M_TEMP, M_WAITOK);
                   1259:                if (bset == NULL || kbset == NULL || lset == NULL)
1.151.2.1  yamt     1260:                {
                   1261:                        error = ENOMEM;
                   1262:                        goto out;
                   1263:                }
1.81      fvdl     1264:                SCARG(&bsa, gidsetsize) = n;
                   1265:                SCARG(&bsa, gidset) = bset;
1.116     thorpej  1266:                error = sys_getgroups(l, &bsa, retval);
1.81      fvdl     1267:                if (error != 0)
                   1268:                        goto out;
                   1269:                error = copyin(bset, kbset, n * sizeof (gid_t));
                   1270:                if (error != 0)
                   1271:                        goto out;
                   1272:                for (i = 0; i < n; i++)
                   1273:                        lset[i] = (linux_gid_t)kbset[i];
                   1274:                error = copyout(lset, SCARG(uap, gidset),
                   1275:                    n * sizeof (linux_gid_t));
                   1276:        } else
1.151.2.2  yamt     1277:                *retval = kauth_cred_ngroups(pc);
1.81      fvdl     1278: out:
                   1279:        if (kbset != NULL)
                   1280:                free(kbset, M_TEMP);
                   1281:        if (lset != NULL)
                   1282:                free(lset, M_TEMP);
                   1283:        return error;
                   1284: }
                   1285:
                   1286: int
1.116     thorpej  1287: linux_sys_setgroups16(l, v, retval)
                   1288:        struct lwp *l;
1.81      fvdl     1289:        void *v;
                   1290:        register_t *retval;
                   1291: {
                   1292:        struct linux_sys_setgroups16_args /* {
                   1293:                syscallarg(int) gidsetsize;
                   1294:                syscallarg(linux_gid_t *) gidset;
                   1295:        } */ *uap = v;
1.116     thorpej  1296:        struct proc *p = l->l_proc;
1.81      fvdl     1297:        caddr_t sg;
                   1298:        int n;
                   1299:        int error, i;
                   1300:        struct sys_setgroups_args bsa;
                   1301:        gid_t *bset, *kbset;
                   1302:        linux_gid_t *lset;
                   1303:
                   1304:        n = SCARG(uap, gidsetsize);
                   1305:        if (n < 0 || n > NGROUPS)
                   1306:                return EINVAL;
1.102     christos 1307:        sg = stackgap_init(p, 0);
                   1308:        bset = stackgap_alloc(p, &sg, n * sizeof (gid_t));
1.81      fvdl     1309:        lset = malloc(n * sizeof (linux_gid_t), M_TEMP, M_WAITOK);
1.106     fvdl     1310:        kbset = malloc(n * sizeof (gid_t), M_TEMP, M_WAITOK);
1.151.2.1  yamt     1311:        if (bset == NULL || kbset == NULL || lset == NULL)
                   1312:        {
                   1313:                error = ENOMEM;
                   1314:                goto out;
                   1315:        }
1.81      fvdl     1316:        error = copyin(SCARG(uap, gidset), lset, n * sizeof (linux_gid_t));
                   1317:        if (error != 0)
                   1318:                goto out;
                   1319:        for (i = 0; i < n; i++)
                   1320:                kbset[i] = (gid_t)lset[i];
                   1321:        error = copyout(kbset, bset, n * sizeof (gid_t));
                   1322:        if (error != 0)
                   1323:                goto out;
                   1324:        SCARG(&bsa, gidsetsize) = n;
                   1325:        SCARG(&bsa, gidset) = bset;
1.116     thorpej  1326:        error = sys_setgroups(l, &bsa, retval);
1.135     perry    1327:
1.81      fvdl     1328: out:
                   1329:        if (lset != NULL)
                   1330:                free(lset, M_TEMP);
                   1331:        if (kbset != NULL)
                   1332:                free(kbset, M_TEMP);
                   1333:
                   1334:        return error;
                   1335: }
                   1336:
1.150     manu     1337: #endif /* __i386__ || __m68k__ || COMPAT_LINUX32 */
1.63      abs      1338:
1.150     manu     1339: #ifndef COMPAT_LINUX32
1.63      abs      1340: /*
1.64      abs      1341:  * We have nonexistent fsuid equal to uid.
                   1342:  * If modification is requested, refuse.
1.63      abs      1343:  */
                   1344: int
1.116     thorpej  1345: linux_sys_setfsuid(l, v, retval)
                   1346:         struct lwp *l;
1.63      abs      1347:         void *v;
                   1348:         register_t *retval;
                   1349: {
                   1350:         struct linux_sys_setfsuid_args /* {
                   1351:                 syscallarg(uid_t) uid;
                   1352:         } */ *uap = v;
                   1353:         uid_t uid;
                   1354:
                   1355:         uid = SCARG(uap, uid);
1.151.2.4! yamt     1356:         if (kauth_cred_getuid(l->l_cred) != uid)
1.116     thorpej  1357:                 return sys_nosys(l, v, retval);
1.63      abs      1358:         else
                   1359:                 return (0);
                   1360: }
                   1361:
1.66      erh      1362: /* XXX XXX XXX */
1.150     manu     1363: # ifndef alpha
1.63      abs      1364: int
1.116     thorpej  1365: linux_sys_getfsuid(l, v, retval)
                   1366:        struct lwp *l;
1.66      erh      1367:        void *v;
                   1368:        register_t *retval;
1.63      abs      1369: {
1.116     thorpej  1370:        return sys_getuid(l, v, retval);
1.27      fvdl     1371: }
1.150     manu     1372: # endif
1.27      fvdl     1373:
                   1374: int
1.116     thorpej  1375: linux_sys_setresuid(l, v, retval)
                   1376:        struct lwp *l;
1.57      thorpej  1377:        void *v;
                   1378:        register_t *retval;
                   1379: {
                   1380:        struct linux_sys_setresuid_args /* {
                   1381:                syscallarg(uid_t) ruid;
                   1382:                syscallarg(uid_t) euid;
                   1383:                syscallarg(uid_t) suid;
                   1384:        } */ *uap = v;
                   1385:
                   1386:        /*
                   1387:         * Note: These checks are a little different than the NetBSD
                   1388:         * setreuid(2) call performs.  This precisely follows the
                   1389:         * behavior of the Linux kernel.
                   1390:         */
                   1391:
1.117     dsl      1392:        return do_setresuid(l, SCARG(uap, ruid), SCARG(uap, euid),
                   1393:                            SCARG(uap, suid),
                   1394:                            ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S |
                   1395:                            ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
                   1396:                            ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S );
1.57      thorpej  1397: }
                   1398:
                   1399: int
1.116     thorpej  1400: linux_sys_getresuid(l, v, retval)
                   1401:        struct lwp *l;
1.57      thorpej  1402:        void *v;
                   1403:        register_t *retval;
                   1404: {
                   1405:        struct linux_sys_getresuid_args /* {
                   1406:                syscallarg(uid_t *) ruid;
                   1407:                syscallarg(uid_t *) euid;
                   1408:                syscallarg(uid_t *) suid;
                   1409:        } */ *uap = v;
1.151.2.4! yamt     1410:        kauth_cred_t pc = l->l_cred;
1.57      thorpej  1411:        int error;
1.151.2.2  yamt     1412:        uid_t uid;
1.57      thorpej  1413:
                   1414:        /*
                   1415:         * Linux copies these values out to userspace like so:
                   1416:         *
                   1417:         *      1. Copy out ruid.
                   1418:         *      2. If that succeeds, copy out euid.
                   1419:         *      3. If both of those succeed, copy out suid.
                   1420:         */
1.151.2.2  yamt     1421:        uid = kauth_cred_getuid(pc);
                   1422:        if ((error = copyout(&uid, SCARG(uap, ruid), sizeof(uid_t))) != 0)
1.57      thorpej  1423:                return (error);
                   1424:
1.151.2.2  yamt     1425:        uid = kauth_cred_geteuid(pc);
                   1426:        if ((error = copyout(&uid, SCARG(uap, euid), sizeof(uid_t))) != 0)
1.57      thorpej  1427:                return (error);
                   1428:
1.151.2.2  yamt     1429:        uid = kauth_cred_getsvuid(pc);
                   1430:
                   1431:        return (copyout(&uid, SCARG(uap, suid), sizeof(uid_t)));
1.78      fvdl     1432: }
1.62      tron     1433:
                   1434: int
1.116     thorpej  1435: linux_sys_ptrace(l, v, retval)
                   1436:        struct lwp *l;
1.62      tron     1437:        void *v;
                   1438:        register_t *retval;
                   1439: {
                   1440:        struct linux_sys_ptrace_args /* {
1.88      manu     1441:                i386, m68k, powerpc: T=int
1.137     manu     1442:                alpha, amd64: T=long
1.66      erh      1443:                syscallarg(T) request;
                   1444:                syscallarg(T) pid;
                   1445:                syscallarg(T) addr;
                   1446:                syscallarg(T) data;
1.62      tron     1447:        } */ *uap = v;
1.73      jdolecek 1448:        const int *ptr;
                   1449:        int request;
1.89      manu     1450:        int error;
1.62      tron     1451:
                   1452:        ptr = linux_ptrace_request_map;
                   1453:        request = SCARG(uap, request);
                   1454:        while (*ptr != -1)
                   1455:                if (*ptr++ == request) {
                   1456:                        struct sys_ptrace_args pta;
                   1457:
                   1458:                        SCARG(&pta, req) = *ptr;
                   1459:                        SCARG(&pta, pid) = SCARG(uap, pid);
                   1460:                        SCARG(&pta, addr) = (caddr_t)SCARG(uap, addr);
                   1461:                        SCARG(&pta, data) = SCARG(uap, data);
                   1462:
1.73      jdolecek 1463:                        /*
                   1464:                         * Linux ptrace(PTRACE_CONT, pid, 0, 0) means actually
1.90      jdolecek 1465:                         * to continue where the process left off previously.
                   1466:                         * The same thing is achieved by addr == (caddr_t) 1
                   1467:                         * on NetBSD, so rewrite 'addr' appropriately.
1.73      jdolecek 1468:                         */
                   1469:                        if (request == LINUX_PTRACE_CONT && SCARG(uap, addr)==0)
                   1470:                                SCARG(&pta, addr) = (caddr_t) 1;
1.135     perry    1471:
1.116     thorpej  1472:                        error = sys_ptrace(l, &pta, retval);
1.135     perry    1473:                        if (error)
1.92      manu     1474:                                return error;
                   1475:                        switch (request) {
                   1476:                        case LINUX_PTRACE_PEEKTEXT:
                   1477:                        case LINUX_PTRACE_PEEKDATA:
1.135     perry    1478:                                error = copyout (retval,
1.137     manu     1479:                                    (caddr_t)SCARG(uap, data),
                   1480:                                    sizeof *retval);
1.92      manu     1481:                                *retval = SCARG(uap, data);
                   1482:                                break;
1.135     perry    1483:                        default:
1.92      manu     1484:                                break;
                   1485:                        }
1.89      manu     1486:                        return error;
1.62      tron     1487:                }
                   1488:                else
                   1489:                        ptr++;
                   1490:
1.116     thorpej  1491:        return LINUX_SYS_PTRACE_ARCH(l, uap, retval);
1.1       fvdl     1492: }
1.67      erh      1493:
                   1494: int
1.116     thorpej  1495: linux_sys_reboot(struct lwp *l, void *v, register_t *retval)
1.67      erh      1496: {
                   1497:        struct linux_sys_reboot_args /* {
                   1498:                syscallarg(int) magic1;
                   1499:                syscallarg(int) magic2;
                   1500:                syscallarg(int) cmd;
                   1501:                syscallarg(void *) arg;
                   1502:        } */ *uap = v;
                   1503:        struct sys_reboot_args /* {
                   1504:                syscallarg(int) opt;
                   1505:                syscallarg(char *) bootstr;
                   1506:        } */ sra;
                   1507:        int error;
                   1508:
1.151.2.4! yamt     1509:        if ((error = kauth_authorize_generic(l->l_cred,
        !          1510:            KAUTH_GENERIC_ISSUSER, &l->l_acflag)) != 0)
1.67      erh      1511:                return(error);
                   1512:
                   1513:        if (SCARG(uap, magic1) != LINUX_REBOOT_MAGIC1)
                   1514:                return(EINVAL);
                   1515:        if (SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2 &&
                   1516:            SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2A &&
                   1517:            SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2B)
                   1518:                return(EINVAL);
                   1519:
                   1520:        switch (SCARG(uap, cmd)) {
                   1521:        case LINUX_REBOOT_CMD_RESTART:
                   1522:                SCARG(&sra, opt) = RB_AUTOBOOT;
                   1523:                break;
                   1524:        case LINUX_REBOOT_CMD_HALT:
                   1525:                SCARG(&sra, opt) = RB_HALT;
                   1526:                break;
                   1527:        case LINUX_REBOOT_CMD_POWER_OFF:
                   1528:                SCARG(&sra, opt) = RB_HALT|RB_POWERDOWN;
                   1529:                break;
                   1530:        case LINUX_REBOOT_CMD_RESTART2:
                   1531:                /* Reboot with an argument. */
                   1532:                SCARG(&sra, opt) = RB_AUTOBOOT|RB_STRING;
                   1533:                SCARG(&sra, bootstr) = SCARG(uap, arg);
                   1534:                break;
                   1535:        case LINUX_REBOOT_CMD_CAD_ON:
                   1536:                return(EINVAL); /* We don't implement ctrl-alt-delete */
                   1537:        case LINUX_REBOOT_CMD_CAD_OFF:
                   1538:                return(0);
                   1539:        default:
                   1540:                return(EINVAL);
                   1541:        }
                   1542:
1.116     thorpej  1543:        return(sys_reboot(l, &sra, retval));
1.75      jdolecek 1544: }
                   1545:
                   1546: /*
                   1547:  * Copy of compat_12_sys_swapon().
                   1548:  */
                   1549: int
1.116     thorpej  1550: linux_sys_swapon(l, v, retval)
                   1551:        struct lwp *l;
1.75      jdolecek 1552:        void *v;
                   1553:        register_t *retval;
                   1554: {
                   1555:        struct sys_swapctl_args ua;
                   1556:        struct linux_sys_swapon_args /* {
                   1557:                syscallarg(const char *) name;
                   1558:        } */ *uap = v;
                   1559:
                   1560:        SCARG(&ua, cmd) = SWAP_ON;
1.139     drochner 1561:        SCARG(&ua, arg) = (void *)__UNCONST(SCARG(uap, name));
1.75      jdolecek 1562:        SCARG(&ua, misc) = 0;   /* priority */
1.116     thorpej  1563:        return (sys_swapctl(l, &ua, retval));
1.76      jdolecek 1564: }
                   1565:
                   1566: /*
                   1567:  * Stop swapping to the file or block device specified by path.
                   1568:  */
                   1569: int
1.116     thorpej  1570: linux_sys_swapoff(l, v, retval)
                   1571:        struct lwp *l;
1.76      jdolecek 1572:        void *v;
                   1573:        register_t *retval;
                   1574: {
                   1575:        struct sys_swapctl_args ua;
                   1576:        struct linux_sys_swapoff_args /* {
                   1577:                syscallarg(const char *) path;
                   1578:        } */ *uap = v;
                   1579:
                   1580:        SCARG(&ua, cmd) = SWAP_OFF;
1.138     christos 1581:        SCARG(&ua, arg) = __UNCONST(SCARG(uap, path)); /*XXXUNCONST*/
1.116     thorpej  1582:        return (sys_swapctl(l, &ua, retval));
1.75      jdolecek 1583: }
                   1584:
                   1585: /*
                   1586:  * Copy of compat_09_sys_setdomainname()
                   1587:  */
                   1588: /* ARGSUSED */
                   1589: int
1.116     thorpej  1590: linux_sys_setdomainname(l, v, retval)
                   1591:        struct lwp *l;
1.75      jdolecek 1592:        void *v;
                   1593:        register_t *retval;
                   1594: {
                   1595:        struct linux_sys_setdomainname_args /* {
                   1596:                syscallarg(char *) domainname;
                   1597:                syscallarg(int) len;
                   1598:        } */ *uap = v;
1.122     atatat   1599:        int name[2];
1.75      jdolecek 1600:
1.122     atatat   1601:        name[0] = CTL_KERN;
                   1602:        name[1] = KERN_DOMAINNAME;
                   1603:        return (old_sysctl(&name[0], 2, 0, 0, SCARG(uap, domainname),
                   1604:                            SCARG(uap, len), l));
1.77      augustss 1605: }
                   1606:
                   1607: /*
                   1608:  * sysinfo()
                   1609:  */
                   1610: /* ARGSUSED */
                   1611: int
1.116     thorpej  1612: linux_sys_sysinfo(l, v, retval)
                   1613:        struct lwp *l;
1.77      augustss 1614:        void *v;
                   1615:        register_t *retval;
                   1616: {
                   1617:        struct linux_sys_sysinfo_args /* {
                   1618:                syscallarg(struct linux_sysinfo *) arg;
                   1619:        } */ *uap = v;
                   1620:        struct linux_sysinfo si;
                   1621:        struct loadavg *la;
                   1622:
1.151.2.3  yamt     1623:        si.uptime = time_uptime;
1.77      augustss 1624:        la = &averunnable;
                   1625:        si.loads[0] = la->ldavg[0] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
                   1626:        si.loads[1] = la->ldavg[1] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
                   1627:        si.loads[2] = la->ldavg[2] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
                   1628:        si.totalram = ctob(physmem);
                   1629:        si.freeram = uvmexp.free * uvmexp.pagesize;
                   1630:        si.sharedram = 0;       /* XXX */
1.96      chs      1631:        si.bufferram = uvmexp.filepages * uvmexp.pagesize;
1.77      augustss 1632:        si.totalswap = uvmexp.swpages * uvmexp.pagesize;
                   1633:        si.freeswap = (uvmexp.swpages - uvmexp.swpginuse) * uvmexp.pagesize;
                   1634:        si.procs = nprocs;
                   1635:
                   1636:        /* The following are only present in newer Linux kernels. */
                   1637:        si.totalbig = 0;
                   1638:        si.freebig = 0;
                   1639:        si.mem_unit = 1;
                   1640:
                   1641:        return (copyout(&si, SCARG(uap, arg), sizeof si));
1.97      christos 1642: }
                   1643:
                   1644: int
1.116     thorpej  1645: linux_sys_getrlimit(l, v, retval)
                   1646:        struct lwp *l;
1.97      christos 1647:        void *v;
                   1648:        register_t *retval;
                   1649: {
                   1650:        struct linux_sys_getrlimit_args /* {
                   1651:                syscallarg(int) which;
1.150     manu     1652: # ifdef LINUX_LARGEFILE64
1.144     manu     1653:                syscallarg(struct rlimit *) rlp;
1.150     manu     1654: # else
1.97      christos 1655:                syscallarg(struct orlimit *) rlp;
1.150     manu     1656: # endif
1.97      christos 1657:        } */ *uap = v;
1.116     thorpej  1658:        struct proc *p = l->l_proc;
1.102     christos 1659:        caddr_t sg = stackgap_init(p, 0);
1.97      christos 1660:        struct sys_getrlimit_args ap;
                   1661:        struct rlimit rl;
1.150     manu     1662: # ifdef LINUX_LARGEFILE64
1.144     manu     1663:        struct rlimit orl;
1.150     manu     1664: # else
1.97      christos 1665:        struct orlimit orl;
1.150     manu     1666: # endif
1.97      christos 1667:        int error;
                   1668:
                   1669:        SCARG(&ap, which) = linux_to_bsd_limit(SCARG(uap, which));
                   1670:        if ((error = SCARG(&ap, which)) < 0)
                   1671:                return -error;
1.102     christos 1672:        SCARG(&ap, rlp) = stackgap_alloc(p, &sg, sizeof rl);
1.116     thorpej  1673:        if ((error = sys_getrlimit(l, &ap, retval)) != 0)
1.97      christos 1674:                return error;
                   1675:        if ((error = copyin(SCARG(&ap, rlp), &rl, sizeof(rl))) != 0)
                   1676:                return error;
                   1677:        bsd_to_linux_rlimit(&orl, &rl);
1.146     rpaulo   1678:
1.97      christos 1679:        return copyout(&orl, SCARG(uap, rlp), sizeof(orl));
                   1680: }
                   1681:
                   1682: int
1.116     thorpej  1683: linux_sys_setrlimit(l, v, retval)
                   1684:        struct lwp *l;
1.97      christos 1685:        void *v;
                   1686:        register_t *retval;
                   1687: {
                   1688:        struct linux_sys_setrlimit_args /* {
                   1689:                syscallarg(int) which;
1.150     manu     1690: # ifdef LINUX_LARGEFILE64
1.144     manu     1691:                syscallarg(struct rlimit *) rlp;
1.150     manu     1692: # else
1.97      christos 1693:                syscallarg(struct orlimit *) rlp;
1.150     manu     1694: # endif
1.97      christos 1695:        } */ *uap = v;
1.116     thorpej  1696:        struct proc *p = l->l_proc;
1.102     christos 1697:        caddr_t sg = stackgap_init(p, 0);
1.138     christos 1698:        struct sys_getrlimit_args ap;
1.97      christos 1699:        struct rlimit rl;
1.150     manu     1700: # ifdef LINUX_LARGEFILE64
1.144     manu     1701:        struct rlimit orl;
1.150     manu     1702: # else
1.97      christos 1703:        struct orlimit orl;
1.150     manu     1704: # endif
1.97      christos 1705:        int error;
                   1706:
                   1707:        SCARG(&ap, which) = linux_to_bsd_limit(SCARG(uap, which));
1.102     christos 1708:        SCARG(&ap, rlp) = stackgap_alloc(p, &sg, sizeof rl);
1.97      christos 1709:        if ((error = SCARG(&ap, which)) < 0)
                   1710:                return -error;
                   1711:        if ((error = copyin(SCARG(uap, rlp), &orl, sizeof(orl))) != 0)
                   1712:                return error;
                   1713:        linux_to_bsd_rlimit(&rl, &orl);
1.138     christos 1714:        if ((error = copyout(&rl, SCARG(&ap, rlp), sizeof(rl))) != 0)
1.97      christos 1715:                return error;
1.116     thorpej  1716:        return sys_setrlimit(l, &ap, retval);
1.97      christos 1717: }
                   1718:
1.150     manu     1719: # if !defined(__mips__) && !defined(__amd64__)
1.98      rafal    1720: /* XXX: this doesn't look 100% common, at least mips doesn't have it */
1.97      christos 1721: int
1.116     thorpej  1722: linux_sys_ugetrlimit(l, v, retval)
                   1723:        struct lwp *l;
1.97      christos 1724:        void *v;
                   1725:        register_t *retval;
                   1726: {
1.116     thorpej  1727:        return linux_sys_getrlimit(l, v, retval);
1.87      jdolecek 1728: }
1.150     manu     1729: # endif
1.87      jdolecek 1730:
                   1731: /*
                   1732:  * This gets called for unsupported syscalls. The difference to sys_nosys()
                   1733:  * is that process does not get SIGSYS, the call just returns with ENOSYS.
                   1734:  * This is the way Linux does it and glibc depends on this behaviour.
                   1735:  */
                   1736: int
1.116     thorpej  1737: linux_sys_nosys(l, v, retval)
                   1738:        struct lwp *l;
1.87      jdolecek 1739:        void *v;
                   1740:        register_t *retval;
                   1741: {
                   1742:        return (ENOSYS);
1.67      erh      1743: }
1.150     manu     1744:
1.151.2.3  yamt     1745: int
                   1746: linux_sys_getpriority(l, v, retval)
                   1747:         struct lwp *l;
                   1748:         void *v;
                   1749:         register_t *retval;
                   1750: {
                   1751:         struct linux_sys_getpriority_args /* {
                   1752:                 syscallarg(int) which;
                   1753:                 syscallarg(int) who;
                   1754:         } */ *uap = v;
                   1755:         struct sys_getpriority_args bsa;
                   1756:         int error;
                   1757:
                   1758:         SCARG(&bsa, which) = SCARG(uap, which);
                   1759:         SCARG(&bsa, who) = SCARG(uap, who);
                   1760:
                   1761:         if ((error = sys_getpriority(l, &bsa, retval)))
                   1762:                 return error;
                   1763:
                   1764:         *retval = NZERO - *retval;
                   1765:
                   1766:         return 0;
                   1767: }
                   1768:
1.150     manu     1769: #endif /* !COMPAT_LINUX32 */

CVSweb <webmaster@jp.NetBSD.org>