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

1.239.4.2! martin      1: /*     $NetBSD$        */
1.47      erh         2:
                      3: /*-
1.194     ad          4:  * Copyright (c) 1995, 1998, 1999, 2008 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:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     21:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     22:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     23:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     30:  * POSSIBILITY OF SUCH DAMAGE.
1.1       fvdl       31:  */
                     32:
                     33: /*
                     34:  * Linux compatibility module. Try to deal with various Linux system calls.
                     35:  */
                     36:
1.47      erh        37: /*
                     38:  * These functions have been moved to multiarch to allow
1.135     perry      39:  * selection of which machines include them to be
1.47      erh        40:  * determined by the individual files.linux_<arch> files.
                     41:  *
                     42:  * Function in multiarch:
                     43:  *     linux_sys_break                 : linux_break.c
                     44:  *     linux_sys_alarm                 : linux_misc_notalpha.c
1.57      thorpej    45:  *     linux_sys_getresgid             : linux_misc_notalpha.c
1.47      erh        46:  *     linux_sys_nice                  : linux_misc_notalpha.c
                     47:  *     linux_sys_readdir               : linux_misc_notalpha.c
1.57      thorpej    48:  *     linux_sys_setresgid             : linux_misc_notalpha.c
1.47      erh        49:  *     linux_sys_time                  : linux_misc_notalpha.c
                     50:  *     linux_sys_utime                 : linux_misc_notalpha.c
                     51:  *     linux_sys_waitpid               : linux_misc_notalpha.c
                     52:  *     linux_sys_old_mmap              : linux_oldmmap.c
                     53:  *     linux_sys_oldolduname           : linux_oldolduname.c
                     54:  *     linux_sys_oldselect             : linux_oldselect.c
                     55:  *     linux_sys_olduname              : linux_olduname.c
                     56:  *     linux_sys_pipe                  : linux_pipe.c
                     57:  */
1.95      lukem      58:
                     59: #include <sys/cdefs.h>
1.239.4.2! martin     60: __KERNEL_RCSID(0, "$NetBSD$");
1.47      erh        61:
1.1       fvdl       62: #include <sys/param.h>
                     63: #include <sys/systm.h>
                     64: #include <sys/namei.h>
                     65: #include <sys/proc.h>
1.29      mycroft    66: #include <sys/dirent.h>
1.1       fvdl       67: #include <sys/file.h>
                     68: #include <sys/stat.h>
                     69: #include <sys/filedesc.h>
                     70: #include <sys/ioctl.h>
                     71: #include <sys/kernel.h>
                     72: #include <sys/malloc.h>
                     73: #include <sys/mbuf.h>
                     74: #include <sys/mman.h>
                     75: #include <sys/mount.h>
1.220     pooka      76: #include <sys/poll.h>
1.179     dsl        77: #include <sys/prot.h>
1.67      erh        78: #include <sys/reboot.h>
1.1       fvdl       79: #include <sys/resource.h>
                     80: #include <sys/resourcevar.h>
1.177     dsl        81: #include <sys/select.h>
1.1       fvdl       82: #include <sys/signal.h>
                     83: #include <sys/signalvar.h>
                     84: #include <sys/socket.h>
                     85: #include <sys/time.h>
                     86: #include <sys/times.h>
                     87: #include <sys/vnode.h>
                     88: #include <sys/uio.h>
                     89: #include <sys/wait.h>
                     90: #include <sys/utsname.h>
                     91: #include <sys/unistd.h>
1.172     dsl        92: #include <sys/vfs_syscalls.h>
1.75      jdolecek   93: #include <sys/swap.h>          /* for SWAP_ON */
                     94: #include <sys/sysctl.h>                /* for KERN_DOMAINNAME */
1.154     elad       95: #include <sys/kauth.h>
1.1       fvdl       96:
1.73      jdolecek   97: #include <sys/ptrace.h>
                     98: #include <machine/ptrace.h>
                     99:
1.161     matt      100: #include <sys/syscall.h>
1.1       fvdl      101: #include <sys/syscallargs.h>
                    102:
1.204     njoly     103: #include <compat/sys/resource.h>
                    104:
1.143     manu      105: #include <compat/linux/common/linux_machdep.h>
1.49      christos  106: #include <compat/linux/common/linux_types.h>
                    107: #include <compat/linux/common/linux_signal.h>
1.184     njoly     108: #include <compat/linux/common/linux_ipc.h>
                    109: #include <compat/linux/common/linux_sem.h>
1.49      christos  110:
                    111: #include <compat/linux/common/linux_fcntl.h>
                    112: #include <compat/linux/common/linux_mmap.h>
                    113: #include <compat/linux/common/linux_dirent.h>
                    114: #include <compat/linux/common/linux_util.h>
                    115: #include <compat/linux/common/linux_misc.h>
1.170     njoly     116: #include <compat/linux/common/linux_statfs.h>
1.150     manu      117: #include <compat/linux/common/linux_limit.h>
1.62      tron      118: #include <compat/linux/common/linux_ptrace.h>
1.67      erh       119: #include <compat/linux/common/linux_reboot.h>
1.84      manu      120: #include <compat/linux/common/linux_emuldata.h>
1.220     pooka     121: #include <compat/linux/common/linux_sched.h>
1.49      christos  122:
1.216     chs       123: #include <compat/linux/linux_syscallargs.h>
                    124:
1.73      jdolecek  125: const int linux_ptrace_request_map[] = {
1.62      tron      126:        LINUX_PTRACE_TRACEME,   PT_TRACE_ME,
                    127:        LINUX_PTRACE_PEEKTEXT,  PT_READ_I,
                    128:        LINUX_PTRACE_PEEKDATA,  PT_READ_D,
                    129:        LINUX_PTRACE_POKETEXT,  PT_WRITE_I,
                    130:        LINUX_PTRACE_POKEDATA,  PT_WRITE_D,
                    131:        LINUX_PTRACE_CONT,      PT_CONTINUE,
                    132:        LINUX_PTRACE_KILL,      PT_KILL,
                    133:        LINUX_PTRACE_ATTACH,    PT_ATTACH,
                    134:        LINUX_PTRACE_DETACH,    PT_DETACH,
1.150     manu      135: # ifdef PT_STEP
1.73      jdolecek  136:        LINUX_PTRACE_SINGLESTEP,        PT_STEP,
1.150     manu      137: # endif
1.170     njoly     138:        LINUX_PTRACE_SYSCALL,   PT_SYSCALL,
1.62      tron      139:        -1
                    140: };
1.1       fvdl      141:
1.132     jdolecek  142: const struct linux_mnttypes linux_fstypes[] = {
1.101     christos  143:        { MOUNT_FFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    144:        { MOUNT_NFS,            LINUX_NFS_SUPER_MAGIC           },
                    145:        { MOUNT_MFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    146:        { MOUNT_MSDOS,          LINUX_MSDOS_SUPER_MAGIC         },
                    147:        { MOUNT_LFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    148:        { MOUNT_FDESC,          LINUX_DEFAULT_SUPER_MAGIC       },
                    149:        { MOUNT_NULL,           LINUX_DEFAULT_SUPER_MAGIC       },
1.135     perry     150:        { MOUNT_OVERLAY,        LINUX_DEFAULT_SUPER_MAGIC       },
1.101     christos  151:        { MOUNT_UMAP,           LINUX_DEFAULT_SUPER_MAGIC       },
                    152:        { MOUNT_KERNFS,         LINUX_DEFAULT_SUPER_MAGIC       },
                    153:        { MOUNT_PROCFS,         LINUX_PROC_SUPER_MAGIC          },
                    154:        { MOUNT_AFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    155:        { MOUNT_CD9660,         LINUX_ISOFS_SUPER_MAGIC         },
                    156:        { MOUNT_UNION,          LINUX_DEFAULT_SUPER_MAGIC       },
                    157:        { MOUNT_ADOSFS,         LINUX_ADFS_SUPER_MAGIC          },
                    158:        { MOUNT_EXT2FS,         LINUX_EXT2_SUPER_MAGIC          },
                    159:        { MOUNT_CFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    160:        { MOUNT_CODA,           LINUX_CODA_SUPER_MAGIC          },
                    161:        { MOUNT_FILECORE,       LINUX_DEFAULT_SUPER_MAGIC       },
                    162:        { MOUNT_NTFS,           LINUX_DEFAULT_SUPER_MAGIC       },
1.134     christos  163:        { MOUNT_SMBFS,          LINUX_SMB_SUPER_MAGIC           },
1.140     jmmv      164:        { MOUNT_PTYFS,          LINUX_DEVPTS_SUPER_MAGIC        },
1.199     njoly     165:        { MOUNT_TMPFS,          LINUX_TMPFS_SUPER_MAGIC         }
1.101     christos  166: };
1.132     jdolecek  167: const int linux_fstypes_cnt = sizeof(linux_fstypes) / sizeof(linux_fstypes[0]);
1.101     christos  168:
1.150     manu      169: # ifdef DEBUG_LINUX
1.104     christos  170: #define DPRINTF(a)     uprintf a
1.150     manu      171: # else
1.104     christos  172: #define DPRINTF(a)
1.150     manu      173: # endif
1.104     christos  174:
1.47      erh       175: /* Local linux_misc.c functions: */
1.188     dsl       176: static void linux_to_bsd_mmap_args(struct sys_mmap_args *,
                    177:     const struct linux_sys_mmap_args *);
1.190     dsl       178: static int linux_mmap(struct lwp *, const struct linux_sys_mmap_args *,
1.188     dsl       179:     register_t *, off_t);
1.128     jdolecek  180:
1.26      christos  181:
1.1       fvdl      182: /*
                    183:  * The information on a terminated (or stopped) process needs
                    184:  * to be converted in order for Linux binaries to get a valid signal
                    185:  * number out of it.
                    186:  */
1.173     dsl       187: int
                    188: bsd_to_linux_wstat(int st)
1.1       fvdl      189: {
1.21      mycroft   190:
1.52      christos  191:        int sig;
                    192:
1.173     dsl       193:        if (WIFSIGNALED(st)) {
                    194:                sig = WTERMSIG(st);
1.52      christos  195:                if (sig >= 0 && sig < NSIG)
1.173     dsl       196:                        st= (st & ~0177) | native_to_linux_signo[sig];
                    197:        } else if (WIFSTOPPED(st)) {
                    198:                sig = WSTOPSIG(st);
1.52      christos  199:                if (sig >= 0 && sig < NSIG)
1.173     dsl       200:                        st = (st & ~0xff00) |
1.105     christos  201:                            (native_to_linux_signo[sig] << 8);
1.52      christos  202:        }
1.173     dsl       203:        return st;
1.1       fvdl      204: }
                    205:
                    206: /*
1.133     erh       207:  * wait4(2).  Passed on to the NetBSD call, surrounded by code to
                    208:  * reserve some space for a NetBSD-style wait status, and converting
                    209:  * it to what Linux wants.
1.1       fvdl      210:  */
                    211: int
1.190     dsl       212: linux_sys_wait4(struct lwp *l, const struct linux_sys_wait4_args *uap, register_t *retval)
1.20      thorpej   213: {
1.190     dsl       214:        /* {
1.1       fvdl      215:                syscallarg(int) pid;
                    216:                syscallarg(int *) status;
                    217:                syscallarg(int) options;
1.204     njoly     218:                syscallarg(struct rusage50 *) rusage;
1.190     dsl       219:        } */
1.210     rmind     220:        int error, status, options, linux_options, pid = SCARG(uap, pid);
                    221:        struct rusage50 ru50;
1.173     dsl       222:        struct rusage ru;
1.196     ad        223:        proc_t *p;
1.1       fvdl      224:
1.55      thorpej   225:        linux_options = SCARG(uap, options);
1.133     erh       226:        if (linux_options & ~(LINUX_WAIT4_KNOWNFLAGS))
1.55      thorpej   227:                return (EINVAL);
                    228:
1.233     christos  229:        options = 0;
1.55      thorpej   230:        if (linux_options & LINUX_WAIT4_WNOHANG)
                    231:                options |= WNOHANG;
                    232:        if (linux_options & LINUX_WAIT4_WUNTRACED)
                    233:                options |= WUNTRACED;
1.232     njoly     234:        if (linux_options & LINUX_WAIT4_WCONTINUED)
                    235:                options |= WCONTINUED;
1.93      thorpej   236:        if (linux_options & LINUX_WAIT4_WALL)
                    237:                options |= WALLSIG;
1.55      thorpej   238:        if (linux_options & LINUX_WAIT4_WCLONE)
                    239:                options |= WALTSIG;
1.150     manu      240: # ifdef DIAGNOSTIC
1.133     erh       241:        if (linux_options & LINUX_WAIT4_WNOTHREAD)
                    242:                printf("WARNING: %s: linux process %d.%d called "
                    243:                       "waitpid with __WNOTHREAD set!",
1.173     dsl       244:                       __FILE__, l->l_proc->p_pid, l->l_lid);
1.133     erh       245:
1.150     manu      246: # endif
1.55      thorpej   247:
1.210     rmind     248:        error = do_sys_wait(&pid, &status, options,
                    249:            SCARG(uap, rusage) != NULL ? &ru : NULL);
1.1       fvdl      250:
1.190     dsl       251:        retval[0] = pid;
                    252:        if (pid == 0)
1.1       fvdl      253:                return error;
                    254:
1.210     rmind     255:        p = curproc;
                    256:        mutex_enter(p->p_lock);
1.196     ad        257:        sigdelset(&p->p_sigpend.sp_set, SIGCHLD); /* XXXAD ksiginfo leak */
1.210     rmind     258:        mutex_exit(p->p_lock);
1.18      fvdl      259:
1.204     njoly     260:        if (SCARG(uap, rusage) != NULL) {
                    261:                rusage_to_rusage50(&ru, &ru50);
1.174     dsl       262:                error = copyout(&ru, SCARG(uap, rusage), sizeof(ru));
1.204     njoly     263:        }
1.174     dsl       264:
                    265:        if (error == 0 && SCARG(uap, status) != NULL) {
1.173     dsl       266:                status = bsd_to_linux_wstat(status);
1.174     dsl       267:                error = copyout(&status, SCARG(uap, status), sizeof status);
1.16      fvdl      268:        }
1.1       fvdl      269:
1.174     dsl       270:        return error;
1.1       fvdl      271: }
                    272:
                    273: /*
1.216     chs       274:  * Linux brk(2).  Like native, but always return the new break value.
1.1       fvdl      275:  */
                    276: int
1.190     dsl       277: linux_sys_brk(struct lwp *l, const struct linux_sys_brk_args *uap, register_t *retval)
1.20      thorpej   278: {
1.190     dsl       279:        /* {
1.1       fvdl      280:                syscallarg(char *) nsize;
1.190     dsl       281:        } */
1.116     thorpej   282:        struct proc *p = l->l_proc;
1.216     chs       283:        struct vmspace *vm = p->p_vmspace;
1.21      mycroft   284:        struct sys_obreak_args oba;
1.1       fvdl      285:
1.216     chs       286:        SCARG(&oba, nsize) = SCARG(uap, nsize);
1.1       fvdl      287:
1.216     chs       288:        (void) sys_obreak(l, &oba, retval);
                    289:        retval[0] = (register_t)((char *)vm->vm_daddr + ptoa(vm->vm_dsize));
1.1       fvdl      290:        return 0;
                    291: }
                    292:
                    293: /*
1.2       fvdl      294:  * Implement the fs stat functions. Straightforward.
1.1       fvdl      295:  */
                    296: int
1.190     dsl       297: linux_sys_statfs(struct lwp *l, const struct linux_sys_statfs_args *uap, register_t *retval)
1.20      thorpej   298: {
1.190     dsl       299:        /* {
1.53      christos  300:                syscallarg(const char *) path;
1.1       fvdl      301:                syscallarg(struct linux_statfs *) sp;
1.190     dsl       302:        } */
1.172     dsl       303:        struct statvfs *sb;
1.2       fvdl      304:        struct linux_statfs ltmp;
                    305:        int error;
                    306:
1.172     dsl       307:        sb = STATVFSBUF_GET();
                    308:        error = do_sys_pstatvfs(l, SCARG(uap, path), ST_WAIT, sb);
                    309:        if (error == 0) {
                    310:                bsd_to_linux_statfs(sb, &ltmp);
                    311:                error = copyout(&ltmp, SCARG(uap, sp), sizeof ltmp);
                    312:        }
                    313:        STATVFSBUF_PUT(sb);
1.2       fvdl      314:
1.153     yamt      315:        return error;
1.1       fvdl      316: }
                    317:
                    318: int
1.190     dsl       319: linux_sys_fstatfs(struct lwp *l, const struct linux_sys_fstatfs_args *uap, register_t *retval)
1.20      thorpej   320: {
1.190     dsl       321:        /* {
1.2       fvdl      322:                syscallarg(int) fd;
1.1       fvdl      323:                syscallarg(struct linux_statfs *) sp;
1.190     dsl       324:        } */
1.172     dsl       325:        struct statvfs *sb;
1.2       fvdl      326:        struct linux_statfs ltmp;
                    327:        int error;
                    328:
1.172     dsl       329:        sb = STATVFSBUF_GET();
                    330:        error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
                    331:        if (error == 0) {
                    332:                bsd_to_linux_statfs(sb, &ltmp);
                    333:                error = copyout(&ltmp, SCARG(uap, sp), sizeof ltmp);
                    334:        }
                    335:        STATVFSBUF_PUT(sb);
1.2       fvdl      336:
1.153     yamt      337:        return error;
1.1       fvdl      338: }
1.82      fvdl      339:
1.1       fvdl      340: /*
                    341:  * uname(). Just copy the info from the various strings stored in the
                    342:  * kernel, and put it in the Linux utsname structure. That structure
                    343:  * is almost the same as the NetBSD one, only it has fields 65 characters
                    344:  * long, and an extra domainname field.
                    345:  */
                    346: int
1.190     dsl       347: linux_sys_uname(struct lwp *l, const struct linux_sys_uname_args *uap, register_t *retval)
1.20      thorpej   348: {
1.190     dsl       349:        /* {
1.1       fvdl      350:                syscallarg(struct linux_utsname *) up;
1.190     dsl       351:        } */
1.15      mycroft   352:        struct linux_utsname luts;
1.1       fvdl      353:
1.186     njoly     354:        strlcpy(luts.l_sysname, linux_sysname, sizeof(luts.l_sysname));
                    355:        strlcpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
                    356:        strlcpy(luts.l_release, linux_release, sizeof(luts.l_release));
                    357:        strlcpy(luts.l_version, linux_version, sizeof(luts.l_version));
                    358:        strlcpy(luts.l_machine, LINUX_UNAME_ARCH, sizeof(luts.l_machine));
                    359:        strlcpy(luts.l_domainname, domainname, sizeof(luts.l_domainname));
1.15      mycroft   360:
                    361:        return copyout(&luts, SCARG(uap, up), sizeof(luts));
                    362: }
                    363:
1.47      erh       364: /* Used directly on: alpha, mips, ppc, sparc, sparc64 */
                    365: /* Used indirectly on: arm, i386, m68k */
1.1       fvdl      366:
                    367: /*
1.47      erh       368:  * New type Linux mmap call.
                    369:  * Only called directly on machines with >= 6 free regs.
1.1       fvdl      370:  */
                    371: int
1.190     dsl       372: linux_sys_mmap(struct lwp *l, const struct linux_sys_mmap_args *uap, register_t *retval)
1.20      thorpej   373: {
1.190     dsl       374:        /* {
1.47      erh       375:                syscallarg(unsigned long) addr;
                    376:                syscallarg(size_t) len;
                    377:                syscallarg(int) prot;
                    378:                syscallarg(int) flags;
                    379:                syscallarg(int) fd;
1.94      manu      380:                syscallarg(linux_off_t) offset;
1.190     dsl       381:        } */
1.118     christos  382:
1.115     christos  383:        if (SCARG(uap, offset) & PAGE_MASK)
                    384:                return EINVAL;
                    385:
1.128     jdolecek  386:        return linux_mmap(l, uap, retval, SCARG(uap, offset));
1.118     christos  387: }
                    388:
                    389: /*
                    390:  * Guts of most architectures' mmap64() implementations.  This shares
                    391:  * its list of arguments with linux_sys_mmap().
                    392:  *
                    393:  * The difference in linux_sys_mmap2() is that "offset" is actually
                    394:  * (offset / pagesize), not an absolute byte count.  This translation
                    395:  * to pagesize offsets is done inside glibc between the mmap64() call
                    396:  * point, and the actual syscall.
                    397:  */
                    398: int
1.190     dsl       399: linux_sys_mmap2(struct lwp *l, const struct linux_sys_mmap2_args *uap, register_t *retval)
1.118     christos  400: {
1.190     dsl       401:        /* {
1.118     christos  402:                syscallarg(unsigned long) addr;
                    403:                syscallarg(size_t) len;
                    404:                syscallarg(int) prot;
                    405:                syscallarg(int) flags;
                    406:                syscallarg(int) fd;
                    407:                syscallarg(linux_off_t) offset;
1.190     dsl       408:        } */
1.128     jdolecek  409:
                    410:        return linux_mmap(l, uap, retval,
                    411:            ((off_t)SCARG(uap, offset)) << PAGE_SHIFT);
                    412: }
                    413:
                    414: /*
                    415:  * Massage arguments and call system mmap(2).
                    416:  */
                    417: static int
1.190     dsl       418: linux_mmap(struct lwp *l, const struct linux_sys_mmap_args *uap, register_t *retval, off_t offset)
1.128     jdolecek  419: {
1.118     christos  420:        struct sys_mmap_args cma;
1.128     jdolecek  421:        int error;
                    422:        size_t mmoff=0;
                    423:
1.190     dsl       424:        linux_to_bsd_mmap_args(&cma, uap);
                    425:        SCARG(&cma, pos) = offset;
                    426:
1.128     jdolecek  427:        if (SCARG(uap, flags) & LINUX_MAP_GROWSDOWN) {
                    428:                /*
                    429:                 * Request for stack-like memory segment. On linux, this
                    430:                 * works by mmap()ping (small) segment, which is automatically
                    431:                 * extended when page fault happens below the currently
                    432:                 * allocated area. We emulate this by allocating (typically
                    433:                 * bigger) segment sized at current stack size limit, and
                    434:                 * offsetting the requested and returned address accordingly.
                    435:                 * Since physical pages are only allocated on-demand, this
                    436:                 * is effectively identical.
                    437:                 */
                    438:                rlim_t ssl = l->l_proc->p_rlimit[RLIMIT_STACK].rlim_cur;
                    439:
1.190     dsl       440:                if (SCARG(&cma, len) < ssl) {
1.128     jdolecek  441:                        /* Compute the address offset */
                    442:                        mmoff = round_page(ssl) - SCARG(uap, len);
                    443:
1.190     dsl       444:                        if (SCARG(&cma, addr))
                    445:                                SCARG(&cma, addr) = (char *)SCARG(&cma, addr) - mmoff;
1.128     jdolecek  446:
1.190     dsl       447:                        SCARG(&cma, len) = (size_t) ssl;
1.128     jdolecek  448:                }
                    449:        }
1.118     christos  450:
1.128     jdolecek  451:        error = sys_mmap(l, &cma, retval);
                    452:        if (error)
                    453:                return (error);
                    454:
                    455:        /* Shift the returned address for stack-like segment if necessary */
1.190     dsl       456:        retval[0] += mmoff;
1.118     christos  457:
1.128     jdolecek  458:        return (0);
1.118     christos  459: }
                    460:
                    461: static void
1.189     dsl       462: linux_to_bsd_mmap_args(struct sys_mmap_args *cma, const struct linux_sys_mmap_args *uap)
1.118     christos  463: {
1.119     christos  464:        int flags = MAP_TRYFIXED, fl = SCARG(uap, flags);
1.135     perry     465:
1.103     christos  466:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_SHARED, MAP_SHARED);
                    467:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_PRIVATE, MAP_PRIVATE);
                    468:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_FIXED, MAP_FIXED);
                    469:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_ANON, MAP_ANON);
1.231     njoly     470:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_LOCKED, MAP_WIRED);
1.47      erh       471:        /* XXX XAX ERH: Any other flags here?  There are more defined... */
                    472:
1.118     christos  473:        SCARG(cma, addr) = (void *)SCARG(uap, addr);
                    474:        SCARG(cma, len) = SCARG(uap, len);
                    475:        SCARG(cma, prot) = SCARG(uap, prot);
                    476:        if (SCARG(cma, prot) & VM_PROT_WRITE) /* XXX */
                    477:                SCARG(cma, prot) |= VM_PROT_READ;
                    478:        SCARG(cma, flags) = flags;
                    479:        SCARG(cma, fd) = flags & MAP_ANON ? -1 : SCARG(uap, fd);
1.208     pooka     480:        SCARG(cma, PAD) = 0;
1.97      christos  481: }
                    482:
1.148     yamt      483: #define        LINUX_MREMAP_MAYMOVE    1
                    484: #define        LINUX_MREMAP_FIXED      2
                    485:
1.34      mycroft   486: int
1.190     dsl       487: linux_sys_mremap(struct lwp *l, const struct linux_sys_mremap_args *uap, register_t *retval)
1.34      mycroft   488: {
1.190     dsl       489:        /* {
1.34      mycroft   490:                syscallarg(void *) old_address;
                    491:                syscallarg(size_t) old_size;
                    492:                syscallarg(size_t) new_size;
                    493:                syscallarg(u_long) flags;
1.190     dsl       494:        } */
1.148     yamt      495:
                    496:        struct proc *p;
                    497:        struct vm_map *map;
                    498:        vaddr_t oldva;
                    499:        vaddr_t newva;
                    500:        size_t oldsize;
                    501:        size_t newsize;
                    502:        int flags;
                    503:        int uvmflags;
1.42      thorpej   504:        int error;
                    505:
1.148     yamt      506:        flags = SCARG(uap, flags);
                    507:        oldva = (vaddr_t)SCARG(uap, old_address);
                    508:        oldsize = round_page(SCARG(uap, old_size));
                    509:        newsize = round_page(SCARG(uap, new_size));
1.149     yamt      510:        if ((flags & ~(LINUX_MREMAP_FIXED|LINUX_MREMAP_MAYMOVE)) != 0) {
                    511:                error = EINVAL;
                    512:                goto done;
                    513:        }
1.148     yamt      514:        if ((flags & LINUX_MREMAP_FIXED) != 0) {
1.149     yamt      515:                if ((flags & LINUX_MREMAP_MAYMOVE) == 0) {
                    516:                        error = EINVAL;
                    517:                        goto done;
                    518:                }
1.148     yamt      519: #if 0 /* notyet */
                    520:                newva = SCARG(uap, new_address);
1.183     joerg     521:                uvmflags = MAP_FIXED;
1.148     yamt      522: #else /* notyet */
                    523:                error = EOPNOTSUPP;
                    524:                goto done;
                    525: #endif /* notyet */
                    526:        } else if ((flags & LINUX_MREMAP_MAYMOVE) != 0) {
                    527:                uvmflags = 0;
                    528:        } else {
                    529:                newva = oldva;
1.183     joerg     530:                uvmflags = MAP_FIXED;
1.42      thorpej   531:        }
1.148     yamt      532:        p = l->l_proc;
                    533:        map = &p->p_vmspace->vm_map;
                    534:        error = uvm_mremap(map, oldva, oldsize, map, &newva, newsize, p,
                    535:            uvmflags);
1.42      thorpej   536:
1.148     yamt      537: done:
                    538:        *retval = (error != 0) ? 0 : (register_t)newva;
                    539:        return error;
1.24      fvdl      540: }
                    541:
1.224     pooka     542: #ifdef USRSTACK
1.24      fvdl      543: int
1.190     dsl       544: linux_sys_mprotect(struct lwp *l, const struct linux_sys_mprotect_args *uap, register_t *retval)
1.103     christos  545: {
1.190     dsl       546:        /* {
1.103     christos  547:                syscallarg(const void *) start;
                    548:                syscallarg(unsigned long) len;
                    549:                syscallarg(int) prot;
1.190     dsl       550:        } */
1.103     christos  551:        struct vm_map_entry *entry;
1.141     chs       552:        struct vm_map *map;
                    553:        struct proc *p;
                    554:        vaddr_t end, start, len, stacklim;
                    555:        int prot, grows;
1.103     christos  556:
1.141     chs       557:        start = (vaddr_t)SCARG(uap, start);
1.103     christos  558:        len = round_page(SCARG(uap, len));
1.141     chs       559:        prot = SCARG(uap, prot);
                    560:        grows = prot & (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP);
                    561:        prot &= ~grows;
1.103     christos  562:        end = start + len;
                    563:
1.141     chs       564:        if (start & PAGE_MASK)
                    565:                return EINVAL;
1.103     christos  566:        if (end < start)
                    567:                return EINVAL;
1.141     chs       568:        if (end == start)
1.103     christos  569:                return 0;
                    570:
1.141     chs       571:        if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
                    572:                return EINVAL;
                    573:        if (grows == (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP))
1.103     christos  574:                return EINVAL;
                    575:
1.141     chs       576:        p = l->l_proc;
                    577:        map = &p->p_vmspace->vm_map;
1.103     christos  578:        vm_map_lock(map);
1.150     manu      579: # ifdef notdef
1.103     christos  580:        VM_MAP_RANGE_CHECK(map, start, end);
1.150     manu      581: # endif
1.103     christos  582:        if (!uvm_map_lookup_entry(map, start, &entry) || entry->start > start) {
                    583:                vm_map_unlock(map);
1.126     jdolecek  584:                return ENOMEM;
1.103     christos  585:        }
1.141     chs       586:
                    587:        /*
                    588:         * Approximate the behaviour of PROT_GROWS{DOWN,UP}.
                    589:         */
                    590:
                    591:        stacklim = (vaddr_t)p->p_limit->pl_rlimit[RLIMIT_STACK].rlim_cur;
                    592:        if (grows & LINUX_PROT_GROWSDOWN) {
                    593:                if (USRSTACK - stacklim <= start && start < USRSTACK) {
                    594:                        start = USRSTACK - stacklim;
                    595:                } else {
                    596:                        start = entry->start;
                    597:                }
                    598:        } else if (grows & LINUX_PROT_GROWSUP) {
                    599:                if (USRSTACK <= end && end < USRSTACK + stacklim) {
                    600:                        end = USRSTACK + stacklim;
                    601:                } else {
                    602:                        end = entry->end;
                    603:                }
                    604:        }
1.103     christos  605:        vm_map_unlock(map);
1.238     joerg     606:        return uvm_map_protect_user(l, start, end, prot);
1.1       fvdl      607: }
1.224     pooka     608: #endif /* USRSTACK */
1.1       fvdl      609:
                    610: /*
                    611:  * This code is partly stolen from src/lib/libc/compat-43/times.c
                    612:  */
                    613:
1.113     jdolecek  614: #define        CONVTCK(r)      (r.tv_sec * hz + r.tv_usec / (1000000 / hz))
1.1       fvdl      615:
                    616: int
1.190     dsl       617: linux_sys_times(struct lwp *l, const struct linux_sys_times_args *uap, register_t *retval)
1.20      thorpej   618: {
1.190     dsl       619:        /* {
1.1       fvdl      620:                syscallarg(struct times *) tms;
1.190     dsl       621:        } */
1.116     thorpej   622:        struct proc *p = l->l_proc;
1.1       fvdl      623:        struct timeval t;
1.155     kardel    624:        int error;
1.1       fvdl      625:
1.112     jdolecek  626:        if (SCARG(uap, tms)) {
                    627:                struct linux_tms ltms;
                    628:                struct rusage ru;
                    629:
1.197     ad        630:                mutex_enter(p->p_lock);
1.166     ad        631:                calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
1.112     jdolecek  632:                ltms.ltms_utime = CONVTCK(ru.ru_utime);
                    633:                ltms.ltms_stime = CONVTCK(ru.ru_stime);
                    634:                ltms.ltms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime);
                    635:                ltms.ltms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime);
1.197     ad        636:                mutex_exit(p->p_lock);
1.1       fvdl      637:
1.112     jdolecek  638:                if ((error = copyout(&ltms, SCARG(uap, tms), sizeof ltms)))
                    639:                        return error;
                    640:        }
1.1       fvdl      641:
1.155     kardel    642:        getmicrouptime(&t);
1.1       fvdl      643:
                    644:        retval[0] = ((linux_clock_t)(CONVTCK(t)));
                    645:        return 0;
                    646: }
1.113     jdolecek  647:
                    648: #undef CONVTCK
1.1       fvdl      649:
                    650: /*
                    651:  * Linux 'readdir' call. This code is mostly taken from the
                    652:  * SunOS getdents call (see compat/sunos/sunos_misc.c), though
                    653:  * an attempt has been made to keep it a little cleaner (failing
                    654:  * miserably, because of the cruft needed if count 1 is passed).
                    655:  *
1.17      fvdl      656:  * The d_off field should contain the offset of the next valid entry,
                    657:  * but in Linux it has the offset of the entry itself. We emulate
                    658:  * that bug here.
                    659:  *
1.1       fvdl      660:  * Read in BSD-style entries, convert them, and copy them out.
                    661:  *
                    662:  * Note that this doesn't handle union-mounted filesystems.
                    663:  */
                    664: int
1.190     dsl       665: linux_sys_getdents(struct lwp *l, const struct linux_sys_getdents_args *uap, register_t *retval)
1.20      thorpej   666: {
1.190     dsl       667:        /* {
1.1       fvdl      668:                syscallarg(int) fd;
1.47      erh       669:                syscallarg(struct linux_dirent *) dent;
1.1       fvdl      670:                syscallarg(unsigned int) count;
1.190     dsl       671:        } */
1.69      augustss  672:        struct dirent *bdp;
1.1       fvdl      673:        struct vnode *vp;
1.167     christos  674:        char *inp, *tbuf;               /* BSD-format */
1.26      christos  675:        int len, reclen;                /* BSD-format */
1.167     christos  676:        char *outp;                     /* Linux-format */
1.26      christos  677:        int resid, linux_reclen = 0;    /* Linux-format */
1.1       fvdl      678:        struct file *fp;
                    679:        struct uio auio;
                    680:        struct iovec aiov;
                    681:        struct linux_dirent idb;
                    682:        off_t off;              /* true file offset */
1.17      fvdl      683:        int buflen, error, eofflag, nbytes, oldcall;
1.1       fvdl      684:        struct vattr va;
1.40      fvdl      685:        off_t *cookiebuf = NULL, *cookie;
1.22      mycroft   686:        int ncookies;
1.1       fvdl      687:
1.201     ad        688:        /* fd_getvnode() will use the descriptor for us */
                    689:        if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
1.1       fvdl      690:                return (error);
                    691:
1.54      thorpej   692:        if ((fp->f_flag & FREAD) == 0) {
                    693:                error = EBADF;
                    694:                goto out1;
                    695:        }
1.1       fvdl      696:
1.5       mycroft   697:        vp = (struct vnode *)fp->f_data;
1.54      thorpej   698:        if (vp->v_type != VDIR) {
1.209     njoly     699:                error = ENOTDIR;
1.54      thorpej   700:                goto out1;
                    701:        }
1.1       fvdl      702:
1.219     hannken   703:        vn_lock(vp, LK_SHARED | LK_RETRY);
                    704:        error = VOP_GETATTR(vp, &va, l->l_cred);
                    705:        VOP_UNLOCK(vp);
                    706:        if (error)
1.54      thorpej   707:                goto out1;
1.1       fvdl      708:
                    709:        nbytes = SCARG(uap, count);
1.17      fvdl      710:        if (nbytes == 1) {      /* emulating old, broken behaviour */
1.107     christos  711:                nbytes = sizeof (idb);
1.239.4.1  christos  712:                buflen = uimax(va.va_blocksize, nbytes);
1.17      fvdl      713:                oldcall = 1;
1.5       mycroft   714:        } else {
1.239.4.1  christos  715:                buflen = uimin(MAXBSIZE, nbytes);
1.33      fvdl      716:                if (buflen < va.va_blocksize)
                    717:                        buflen = va.va_blocksize;
1.17      fvdl      718:                oldcall = 0;
1.1       fvdl      719:        }
1.138     christos  720:        tbuf = malloc(buflen, M_TEMP, M_WAITOK);
1.33      fvdl      721:
1.39      fvdl      722:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.1       fvdl      723:        off = fp->f_offset;
                    724: again:
1.138     christos  725:        aiov.iov_base = tbuf;
1.1       fvdl      726:        aiov.iov_len = buflen;
                    727:        auio.uio_iov = &aiov;
                    728:        auio.uio_iovcnt = 1;
                    729:        auio.uio_rw = UIO_READ;
                    730:        auio.uio_resid = buflen;
                    731:        auio.uio_offset = off;
1.151     yamt      732:        UIO_SETUP_SYSSPACE(&auio);
1.1       fvdl      733:        /*
                    734:          * First we read into the malloc'ed buffer, then
                    735:          * we massage it into user space, one record at a time.
                    736:          */
1.39      fvdl      737:        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
                    738:            &ncookies);
1.1       fvdl      739:        if (error)
                    740:                goto out;
                    741:
1.138     christos  742:        inp = tbuf;
1.167     christos  743:        outp = (void *)SCARG(uap, dent);
1.1       fvdl      744:        resid = nbytes;
1.35      fvdl      745:        if ((len = buflen - auio.uio_resid) == 0)
1.1       fvdl      746:                goto eof;
                    747:
1.22      mycroft   748:        for (cookie = cookiebuf; len > 0; len -= reclen) {
1.5       mycroft   749:                bdp = (struct dirent *)inp;
                    750:                reclen = bdp->d_reclen;
1.239     riastrad  751:                if (reclen & 3) {
                    752:                        error = EIO;
                    753:                        goto out;
                    754:                }
1.1       fvdl      755:                if (bdp->d_fileno == 0) {
                    756:                        inp += reclen;  /* it is a hole; squish it out */
1.136     christos  757:                        if (cookie)
                    758:                                off = *cookie++;
                    759:                        else
                    760:                                off += reclen;
1.1       fvdl      761:                        continue;
                    762:                }
1.21      mycroft   763:                linux_reclen = LINUX_RECLEN(&idb, bdp->d_namlen);
                    764:                if (reclen > len || resid < linux_reclen) {
1.1       fvdl      765:                        /* entry too big for buffer, so just stop */
                    766:                        outp++;
                    767:                        break;
                    768:                }
                    769:                /*
                    770:                 * Massage in place to make a Linux-shaped dirent (otherwise
                    771:                 * we have to worry about touching user memory outside of
                    772:                 * the copyout() call).
                    773:                 */
1.107     christos  774:                idb.d_ino = bdp->d_fileno;
1.17      fvdl      775:                /*
1.21      mycroft   776:                 * The old readdir() call misuses the offset and reclen fields.
1.17      fvdl      777:                 */
1.22      mycroft   778:                if (oldcall) {
                    779:                        idb.d_off = (linux_off_t)linux_reclen;
                    780:                        idb.d_reclen = (u_short)bdp->d_namlen;
                    781:                } else {
1.109     tron      782:                        if (sizeof (idb.d_off) <= 4 && (off >> 32) != 0) {
1.33      fvdl      783:                                compat_offseterr(vp, "linux_getdents");
                    784:                                error = EINVAL;
                    785:                                goto out;
                    786:                        }
1.22      mycroft   787:                        idb.d_off = (linux_off_t)off;
1.107     christos  788:                        idb.d_reclen = (u_short)linux_reclen;
1.227     slp       789:                        /* Linux puts d_type at the end of each record */
                    790:                        *((char *)&idb + idb.d_reclen - 1) = bdp->d_type;
1.107     christos  791:                }
1.235     christos  792:                memcpy(idb.d_name, bdp->d_name,
1.237     christos  793:                    MIN(sizeof(idb.d_name), bdp->d_namlen + 1));
1.167     christos  794:                if ((error = copyout((void *)&idb, outp, linux_reclen)))
1.107     christos  795:                        goto out;
                    796:                /* advance past this real entry */
                    797:                inp += reclen;
1.136     christos  798:                if (cookie)
                    799:                        off = *cookie++; /* each entry points to itself */
                    800:                else
                    801:                        off += reclen;
1.107     christos  802:                /* advance output past Linux-shaped entry */
                    803:                outp += linux_reclen;
                    804:                resid -= linux_reclen;
                    805:                if (oldcall)
                    806:                        break;
                    807:        }
                    808:
                    809:        /* if we squished out the whole block, try again */
1.214     he        810:        if (outp == (void *)SCARG(uap, dent)) {
                    811:                if (cookiebuf)
                    812:                        free(cookiebuf, M_TEMP);
                    813:                cookiebuf = NULL;
1.107     christos  814:                goto again;
1.214     he        815:        }
1.107     christos  816:        fp->f_offset = off;     /* update the vnode offset */
                    817:
                    818:        if (oldcall)
                    819:                nbytes = resid + linux_reclen;
                    820:
                    821: eof:
                    822:        *retval = nbytes - resid;
                    823: out:
1.215     hannken   824:        VOP_UNLOCK(vp);
1.107     christos  825:        if (cookiebuf)
                    826:                free(cookiebuf, M_TEMP);
1.138     christos  827:        free(tbuf, M_TEMP);
1.107     christos  828: out1:
1.194     ad        829:        fd_putfile(SCARG(uap, fd));
1.1       fvdl      830:        return error;
                    831: }
                    832:
                    833: /*
1.17      fvdl      834:  * Even when just using registers to pass arguments to syscalls you can
                    835:  * have 5 of them on the i386. So this newer version of select() does
                    836:  * this.
1.1       fvdl      837:  */
                    838: int
1.190     dsl       839: linux_sys_select(struct lwp *l, const struct linux_sys_select_args *uap, register_t *retval)
1.20      thorpej   840: {
1.190     dsl       841:        /* {
1.17      fvdl      842:                syscallarg(int) nfds;
                    843:                syscallarg(fd_set *) readfds;
                    844:                syscallarg(fd_set *) writefds;
                    845:                syscallarg(fd_set *) exceptfds;
1.203     christos  846:                syscallarg(struct timeval50 *) timeout;
1.190     dsl       847:        } */
1.20      thorpej   848:
1.116     thorpej   849:        return linux_select1(l, retval, SCARG(uap, nfds), SCARG(uap, readfds),
1.203     christos  850:            SCARG(uap, writefds), SCARG(uap, exceptfds),
                    851:            (struct linux_timeval *)SCARG(uap, timeout));
1.17      fvdl      852: }
                    853:
                    854: /*
                    855:  * Common code for the old and new versions of select(). A couple of
                    856:  * things are important:
                    857:  * 1) return the amount of time left in the 'timeout' parameter
                    858:  * 2) select never returns ERESTART on Linux, always return EINTR
                    859:  */
                    860: int
1.211     rmind     861: linux_select1(struct lwp *l, register_t *retval, int nfds, fd_set *readfds,
                    862:     fd_set *writefds, fd_set *exceptfds, struct linux_timeval *timeout)
1.17      fvdl      863: {
1.207     christos  864:        struct timespec ts0, ts1, uts, *ts = NULL;
1.203     christos  865:        struct linux_timeval ltv;
1.1       fvdl      866:        int error;
                    867:
1.7       fvdl      868:        /*
                    869:         * Store current time for computation of the amount of
                    870:         * time left.
                    871:         */
1.17      fvdl      872:        if (timeout) {
1.203     christos  873:                if ((error = copyin(timeout, &ltv, sizeof(ltv))))
1.13      mycroft   874:                        return error;
1.207     christos  875:                uts.tv_sec = ltv.tv_sec;
                    876:                uts.tv_nsec = ltv.tv_usec * 1000;
                    877:                if (itimespecfix(&uts)) {
1.13      mycroft   878:                        /*
                    879:                         * The timeval was invalid.  Convert it to something
                    880:                         * valid that will act as it does under Linux.
                    881:                         */
1.207     christos  882:                        uts.tv_sec += uts.tv_nsec / 1000000000;
                    883:                        uts.tv_nsec %= 1000000000;
                    884:                        if (uts.tv_nsec < 0) {
                    885:                                uts.tv_sec -= 1;
                    886:                                uts.tv_nsec += 1000000000;
1.13      mycroft   887:                        }
1.207     christos  888:                        if (uts.tv_sec < 0)
                    889:                                timespecclear(&uts);
1.13      mycroft   890:                }
1.207     christos  891:                ts = &uts;
                    892:                nanotime(&ts0);
1.13      mycroft   893:        }
1.7       fvdl      894:
1.211     rmind     895:        error = selcommon(retval, nfds, readfds, writefds, exceptfds, ts, NULL);
1.177     dsl       896:
1.10      mycroft   897:        if (error) {
                    898:                /*
                    899:                 * See fs/select.c in the Linux kernel.  Without this,
                    900:                 * Maelstrom doesn't work.
                    901:                 */
                    902:                if (error == ERESTART)
                    903:                        error = EINTR;
1.7       fvdl      904:                return error;
1.10      mycroft   905:        }
1.7       fvdl      906:
1.17      fvdl      907:        if (timeout) {
1.14      mycroft   908:                if (*retval) {
1.7       fvdl      909:                        /*
1.13      mycroft   910:                         * Compute how much time was left of the timeout,
1.7       fvdl      911:                         * by subtracting the current time and the time
                    912:                         * before we started the call, and subtracting
                    913:                         * that result from the user-supplied value.
                    914:                         */
1.207     christos  915:                        nanotime(&ts1);
                    916:                        timespecsub(&ts1, &ts0, &ts1);
                    917:                        timespecsub(&uts, &ts1, &uts);
                    918:                        if (uts.tv_sec < 0)
                    919:                                timespecclear(&uts);
1.14      mycroft   920:                } else
1.207     christos  921:                        timespecclear(&uts);
                    922:                ltv.tv_sec = uts.tv_sec;
                    923:                ltv.tv_usec = uts.tv_nsec / 1000;
1.203     christos  924:                if ((error = copyout(&ltv, timeout, sizeof(ltv))))
1.7       fvdl      925:                        return error;
                    926:        }
1.13      mycroft   927:
1.7       fvdl      928:        return 0;
1.1       fvdl      929: }
                    930:
1.234     manu      931: /*
                    932:  * Derived from FreeBSD's sys/compat/linux/linux_misc.c:linux_pselect6()
                    933:  * which was contributed by Dmitry Chagin
                    934:  * https://svnweb.freebsd.org/base?view=revision&revision=283403
                    935:  */
                    936: int
                    937: linux_sys_pselect6(struct lwp *l,
                    938:        const struct linux_sys_pselect6_args *uap, register_t *retval)
                    939: {
                    940:        /* {
                    941:                syscallarg(int) nfds;
                    942:                syscallarg(fd_set *) readfds;
                    943:                syscallarg(fd_set *) writefds;
                    944:                syscallarg(fd_set *) exceptfds;
                    945:                syscallarg(struct timespec *) timeout;
                    946:                syscallarg(linux_sized_sigset_t *) ss;
                    947:        } */
                    948:        struct timespec uts, ts0, ts1, *tsp;
                    949:        linux_sized_sigset_t lsss;
                    950:        struct linux_timespec lts;
                    951:        linux_sigset_t lss;
                    952:        sigset_t *ssp;
                    953:        sigset_t ss;
                    954:        int error;
                    955:
                    956:        ssp = NULL;
                    957:        if (SCARG(uap, ss) != NULL) {
                    958:                if ((error = copyin(SCARG(uap, ss), &lsss, sizeof(lsss))) != 0)
                    959:                        return (error);
                    960:                if (lsss.ss_len != sizeof(lss))
                    961:                        return (EINVAL);
                    962:                if (lsss.ss != NULL) {
                    963:                        if ((error = copyin(lsss.ss, &lss, sizeof(lss))) != 0)
                    964:                                return (error);
                    965:                        linux_to_native_sigset(&ss, &lss);
                    966:                        ssp = &ss;
                    967:                }
                    968:        }
                    969:
                    970:        if (SCARG(uap, timeout) != NULL) {
                    971:                error = copyin(SCARG(uap, timeout), &lts, sizeof(lts));
                    972:                if (error != 0)
                    973:                        return (error);
                    974:                linux_to_native_timespec(&uts, &lts);
                    975:
                    976:                if (itimespecfix(&uts))
                    977:                        return (EINVAL);
                    978:
                    979:                nanotime(&ts0);
                    980:                tsp = &uts;
                    981:        } else {
                    982:                tsp = NULL;
                    983:        }
                    984:
                    985:        error = selcommon(retval, SCARG(uap, nfds), SCARG(uap, readfds),
                    986:            SCARG(uap, writefds), SCARG(uap, exceptfds), tsp, ssp);
                    987:
                    988:        if (error == 0 && tsp != NULL) {
                    989:                if (retval != 0) {
                    990:                        /*
                    991:                         * Compute how much time was left of the timeout,
                    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:                        nanotime(&ts1);
                    997:                        timespecsub(&ts1, &ts0, &ts1);
                    998:                        timespecsub(&uts, &ts1, &uts);
                    999:                        if (uts.tv_sec < 0)
                   1000:                                timespecclear(&uts);
                   1001:                } else {
                   1002:                        timespecclear(&uts);
                   1003:                }
                   1004:
                   1005:                native_to_linux_timespec(&lts, &uts);
                   1006:                error = copyout(&lts, SCARG(uap, timeout), sizeof(lts));
                   1007:        }
                   1008:
                   1009:        return (error);
                   1010: }
                   1011:
1.220     pooka    1012: int
                   1013: linux_sys_ppoll(struct lwp *l,
                   1014:        const struct linux_sys_ppoll_args *uap, register_t *retval)
                   1015: {
                   1016:        /* {
                   1017:                syscallarg(struct pollfd *) fds;
1.230     njoly    1018:                syscallarg(u_int) nfds;
1.220     pooka    1019:                syscallarg(struct linux_timespec *) timeout;
                   1020:                syscallarg(linux_sigset_t *) sigset;
                   1021:        } */
                   1022:        struct linux_timespec lts0, *lts;
                   1023:        struct timespec ts0, *ts = NULL;
                   1024:        linux_sigset_t lsigmask0, *lsigmask;
                   1025:        sigset_t sigmask0, *sigmask = NULL;
                   1026:        int error;
                   1027:
                   1028:        lts = SCARG(uap, timeout);
                   1029:        if (lts) {
                   1030:                if ((error = copyin(lts, &lts0, sizeof(lts0))) != 0)
                   1031:                        return error;
                   1032:                linux_to_native_timespec(&ts0, &lts0);
                   1033:                ts = &ts0;
                   1034:        }
                   1035:
                   1036:        lsigmask = SCARG(uap, sigset);
                   1037:        if (lsigmask) {
                   1038:                if ((error = copyin(lsigmask, &lsigmask0, sizeof(lsigmask0))))
                   1039:                        return error;
                   1040:                linux_to_native_sigset(&sigmask0, &lsigmask0);
                   1041:                sigmask = &sigmask0;
                   1042:        }
                   1043:
                   1044:        return pollcommon(retval, SCARG(uap, fds), SCARG(uap, nfds),
                   1045:            ts, sigmask);
                   1046: }
                   1047:
1.1       fvdl     1048: /*
1.6       fvdl     1049:  * Set the 'personality' (emulation mode) for the current process. Only
                   1050:  * accept the Linux personality here (0). This call is needed because
                   1051:  * the Linux ELF crt0 issues it in an ugly kludge to make sure that
                   1052:  * ELF binaries run in Linux mode, not SVR4 mode.
                   1053:  */
                   1054: int
1.190     dsl      1055: linux_sys_personality(struct lwp *l, const struct linux_sys_personality_args *uap, register_t *retval)
1.20      thorpej  1056: {
1.190     dsl      1057:        /* {
1.212     njoly    1058:                syscallarg(unsigned long) per;
1.190     dsl      1059:        } */
1.218     chs      1060:        struct linux_emuldata *led;
                   1061:        int per;
1.20      thorpej  1062:
1.218     chs      1063:        per = SCARG(uap, per);
                   1064:        led = l->l_emuldata;
                   1065:        if (per == LINUX_PER_QUERY) {
                   1066:                retval[0] = led->led_personality;
                   1067:                return 0;
                   1068:        }
                   1069:
                   1070:        switch (per & LINUX_PER_MASK) {
1.205     njoly    1071:        case LINUX_PER_LINUX:
1.218     chs      1072:        case LINUX_PER_LINUX32:
                   1073:                led->led_personality = per;
1.205     njoly    1074:                break;
1.218     chs      1075:
1.205     njoly    1076:        default:
1.6       fvdl     1077:                return EINVAL;
1.205     njoly    1078:        }
                   1079:
1.218     chs      1080:        retval[0] = per;
1.1       fvdl     1081:        return 0;
1.18      fvdl     1082: }
1.81      fvdl     1083:
1.63      abs      1084: /*
1.64      abs      1085:  * We have nonexistent fsuid equal to uid.
                   1086:  * If modification is requested, refuse.
1.63      abs      1087:  */
                   1088: int
1.190     dsl      1089: linux_sys_setfsuid(struct lwp *l, const struct linux_sys_setfsuid_args *uap, register_t *retval)
1.63      abs      1090: {
1.190     dsl      1091:         /* {
1.63      abs      1092:                 syscallarg(uid_t) uid;
1.190     dsl      1093:         } */
1.63      abs      1094:         uid_t uid;
                   1095:
                   1096:         uid = SCARG(uap, uid);
1.158     ad       1097:         if (kauth_cred_getuid(l->l_cred) != uid)
1.190     dsl      1098:                 return sys_nosys(l, uap, retval);
1.191     njoly    1099:
                   1100:         *retval = uid;
                   1101:         return 0;
1.63      abs      1102: }
                   1103:
                   1104: int
1.191     njoly    1105: linux_sys_setfsgid(struct lwp *l, const struct linux_sys_setfsgid_args *uap, register_t *retval)
1.63      abs      1106: {
1.191     njoly    1107:        /* {
                   1108:                syscallarg(gid_t) gid;
                   1109:        } */
                   1110:        gid_t gid;
                   1111:
                   1112:        gid = SCARG(uap, gid);
                   1113:        if (kauth_cred_getgid(l->l_cred) != gid)
                   1114:                return sys_nosys(l, uap, retval);
                   1115:
                   1116:        *retval = gid;
                   1117:        return 0;
1.27      fvdl     1118: }
                   1119:
                   1120: int
1.190     dsl      1121: linux_sys_setresuid(struct lwp *l, const struct linux_sys_setresuid_args *uap, register_t *retval)
1.57      thorpej  1122: {
1.190     dsl      1123:        /* {
1.57      thorpej  1124:                syscallarg(uid_t) ruid;
                   1125:                syscallarg(uid_t) euid;
                   1126:                syscallarg(uid_t) suid;
1.190     dsl      1127:        } */
1.57      thorpej  1128:
                   1129:        /*
                   1130:         * Note: These checks are a little different than the NetBSD
                   1131:         * setreuid(2) call performs.  This precisely follows the
                   1132:         * behavior of the Linux kernel.
                   1133:         */
                   1134:
1.117     dsl      1135:        return do_setresuid(l, SCARG(uap, ruid), SCARG(uap, euid),
                   1136:                            SCARG(uap, suid),
                   1137:                            ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S |
                   1138:                            ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
                   1139:                            ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S );
1.57      thorpej  1140: }
                   1141:
                   1142: int
1.190     dsl      1143: linux_sys_getresuid(struct lwp *l, const struct linux_sys_getresuid_args *uap, register_t *retval)
1.57      thorpej  1144: {
1.190     dsl      1145:        /* {
1.57      thorpej  1146:                syscallarg(uid_t *) ruid;
                   1147:                syscallarg(uid_t *) euid;
                   1148:                syscallarg(uid_t *) suid;
1.190     dsl      1149:        } */
1.158     ad       1150:        kauth_cred_t pc = l->l_cred;
1.57      thorpej  1151:        int error;
1.154     elad     1152:        uid_t uid;
1.57      thorpej  1153:
                   1154:        /*
                   1155:         * Linux copies these values out to userspace like so:
                   1156:         *
                   1157:         *      1. Copy out ruid.
                   1158:         *      2. If that succeeds, copy out euid.
                   1159:         *      3. If both of those succeed, copy out suid.
                   1160:         */
1.154     elad     1161:        uid = kauth_cred_getuid(pc);
                   1162:        if ((error = copyout(&uid, SCARG(uap, ruid), sizeof(uid_t))) != 0)
1.57      thorpej  1163:                return (error);
                   1164:
1.154     elad     1165:        uid = kauth_cred_geteuid(pc);
                   1166:        if ((error = copyout(&uid, SCARG(uap, euid), sizeof(uid_t))) != 0)
1.57      thorpej  1167:                return (error);
                   1168:
1.154     elad     1169:        uid = kauth_cred_getsvuid(pc);
                   1170:
                   1171:        return (copyout(&uid, SCARG(uap, suid), sizeof(uid_t)));
1.78      fvdl     1172: }
1.62      tron     1173:
                   1174: int
1.190     dsl      1175: linux_sys_ptrace(struct lwp *l, const struct linux_sys_ptrace_args *uap, register_t *retval)
1.62      tron     1176: {
1.190     dsl      1177:        /* {
1.88      manu     1178:                i386, m68k, powerpc: T=int
1.137     manu     1179:                alpha, amd64: T=long
1.66      erh      1180:                syscallarg(T) request;
                   1181:                syscallarg(T) pid;
                   1182:                syscallarg(T) addr;
                   1183:                syscallarg(T) data;
1.190     dsl      1184:        } */
1.73      jdolecek 1185:        const int *ptr;
                   1186:        int request;
1.89      manu     1187:        int error;
1.62      tron     1188:
                   1189:        ptr = linux_ptrace_request_map;
                   1190:        request = SCARG(uap, request);
                   1191:        while (*ptr != -1)
                   1192:                if (*ptr++ == request) {
                   1193:                        struct sys_ptrace_args pta;
                   1194:
                   1195:                        SCARG(&pta, req) = *ptr;
                   1196:                        SCARG(&pta, pid) = SCARG(uap, pid);
1.167     christos 1197:                        SCARG(&pta, addr) = (void *)SCARG(uap, addr);
1.62      tron     1198:                        SCARG(&pta, data) = SCARG(uap, data);
                   1199:
1.73      jdolecek 1200:                        /*
                   1201:                         * Linux ptrace(PTRACE_CONT, pid, 0, 0) means actually
1.90      jdolecek 1202:                         * to continue where the process left off previously.
1.202     ad       1203:                         * The same thing is achieved by addr == (void *) 1
1.90      jdolecek 1204:                         * on NetBSD, so rewrite 'addr' appropriately.
1.73      jdolecek 1205:                         */
                   1206:                        if (request == LINUX_PTRACE_CONT && SCARG(uap, addr)==0)
1.167     christos 1207:                                SCARG(&pta, addr) = (void *) 1;
1.135     perry    1208:
1.202     ad       1209:                        error = sysent[SYS_ptrace].sy_call(l, &pta, retval);
1.135     perry    1210:                        if (error)
1.92      manu     1211:                                return error;
                   1212:                        switch (request) {
                   1213:                        case LINUX_PTRACE_PEEKTEXT:
                   1214:                        case LINUX_PTRACE_PEEKDATA:
1.135     perry    1215:                                error = copyout (retval,
1.167     christos 1216:                                    (void *)SCARG(uap, data),
1.137     manu     1217:                                    sizeof *retval);
1.92      manu     1218:                                *retval = SCARG(uap, data);
                   1219:                                break;
1.135     perry    1220:                        default:
1.92      manu     1221:                                break;
                   1222:                        }
1.89      manu     1223:                        return error;
1.62      tron     1224:                }
                   1225:                else
                   1226:                        ptr++;
                   1227:
1.116     thorpej  1228:        return LINUX_SYS_PTRACE_ARCH(l, uap, retval);
1.1       fvdl     1229: }
1.67      erh      1230:
                   1231: int
1.190     dsl      1232: linux_sys_reboot(struct lwp *l, const struct linux_sys_reboot_args *uap, register_t *retval)
1.67      erh      1233: {
1.190     dsl      1234:        /* {
1.67      erh      1235:                syscallarg(int) magic1;
                   1236:                syscallarg(int) magic2;
                   1237:                syscallarg(int) cmd;
                   1238:                syscallarg(void *) arg;
1.190     dsl      1239:        } */
1.67      erh      1240:        struct sys_reboot_args /* {
                   1241:                syscallarg(int) opt;
                   1242:                syscallarg(char *) bootstr;
                   1243:        } */ sra;
                   1244:        int error;
                   1245:
1.164     elad     1246:        if ((error = kauth_authorize_system(l->l_cred,
                   1247:            KAUTH_SYSTEM_REBOOT, 0, NULL, NULL, NULL)) != 0)
1.67      erh      1248:                return(error);
                   1249:
                   1250:        if (SCARG(uap, magic1) != LINUX_REBOOT_MAGIC1)
                   1251:                return(EINVAL);
                   1252:        if (SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2 &&
                   1253:            SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2A &&
                   1254:            SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2B)
                   1255:                return(EINVAL);
                   1256:
1.200     gmcgarry 1257:        switch ((unsigned long)SCARG(uap, cmd)) {
1.67      erh      1258:        case LINUX_REBOOT_CMD_RESTART:
                   1259:                SCARG(&sra, opt) = RB_AUTOBOOT;
                   1260:                break;
                   1261:        case LINUX_REBOOT_CMD_HALT:
                   1262:                SCARG(&sra, opt) = RB_HALT;
                   1263:                break;
                   1264:        case LINUX_REBOOT_CMD_POWER_OFF:
                   1265:                SCARG(&sra, opt) = RB_HALT|RB_POWERDOWN;
                   1266:                break;
                   1267:        case LINUX_REBOOT_CMD_RESTART2:
                   1268:                /* Reboot with an argument. */
                   1269:                SCARG(&sra, opt) = RB_AUTOBOOT|RB_STRING;
                   1270:                SCARG(&sra, bootstr) = SCARG(uap, arg);
                   1271:                break;
                   1272:        case LINUX_REBOOT_CMD_CAD_ON:
                   1273:                return(EINVAL); /* We don't implement ctrl-alt-delete */
                   1274:        case LINUX_REBOOT_CMD_CAD_OFF:
                   1275:                return(0);
                   1276:        default:
                   1277:                return(EINVAL);
                   1278:        }
                   1279:
1.116     thorpej  1280:        return(sys_reboot(l, &sra, retval));
1.75      jdolecek 1281: }
                   1282:
                   1283: /*
                   1284:  * Copy of compat_12_sys_swapon().
                   1285:  */
                   1286: int
1.190     dsl      1287: linux_sys_swapon(struct lwp *l, const struct linux_sys_swapon_args *uap, register_t *retval)
1.75      jdolecek 1288: {
1.190     dsl      1289:        /* {
                   1290:                syscallarg(const char *) name;
                   1291:        } */
1.75      jdolecek 1292:        struct sys_swapctl_args ua;
                   1293:
                   1294:        SCARG(&ua, cmd) = SWAP_ON;
1.139     drochner 1295:        SCARG(&ua, arg) = (void *)__UNCONST(SCARG(uap, name));
1.75      jdolecek 1296:        SCARG(&ua, misc) = 0;   /* priority */
1.116     thorpej  1297:        return (sys_swapctl(l, &ua, retval));
1.76      jdolecek 1298: }
                   1299:
                   1300: /*
                   1301:  * Stop swapping to the file or block device specified by path.
                   1302:  */
                   1303: int
1.190     dsl      1304: linux_sys_swapoff(struct lwp *l, const struct linux_sys_swapoff_args *uap, register_t *retval)
1.76      jdolecek 1305: {
1.190     dsl      1306:        /* {
                   1307:                syscallarg(const char *) path;
                   1308:        } */
1.76      jdolecek 1309:        struct sys_swapctl_args ua;
                   1310:
                   1311:        SCARG(&ua, cmd) = SWAP_OFF;
1.138     christos 1312:        SCARG(&ua, arg) = __UNCONST(SCARG(uap, path)); /*XXXUNCONST*/
1.116     thorpej  1313:        return (sys_swapctl(l, &ua, retval));
1.75      jdolecek 1314: }
                   1315:
                   1316: /*
                   1317:  * Copy of compat_09_sys_setdomainname()
                   1318:  */
                   1319: /* ARGSUSED */
                   1320: int
1.190     dsl      1321: linux_sys_setdomainname(struct lwp *l, const struct linux_sys_setdomainname_args *uap, register_t *retval)
1.75      jdolecek 1322: {
1.190     dsl      1323:        /* {
1.75      jdolecek 1324:                syscallarg(char *) domainname;
                   1325:                syscallarg(int) len;
1.190     dsl      1326:        } */
1.122     atatat   1327:        int name[2];
1.75      jdolecek 1328:
1.122     atatat   1329:        name[0] = CTL_KERN;
                   1330:        name[1] = KERN_DOMAINNAME;
                   1331:        return (old_sysctl(&name[0], 2, 0, 0, SCARG(uap, domainname),
                   1332:                            SCARG(uap, len), l));
1.77      augustss 1333: }
                   1334:
                   1335: /*
                   1336:  * sysinfo()
                   1337:  */
                   1338: /* ARGSUSED */
                   1339: int
1.190     dsl      1340: linux_sys_sysinfo(struct lwp *l, const struct linux_sys_sysinfo_args *uap, register_t *retval)
1.77      augustss 1341: {
1.190     dsl      1342:        /* {
1.77      augustss 1343:                syscallarg(struct linux_sysinfo *) arg;
1.190     dsl      1344:        } */
1.77      augustss 1345:        struct linux_sysinfo si;
                   1346:        struct loadavg *la;
                   1347:
1.155     kardel   1348:        si.uptime = time_uptime;
1.77      augustss 1349:        la = &averunnable;
                   1350:        si.loads[0] = la->ldavg[0] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
                   1351:        si.loads[1] = la->ldavg[1] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
                   1352:        si.loads[2] = la->ldavg[2] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
1.162     manu     1353:        si.totalram = ctob((u_long)physmem);
1.239.4.2! martin   1354:        si.freeram = (u_long)uvm_availmem() * uvmexp.pagesize;
1.77      augustss 1355:        si.sharedram = 0;       /* XXX */
1.162     manu     1356:        si.bufferram = (u_long)uvmexp.filepages * uvmexp.pagesize;
                   1357:        si.totalswap = (u_long)uvmexp.swpages * uvmexp.pagesize;
                   1358:        si.freeswap =
                   1359:            (u_long)(uvmexp.swpages - uvmexp.swpginuse) * uvmexp.pagesize;
1.77      augustss 1360:        si.procs = nprocs;
                   1361:
                   1362:        /* The following are only present in newer Linux kernels. */
                   1363:        si.totalbig = 0;
                   1364:        si.freebig = 0;
                   1365:        si.mem_unit = 1;
                   1366:
                   1367:        return (copyout(&si, SCARG(uap, arg), sizeof si));
1.97      christos 1368: }
                   1369:
                   1370: int
1.190     dsl      1371: linux_sys_getrlimit(struct lwp *l, const struct linux_sys_getrlimit_args *uap, register_t *retval)
1.97      christos 1372: {
1.190     dsl      1373:        /* {
1.97      christos 1374:                syscallarg(int) which;
1.150     manu     1375: # ifdef LINUX_LARGEFILE64
1.144     manu     1376:                syscallarg(struct rlimit *) rlp;
1.150     manu     1377: # else
1.97      christos 1378:                syscallarg(struct orlimit *) rlp;
1.150     manu     1379: # endif
1.190     dsl      1380:        } */
1.150     manu     1381: # ifdef LINUX_LARGEFILE64
1.144     manu     1382:        struct rlimit orl;
1.150     manu     1383: # else
1.97      christos 1384:        struct orlimit orl;
1.150     manu     1385: # endif
1.176     dsl      1386:        int which;
                   1387:
                   1388:        which = linux_to_bsd_limit(SCARG(uap, which));
                   1389:        if (which < 0)
                   1390:                return -which;
1.97      christos 1391:
1.176     dsl      1392:        bsd_to_linux_rlimit(&orl, &l->l_proc->p_rlimit[which]);
1.146     rpaulo   1393:
1.97      christos 1394:        return copyout(&orl, SCARG(uap, rlp), sizeof(orl));
                   1395: }
                   1396:
                   1397: int
1.190     dsl      1398: linux_sys_setrlimit(struct lwp *l, const struct linux_sys_setrlimit_args *uap, register_t *retval)
1.97      christos 1399: {
1.190     dsl      1400:        /* {
1.97      christos 1401:                syscallarg(int) which;
1.150     manu     1402: # ifdef LINUX_LARGEFILE64
1.144     manu     1403:                syscallarg(struct rlimit *) rlp;
1.150     manu     1404: # else
1.97      christos 1405:                syscallarg(struct orlimit *) rlp;
1.150     manu     1406: # endif
1.190     dsl      1407:        } */
1.97      christos 1408:        struct rlimit rl;
1.150     manu     1409: # ifdef LINUX_LARGEFILE64
1.144     manu     1410:        struct rlimit orl;
1.150     manu     1411: # else
1.97      christos 1412:        struct orlimit orl;
1.150     manu     1413: # endif
1.97      christos 1414:        int error;
1.176     dsl      1415:        int which;
1.97      christos 1416:
                   1417:        if ((error = copyin(SCARG(uap, rlp), &orl, sizeof(orl))) != 0)
                   1418:                return error;
1.176     dsl      1419:
                   1420:        which = linux_to_bsd_limit(SCARG(uap, which));
                   1421:        if (which < 0)
                   1422:                return -which;
                   1423:
1.97      christos 1424:        linux_to_bsd_rlimit(&rl, &orl);
1.176     dsl      1425:        return dosetrlimit(l, l->l_proc, which, &rl);
1.97      christos 1426: }
                   1427:
1.150     manu     1428: # if !defined(__mips__) && !defined(__amd64__)
1.98      rafal    1429: /* XXX: this doesn't look 100% common, at least mips doesn't have it */
1.97      christos 1430: int
1.190     dsl      1431: linux_sys_ugetrlimit(struct lwp *l, const struct linux_sys_ugetrlimit_args *uap, register_t *retval)
1.97      christos 1432: {
1.190     dsl      1433:        return linux_sys_getrlimit(l, (const void *)uap, retval);
1.87      jdolecek 1434: }
1.150     manu     1435: # endif
1.87      jdolecek 1436:
                   1437: /*
                   1438:  * This gets called for unsupported syscalls. The difference to sys_nosys()
                   1439:  * is that process does not get SIGSYS, the call just returns with ENOSYS.
                   1440:  * This is the way Linux does it and glibc depends on this behaviour.
                   1441:  */
                   1442: int
1.190     dsl      1443: linux_sys_nosys(struct lwp *l, const void *v, register_t *retval)
1.87      jdolecek 1444: {
                   1445:        return (ENOSYS);
1.67      erh      1446: }
1.150     manu     1447:
1.156     christos 1448: int
1.190     dsl      1449: linux_sys_getpriority(struct lwp *l, const struct linux_sys_getpriority_args *uap, register_t *retval)
1.156     christos 1450: {
1.190     dsl      1451:         /* {
1.156     christos 1452:                 syscallarg(int) which;
                   1453:                 syscallarg(int) who;
1.190     dsl      1454:         } */
1.156     christos 1455:         struct sys_getpriority_args bsa;
                   1456:         int error;
                   1457:
                   1458:         SCARG(&bsa, which) = SCARG(uap, which);
                   1459:         SCARG(&bsa, who) = SCARG(uap, who);
                   1460:
                   1461:         if ((error = sys_getpriority(l, &bsa, retval)))
                   1462:                 return error;
                   1463:
1.157     christos 1464:         *retval = NZERO - *retval;
1.156     christos 1465:
                   1466:         return 0;
                   1467: }
1.221     pooka    1468:
                   1469: int
1.228     chs      1470: linux_do_sys_utimensat(struct lwp *l, int fd, const char *path, struct timespec *tsp, int flags, register_t *retval)
1.226     njoly    1471: {
                   1472:        int follow, error;
                   1473:
1.228     chs      1474:        follow = (flags & LINUX_AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
1.226     njoly    1475:
1.228     chs      1476:        if (path == NULL && fd != AT_FDCWD) {
1.226     njoly    1477:                file_t *fp;
                   1478:
                   1479:                /* fd_getvnode() will use the descriptor for us */
1.228     chs      1480:                if ((error = fd_getvnode(fd, &fp)) != 0)
1.226     njoly    1481:                        return error;
                   1482:                error = do_sys_utimensat(l, AT_FDCWD, fp->f_data, NULL, 0,
                   1483:                    tsp, UIO_SYSSPACE);
1.228     chs      1484:                fd_putfile(fd);
1.226     njoly    1485:                return error;
                   1486:        }
                   1487:
1.228     chs      1488:        return do_sys_utimensat(l, fd, NULL, path, follow, tsp, UIO_SYSSPACE);
1.226     njoly    1489: }
                   1490:
1.221     pooka    1491: int
1.228     chs      1492: linux_sys_utimensat(struct lwp *l, const struct linux_sys_utimensat_args *uap,
                   1493:        register_t *retval)
1.221     pooka    1494: {
                   1495:        /* {
1.228     chs      1496:                syscallarg(int) fd;
1.221     pooka    1497:                syscallarg(const char *) path;
1.228     chs      1498:                syscallarg(const struct linux_timespec *) times;
                   1499:                syscallarg(int) flag;
1.221     pooka    1500:        } */
                   1501:        int error;
1.228     chs      1502:        struct linux_timespec lts[2];
                   1503:        struct timespec *tsp = NULL, ts[2];
1.221     pooka    1504:
                   1505:        if (SCARG(uap, times)) {
1.228     chs      1506:                error = copyin(SCARG(uap, times), &lts, sizeof(lts));
                   1507:                if (error != 0)
1.221     pooka    1508:                        return error;
1.228     chs      1509:                linux_to_native_timespec(&ts[0], &lts[0]);
                   1510:                linux_to_native_timespec(&ts[1], &lts[1]);
                   1511:                tsp = ts;
1.221     pooka    1512:        }
                   1513:
1.228     chs      1514:        return linux_do_sys_utimensat(l, SCARG(uap, fd), SCARG(uap, path),
                   1515:            tsp, SCARG(uap, flag), retval);
1.221     pooka    1516: }

CVSweb <webmaster@jp.NetBSD.org>