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

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

CVSweb <webmaster@jp.NetBSD.org>