[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.121.2.4

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

CVSweb <webmaster@jp.NetBSD.org>