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

1.237.4.1! pgoyette    1: /*     $NetBSD: linux_misc.c,v 1.238 2017/05/06 21:34:51 joerg Exp $   */
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.237.4.1! pgoyette   60: __KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.238 2017/05/06 21:34:51 joerg Exp $");
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.237.4.1! pgoyette  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.5       mycroft   712:                buflen = max(va.va_blocksize, nbytes);
1.17      fvdl      713:                oldcall = 1;
1.5       mycroft   714:        } else {
                    715:                buflen = min(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.1       fvdl      751:                if (reclen & 3)
                    752:                        panic("linux_readdir");
                    753:                if (bdp->d_fileno == 0) {
                    754:                        inp += reclen;  /* it is a hole; squish it out */
1.136     christos  755:                        if (cookie)
                    756:                                off = *cookie++;
                    757:                        else
                    758:                                off += reclen;
1.1       fvdl      759:                        continue;
                    760:                }
1.21      mycroft   761:                linux_reclen = LINUX_RECLEN(&idb, bdp->d_namlen);
                    762:                if (reclen > len || resid < linux_reclen) {
1.1       fvdl      763:                        /* entry too big for buffer, so just stop */
                    764:                        outp++;
                    765:                        break;
                    766:                }
                    767:                /*
                    768:                 * Massage in place to make a Linux-shaped dirent (otherwise
                    769:                 * we have to worry about touching user memory outside of
                    770:                 * the copyout() call).
                    771:                 */
1.107     christos  772:                idb.d_ino = bdp->d_fileno;
1.17      fvdl      773:                /*
1.21      mycroft   774:                 * The old readdir() call misuses the offset and reclen fields.
1.17      fvdl      775:                 */
1.22      mycroft   776:                if (oldcall) {
                    777:                        idb.d_off = (linux_off_t)linux_reclen;
                    778:                        idb.d_reclen = (u_short)bdp->d_namlen;
                    779:                } else {
1.109     tron      780:                        if (sizeof (idb.d_off) <= 4 && (off >> 32) != 0) {
1.33      fvdl      781:                                compat_offseterr(vp, "linux_getdents");
                    782:                                error = EINVAL;
                    783:                                goto out;
                    784:                        }
1.22      mycroft   785:                        idb.d_off = (linux_off_t)off;
1.107     christos  786:                        idb.d_reclen = (u_short)linux_reclen;
1.227     slp       787:                        /* Linux puts d_type at the end of each record */
                    788:                        *((char *)&idb + idb.d_reclen - 1) = bdp->d_type;
1.107     christos  789:                }
1.235     christos  790:                memcpy(idb.d_name, bdp->d_name,
1.237     christos  791:                    MIN(sizeof(idb.d_name), bdp->d_namlen + 1));
1.167     christos  792:                if ((error = copyout((void *)&idb, outp, linux_reclen)))
1.107     christos  793:                        goto out;
                    794:                /* advance past this real entry */
                    795:                inp += reclen;
1.136     christos  796:                if (cookie)
                    797:                        off = *cookie++; /* each entry points to itself */
                    798:                else
                    799:                        off += reclen;
1.107     christos  800:                /* advance output past Linux-shaped entry */
                    801:                outp += linux_reclen;
                    802:                resid -= linux_reclen;
                    803:                if (oldcall)
                    804:                        break;
                    805:        }
                    806:
                    807:        /* if we squished out the whole block, try again */
1.214     he        808:        if (outp == (void *)SCARG(uap, dent)) {
                    809:                if (cookiebuf)
                    810:                        free(cookiebuf, M_TEMP);
                    811:                cookiebuf = NULL;
1.107     christos  812:                goto again;
1.214     he        813:        }
1.107     christos  814:        fp->f_offset = off;     /* update the vnode offset */
                    815:
                    816:        if (oldcall)
                    817:                nbytes = resid + linux_reclen;
                    818:
                    819: eof:
                    820:        *retval = nbytes - resid;
                    821: out:
1.215     hannken   822:        VOP_UNLOCK(vp);
1.107     christos  823:        if (cookiebuf)
                    824:                free(cookiebuf, M_TEMP);
1.138     christos  825:        free(tbuf, M_TEMP);
1.107     christos  826: out1:
1.194     ad        827:        fd_putfile(SCARG(uap, fd));
1.1       fvdl      828:        return error;
                    829: }
                    830:
                    831: /*
1.17      fvdl      832:  * Even when just using registers to pass arguments to syscalls you can
                    833:  * have 5 of them on the i386. So this newer version of select() does
                    834:  * this.
1.1       fvdl      835:  */
                    836: int
1.190     dsl       837: linux_sys_select(struct lwp *l, const struct linux_sys_select_args *uap, register_t *retval)
1.20      thorpej   838: {
1.190     dsl       839:        /* {
1.17      fvdl      840:                syscallarg(int) nfds;
                    841:                syscallarg(fd_set *) readfds;
                    842:                syscallarg(fd_set *) writefds;
                    843:                syscallarg(fd_set *) exceptfds;
1.203     christos  844:                syscallarg(struct timeval50 *) timeout;
1.190     dsl       845:        } */
1.20      thorpej   846:
1.116     thorpej   847:        return linux_select1(l, retval, SCARG(uap, nfds), SCARG(uap, readfds),
1.203     christos  848:            SCARG(uap, writefds), SCARG(uap, exceptfds),
                    849:            (struct linux_timeval *)SCARG(uap, timeout));
1.17      fvdl      850: }
                    851:
                    852: /*
                    853:  * Common code for the old and new versions of select(). A couple of
                    854:  * things are important:
                    855:  * 1) return the amount of time left in the 'timeout' parameter
                    856:  * 2) select never returns ERESTART on Linux, always return EINTR
                    857:  */
                    858: int
1.211     rmind     859: linux_select1(struct lwp *l, register_t *retval, int nfds, fd_set *readfds,
                    860:     fd_set *writefds, fd_set *exceptfds, struct linux_timeval *timeout)
1.17      fvdl      861: {
1.207     christos  862:        struct timespec ts0, ts1, uts, *ts = NULL;
1.203     christos  863:        struct linux_timeval ltv;
1.1       fvdl      864:        int error;
                    865:
1.7       fvdl      866:        /*
                    867:         * Store current time for computation of the amount of
                    868:         * time left.
                    869:         */
1.17      fvdl      870:        if (timeout) {
1.203     christos  871:                if ((error = copyin(timeout, &ltv, sizeof(ltv))))
1.13      mycroft   872:                        return error;
1.207     christos  873:                uts.tv_sec = ltv.tv_sec;
                    874:                uts.tv_nsec = ltv.tv_usec * 1000;
                    875:                if (itimespecfix(&uts)) {
1.13      mycroft   876:                        /*
                    877:                         * The timeval was invalid.  Convert it to something
                    878:                         * valid that will act as it does under Linux.
                    879:                         */
1.207     christos  880:                        uts.tv_sec += uts.tv_nsec / 1000000000;
                    881:                        uts.tv_nsec %= 1000000000;
                    882:                        if (uts.tv_nsec < 0) {
                    883:                                uts.tv_sec -= 1;
                    884:                                uts.tv_nsec += 1000000000;
1.13      mycroft   885:                        }
1.207     christos  886:                        if (uts.tv_sec < 0)
                    887:                                timespecclear(&uts);
1.13      mycroft   888:                }
1.207     christos  889:                ts = &uts;
                    890:                nanotime(&ts0);
1.13      mycroft   891:        }
1.7       fvdl      892:
1.211     rmind     893:        error = selcommon(retval, nfds, readfds, writefds, exceptfds, ts, NULL);
1.177     dsl       894:
1.10      mycroft   895:        if (error) {
                    896:                /*
                    897:                 * See fs/select.c in the Linux kernel.  Without this,
                    898:                 * Maelstrom doesn't work.
                    899:                 */
                    900:                if (error == ERESTART)
                    901:                        error = EINTR;
1.7       fvdl      902:                return error;
1.10      mycroft   903:        }
1.7       fvdl      904:
1.17      fvdl      905:        if (timeout) {
1.14      mycroft   906:                if (*retval) {
1.7       fvdl      907:                        /*
1.13      mycroft   908:                         * Compute how much time was left of the timeout,
1.7       fvdl      909:                         * by subtracting the current time and the time
                    910:                         * before we started the call, and subtracting
                    911:                         * that result from the user-supplied value.
                    912:                         */
1.207     christos  913:                        nanotime(&ts1);
                    914:                        timespecsub(&ts1, &ts0, &ts1);
                    915:                        timespecsub(&uts, &ts1, &uts);
                    916:                        if (uts.tv_sec < 0)
                    917:                                timespecclear(&uts);
1.14      mycroft   918:                } else
1.207     christos  919:                        timespecclear(&uts);
                    920:                ltv.tv_sec = uts.tv_sec;
                    921:                ltv.tv_usec = uts.tv_nsec / 1000;
1.203     christos  922:                if ((error = copyout(&ltv, timeout, sizeof(ltv))))
1.7       fvdl      923:                        return error;
                    924:        }
1.13      mycroft   925:
1.7       fvdl      926:        return 0;
1.1       fvdl      927: }
                    928:
1.234     manu      929: /*
                    930:  * Derived from FreeBSD's sys/compat/linux/linux_misc.c:linux_pselect6()
                    931:  * which was contributed by Dmitry Chagin
                    932:  * https://svnweb.freebsd.org/base?view=revision&revision=283403
                    933:  */
                    934: int
                    935: linux_sys_pselect6(struct lwp *l,
                    936:        const struct linux_sys_pselect6_args *uap, register_t *retval)
                    937: {
                    938:        /* {
                    939:                syscallarg(int) nfds;
                    940:                syscallarg(fd_set *) readfds;
                    941:                syscallarg(fd_set *) writefds;
                    942:                syscallarg(fd_set *) exceptfds;
                    943:                syscallarg(struct timespec *) timeout;
                    944:                syscallarg(linux_sized_sigset_t *) ss;
                    945:        } */
                    946:        struct timespec uts, ts0, ts1, *tsp;
                    947:        linux_sized_sigset_t lsss;
                    948:        struct linux_timespec lts;
                    949:        linux_sigset_t lss;
                    950:        sigset_t *ssp;
                    951:        sigset_t ss;
                    952:        int error;
                    953:
                    954:        ssp = NULL;
                    955:        if (SCARG(uap, ss) != NULL) {
                    956:                if ((error = copyin(SCARG(uap, ss), &lsss, sizeof(lsss))) != 0)
                    957:                        return (error);
                    958:                if (lsss.ss_len != sizeof(lss))
                    959:                        return (EINVAL);
                    960:                if (lsss.ss != NULL) {
                    961:                        if ((error = copyin(lsss.ss, &lss, sizeof(lss))) != 0)
                    962:                                return (error);
                    963:                        linux_to_native_sigset(&ss, &lss);
                    964:                        ssp = &ss;
                    965:                }
                    966:        }
                    967:
                    968:        if (SCARG(uap, timeout) != NULL) {
                    969:                error = copyin(SCARG(uap, timeout), &lts, sizeof(lts));
                    970:                if (error != 0)
                    971:                        return (error);
                    972:                linux_to_native_timespec(&uts, &lts);
                    973:
                    974:                if (itimespecfix(&uts))
                    975:                        return (EINVAL);
                    976:
                    977:                nanotime(&ts0);
                    978:                tsp = &uts;
                    979:        } else {
                    980:                tsp = NULL;
                    981:        }
                    982:
                    983:        error = selcommon(retval, SCARG(uap, nfds), SCARG(uap, readfds),
                    984:            SCARG(uap, writefds), SCARG(uap, exceptfds), tsp, ssp);
                    985:
                    986:        if (error == 0 && tsp != NULL) {
                    987:                if (retval != 0) {
                    988:                        /*
                    989:                         * Compute how much time was left of the timeout,
                    990:                         * by subtracting the current time and the time
                    991:                         * before we started the call, and subtracting
                    992:                         * that result from the user-supplied value.
                    993:                         */
                    994:                        nanotime(&ts1);
                    995:                        timespecsub(&ts1, &ts0, &ts1);
                    996:                        timespecsub(&uts, &ts1, &uts);
                    997:                        if (uts.tv_sec < 0)
                    998:                                timespecclear(&uts);
                    999:                } else {
                   1000:                        timespecclear(&uts);
                   1001:                }
                   1002:
                   1003:                native_to_linux_timespec(&lts, &uts);
                   1004:                error = copyout(&lts, SCARG(uap, timeout), sizeof(lts));
                   1005:        }
                   1006:
                   1007:        return (error);
                   1008: }
                   1009:
1.220     pooka    1010: int
                   1011: linux_sys_ppoll(struct lwp *l,
                   1012:        const struct linux_sys_ppoll_args *uap, register_t *retval)
                   1013: {
                   1014:        /* {
                   1015:                syscallarg(struct pollfd *) fds;
1.230     njoly    1016:                syscallarg(u_int) nfds;
1.220     pooka    1017:                syscallarg(struct linux_timespec *) timeout;
                   1018:                syscallarg(linux_sigset_t *) sigset;
                   1019:        } */
                   1020:        struct linux_timespec lts0, *lts;
                   1021:        struct timespec ts0, *ts = NULL;
                   1022:        linux_sigset_t lsigmask0, *lsigmask;
                   1023:        sigset_t sigmask0, *sigmask = NULL;
                   1024:        int error;
                   1025:
                   1026:        lts = SCARG(uap, timeout);
                   1027:        if (lts) {
                   1028:                if ((error = copyin(lts, &lts0, sizeof(lts0))) != 0)
                   1029:                        return error;
                   1030:                linux_to_native_timespec(&ts0, &lts0);
                   1031:                ts = &ts0;
                   1032:        }
                   1033:
                   1034:        lsigmask = SCARG(uap, sigset);
                   1035:        if (lsigmask) {
                   1036:                if ((error = copyin(lsigmask, &lsigmask0, sizeof(lsigmask0))))
                   1037:                        return error;
                   1038:                linux_to_native_sigset(&sigmask0, &lsigmask0);
                   1039:                sigmask = &sigmask0;
                   1040:        }
                   1041:
                   1042:        return pollcommon(retval, SCARG(uap, fds), SCARG(uap, nfds),
                   1043:            ts, sigmask);
                   1044: }
                   1045:
1.1       fvdl     1046: /*
1.6       fvdl     1047:  * Set the 'personality' (emulation mode) for the current process. Only
                   1048:  * accept the Linux personality here (0). This call is needed because
                   1049:  * the Linux ELF crt0 issues it in an ugly kludge to make sure that
                   1050:  * ELF binaries run in Linux mode, not SVR4 mode.
                   1051:  */
                   1052: int
1.190     dsl      1053: linux_sys_personality(struct lwp *l, const struct linux_sys_personality_args *uap, register_t *retval)
1.20      thorpej  1054: {
1.190     dsl      1055:        /* {
1.212     njoly    1056:                syscallarg(unsigned long) per;
1.190     dsl      1057:        } */
1.218     chs      1058:        struct linux_emuldata *led;
                   1059:        int per;
1.20      thorpej  1060:
1.218     chs      1061:        per = SCARG(uap, per);
                   1062:        led = l->l_emuldata;
                   1063:        if (per == LINUX_PER_QUERY) {
                   1064:                retval[0] = led->led_personality;
                   1065:                return 0;
                   1066:        }
                   1067:
                   1068:        switch (per & LINUX_PER_MASK) {
1.205     njoly    1069:        case LINUX_PER_LINUX:
1.218     chs      1070:        case LINUX_PER_LINUX32:
                   1071:                led->led_personality = per;
1.205     njoly    1072:                break;
1.218     chs      1073:
1.205     njoly    1074:        default:
1.6       fvdl     1075:                return EINVAL;
1.205     njoly    1076:        }
                   1077:
1.218     chs      1078:        retval[0] = per;
1.1       fvdl     1079:        return 0;
1.18      fvdl     1080: }
1.81      fvdl     1081:
1.63      abs      1082: /*
1.64      abs      1083:  * We have nonexistent fsuid equal to uid.
                   1084:  * If modification is requested, refuse.
1.63      abs      1085:  */
                   1086: int
1.190     dsl      1087: linux_sys_setfsuid(struct lwp *l, const struct linux_sys_setfsuid_args *uap, register_t *retval)
1.63      abs      1088: {
1.190     dsl      1089:         /* {
1.63      abs      1090:                 syscallarg(uid_t) uid;
1.190     dsl      1091:         } */
1.63      abs      1092:         uid_t uid;
                   1093:
                   1094:         uid = SCARG(uap, uid);
1.158     ad       1095:         if (kauth_cred_getuid(l->l_cred) != uid)
1.190     dsl      1096:                 return sys_nosys(l, uap, retval);
1.191     njoly    1097:
                   1098:         *retval = uid;
                   1099:         return 0;
1.63      abs      1100: }
                   1101:
                   1102: int
1.191     njoly    1103: linux_sys_setfsgid(struct lwp *l, const struct linux_sys_setfsgid_args *uap, register_t *retval)
1.63      abs      1104: {
1.191     njoly    1105:        /* {
                   1106:                syscallarg(gid_t) gid;
                   1107:        } */
                   1108:        gid_t gid;
                   1109:
                   1110:        gid = SCARG(uap, gid);
                   1111:        if (kauth_cred_getgid(l->l_cred) != gid)
                   1112:                return sys_nosys(l, uap, retval);
                   1113:
                   1114:        *retval = gid;
                   1115:        return 0;
1.27      fvdl     1116: }
                   1117:
                   1118: int
1.190     dsl      1119: linux_sys_setresuid(struct lwp *l, const struct linux_sys_setresuid_args *uap, register_t *retval)
1.57      thorpej  1120: {
1.190     dsl      1121:        /* {
1.57      thorpej  1122:                syscallarg(uid_t) ruid;
                   1123:                syscallarg(uid_t) euid;
                   1124:                syscallarg(uid_t) suid;
1.190     dsl      1125:        } */
1.57      thorpej  1126:
                   1127:        /*
                   1128:         * Note: These checks are a little different than the NetBSD
                   1129:         * setreuid(2) call performs.  This precisely follows the
                   1130:         * behavior of the Linux kernel.
                   1131:         */
                   1132:
1.117     dsl      1133:        return do_setresuid(l, SCARG(uap, ruid), SCARG(uap, euid),
                   1134:                            SCARG(uap, suid),
                   1135:                            ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S |
                   1136:                            ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
                   1137:                            ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S );
1.57      thorpej  1138: }
                   1139:
                   1140: int
1.190     dsl      1141: linux_sys_getresuid(struct lwp *l, const struct linux_sys_getresuid_args *uap, register_t *retval)
1.57      thorpej  1142: {
1.190     dsl      1143:        /* {
1.57      thorpej  1144:                syscallarg(uid_t *) ruid;
                   1145:                syscallarg(uid_t *) euid;
                   1146:                syscallarg(uid_t *) suid;
1.190     dsl      1147:        } */
1.158     ad       1148:        kauth_cred_t pc = l->l_cred;
1.57      thorpej  1149:        int error;
1.154     elad     1150:        uid_t uid;
1.57      thorpej  1151:
                   1152:        /*
                   1153:         * Linux copies these values out to userspace like so:
                   1154:         *
                   1155:         *      1. Copy out ruid.
                   1156:         *      2. If that succeeds, copy out euid.
                   1157:         *      3. If both of those succeed, copy out suid.
                   1158:         */
1.154     elad     1159:        uid = kauth_cred_getuid(pc);
                   1160:        if ((error = copyout(&uid, SCARG(uap, ruid), sizeof(uid_t))) != 0)
1.57      thorpej  1161:                return (error);
                   1162:
1.154     elad     1163:        uid = kauth_cred_geteuid(pc);
                   1164:        if ((error = copyout(&uid, SCARG(uap, euid), sizeof(uid_t))) != 0)
1.57      thorpej  1165:                return (error);
                   1166:
1.154     elad     1167:        uid = kauth_cred_getsvuid(pc);
                   1168:
                   1169:        return (copyout(&uid, SCARG(uap, suid), sizeof(uid_t)));
1.78      fvdl     1170: }
1.62      tron     1171:
                   1172: int
1.190     dsl      1173: linux_sys_ptrace(struct lwp *l, const struct linux_sys_ptrace_args *uap, register_t *retval)
1.62      tron     1174: {
1.190     dsl      1175:        /* {
1.88      manu     1176:                i386, m68k, powerpc: T=int
1.137     manu     1177:                alpha, amd64: T=long
1.66      erh      1178:                syscallarg(T) request;
                   1179:                syscallarg(T) pid;
                   1180:                syscallarg(T) addr;
                   1181:                syscallarg(T) data;
1.190     dsl      1182:        } */
1.73      jdolecek 1183:        const int *ptr;
                   1184:        int request;
1.89      manu     1185:        int error;
1.62      tron     1186:
                   1187:        ptr = linux_ptrace_request_map;
                   1188:        request = SCARG(uap, request);
                   1189:        while (*ptr != -1)
                   1190:                if (*ptr++ == request) {
                   1191:                        struct sys_ptrace_args pta;
                   1192:
                   1193:                        SCARG(&pta, req) = *ptr;
                   1194:                        SCARG(&pta, pid) = SCARG(uap, pid);
1.167     christos 1195:                        SCARG(&pta, addr) = (void *)SCARG(uap, addr);
1.62      tron     1196:                        SCARG(&pta, data) = SCARG(uap, data);
                   1197:
1.73      jdolecek 1198:                        /*
                   1199:                         * Linux ptrace(PTRACE_CONT, pid, 0, 0) means actually
1.90      jdolecek 1200:                         * to continue where the process left off previously.
1.202     ad       1201:                         * The same thing is achieved by addr == (void *) 1
1.90      jdolecek 1202:                         * on NetBSD, so rewrite 'addr' appropriately.
1.73      jdolecek 1203:                         */
                   1204:                        if (request == LINUX_PTRACE_CONT && SCARG(uap, addr)==0)
1.167     christos 1205:                                SCARG(&pta, addr) = (void *) 1;
1.135     perry    1206:
1.202     ad       1207:                        error = sysent[SYS_ptrace].sy_call(l, &pta, retval);
1.135     perry    1208:                        if (error)
1.92      manu     1209:                                return error;
                   1210:                        switch (request) {
                   1211:                        case LINUX_PTRACE_PEEKTEXT:
                   1212:                        case LINUX_PTRACE_PEEKDATA:
1.135     perry    1213:                                error = copyout (retval,
1.167     christos 1214:                                    (void *)SCARG(uap, data),
1.137     manu     1215:                                    sizeof *retval);
1.92      manu     1216:                                *retval = SCARG(uap, data);
                   1217:                                break;
1.135     perry    1218:                        default:
1.92      manu     1219:                                break;
                   1220:                        }
1.89      manu     1221:                        return error;
1.62      tron     1222:                }
                   1223:                else
                   1224:                        ptr++;
                   1225:
1.116     thorpej  1226:        return LINUX_SYS_PTRACE_ARCH(l, uap, retval);
1.1       fvdl     1227: }
1.67      erh      1228:
                   1229: int
1.190     dsl      1230: linux_sys_reboot(struct lwp *l, const struct linux_sys_reboot_args *uap, register_t *retval)
1.67      erh      1231: {
1.190     dsl      1232:        /* {
1.67      erh      1233:                syscallarg(int) magic1;
                   1234:                syscallarg(int) magic2;
                   1235:                syscallarg(int) cmd;
                   1236:                syscallarg(void *) arg;
1.190     dsl      1237:        } */
1.67      erh      1238:        struct sys_reboot_args /* {
                   1239:                syscallarg(int) opt;
                   1240:                syscallarg(char *) bootstr;
                   1241:        } */ sra;
                   1242:        int error;
                   1243:
1.164     elad     1244:        if ((error = kauth_authorize_system(l->l_cred,
                   1245:            KAUTH_SYSTEM_REBOOT, 0, NULL, NULL, NULL)) != 0)
1.67      erh      1246:                return(error);
                   1247:
                   1248:        if (SCARG(uap, magic1) != LINUX_REBOOT_MAGIC1)
                   1249:                return(EINVAL);
                   1250:        if (SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2 &&
                   1251:            SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2A &&
                   1252:            SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2B)
                   1253:                return(EINVAL);
                   1254:
1.200     gmcgarry 1255:        switch ((unsigned long)SCARG(uap, cmd)) {
1.67      erh      1256:        case LINUX_REBOOT_CMD_RESTART:
                   1257:                SCARG(&sra, opt) = RB_AUTOBOOT;
                   1258:                break;
                   1259:        case LINUX_REBOOT_CMD_HALT:
                   1260:                SCARG(&sra, opt) = RB_HALT;
                   1261:                break;
                   1262:        case LINUX_REBOOT_CMD_POWER_OFF:
                   1263:                SCARG(&sra, opt) = RB_HALT|RB_POWERDOWN;
                   1264:                break;
                   1265:        case LINUX_REBOOT_CMD_RESTART2:
                   1266:                /* Reboot with an argument. */
                   1267:                SCARG(&sra, opt) = RB_AUTOBOOT|RB_STRING;
                   1268:                SCARG(&sra, bootstr) = SCARG(uap, arg);
                   1269:                break;
                   1270:        case LINUX_REBOOT_CMD_CAD_ON:
                   1271:                return(EINVAL); /* We don't implement ctrl-alt-delete */
                   1272:        case LINUX_REBOOT_CMD_CAD_OFF:
                   1273:                return(0);
                   1274:        default:
                   1275:                return(EINVAL);
                   1276:        }
                   1277:
1.116     thorpej  1278:        return(sys_reboot(l, &sra, retval));
1.75      jdolecek 1279: }
                   1280:
                   1281: /*
                   1282:  * Copy of compat_12_sys_swapon().
                   1283:  */
                   1284: int
1.190     dsl      1285: linux_sys_swapon(struct lwp *l, const struct linux_sys_swapon_args *uap, register_t *retval)
1.75      jdolecek 1286: {
1.190     dsl      1287:        /* {
                   1288:                syscallarg(const char *) name;
                   1289:        } */
1.75      jdolecek 1290:        struct sys_swapctl_args ua;
                   1291:
                   1292:        SCARG(&ua, cmd) = SWAP_ON;
1.139     drochner 1293:        SCARG(&ua, arg) = (void *)__UNCONST(SCARG(uap, name));
1.75      jdolecek 1294:        SCARG(&ua, misc) = 0;   /* priority */
1.116     thorpej  1295:        return (sys_swapctl(l, &ua, retval));
1.76      jdolecek 1296: }
                   1297:
                   1298: /*
                   1299:  * Stop swapping to the file or block device specified by path.
                   1300:  */
                   1301: int
1.190     dsl      1302: linux_sys_swapoff(struct lwp *l, const struct linux_sys_swapoff_args *uap, register_t *retval)
1.76      jdolecek 1303: {
1.190     dsl      1304:        /* {
                   1305:                syscallarg(const char *) path;
                   1306:        } */
1.76      jdolecek 1307:        struct sys_swapctl_args ua;
                   1308:
                   1309:        SCARG(&ua, cmd) = SWAP_OFF;
1.138     christos 1310:        SCARG(&ua, arg) = __UNCONST(SCARG(uap, path)); /*XXXUNCONST*/
1.116     thorpej  1311:        return (sys_swapctl(l, &ua, retval));
1.75      jdolecek 1312: }
                   1313:
                   1314: /*
                   1315:  * Copy of compat_09_sys_setdomainname()
                   1316:  */
                   1317: /* ARGSUSED */
                   1318: int
1.190     dsl      1319: linux_sys_setdomainname(struct lwp *l, const struct linux_sys_setdomainname_args *uap, register_t *retval)
1.75      jdolecek 1320: {
1.190     dsl      1321:        /* {
1.75      jdolecek 1322:                syscallarg(char *) domainname;
                   1323:                syscallarg(int) len;
1.190     dsl      1324:        } */
1.122     atatat   1325:        int name[2];
1.75      jdolecek 1326:
1.122     atatat   1327:        name[0] = CTL_KERN;
                   1328:        name[1] = KERN_DOMAINNAME;
                   1329:        return (old_sysctl(&name[0], 2, 0, 0, SCARG(uap, domainname),
                   1330:                            SCARG(uap, len), l));
1.77      augustss 1331: }
                   1332:
                   1333: /*
                   1334:  * sysinfo()
                   1335:  */
                   1336: /* ARGSUSED */
                   1337: int
1.190     dsl      1338: linux_sys_sysinfo(struct lwp *l, const struct linux_sys_sysinfo_args *uap, register_t *retval)
1.77      augustss 1339: {
1.190     dsl      1340:        /* {
1.77      augustss 1341:                syscallarg(struct linux_sysinfo *) arg;
1.190     dsl      1342:        } */
1.77      augustss 1343:        struct linux_sysinfo si;
                   1344:        struct loadavg *la;
                   1345:
1.155     kardel   1346:        si.uptime = time_uptime;
1.77      augustss 1347:        la = &averunnable;
                   1348:        si.loads[0] = la->ldavg[0] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
                   1349:        si.loads[1] = la->ldavg[1] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
                   1350:        si.loads[2] = la->ldavg[2] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
1.162     manu     1351:        si.totalram = ctob((u_long)physmem);
                   1352:        si.freeram = (u_long)uvmexp.free * uvmexp.pagesize;
1.77      augustss 1353:        si.sharedram = 0;       /* XXX */
1.162     manu     1354:        si.bufferram = (u_long)uvmexp.filepages * uvmexp.pagesize;
                   1355:        si.totalswap = (u_long)uvmexp.swpages * uvmexp.pagesize;
                   1356:        si.freeswap =
                   1357:            (u_long)(uvmexp.swpages - uvmexp.swpginuse) * uvmexp.pagesize;
1.77      augustss 1358:        si.procs = nprocs;
                   1359:
                   1360:        /* The following are only present in newer Linux kernels. */
                   1361:        si.totalbig = 0;
                   1362:        si.freebig = 0;
                   1363:        si.mem_unit = 1;
                   1364:
                   1365:        return (copyout(&si, SCARG(uap, arg), sizeof si));
1.97      christos 1366: }
                   1367:
                   1368: int
1.190     dsl      1369: linux_sys_getrlimit(struct lwp *l, const struct linux_sys_getrlimit_args *uap, register_t *retval)
1.97      christos 1370: {
1.190     dsl      1371:        /* {
1.97      christos 1372:                syscallarg(int) which;
1.150     manu     1373: # ifdef LINUX_LARGEFILE64
1.144     manu     1374:                syscallarg(struct rlimit *) rlp;
1.150     manu     1375: # else
1.97      christos 1376:                syscallarg(struct orlimit *) rlp;
1.150     manu     1377: # endif
1.190     dsl      1378:        } */
1.150     manu     1379: # ifdef LINUX_LARGEFILE64
1.144     manu     1380:        struct rlimit orl;
1.150     manu     1381: # else
1.97      christos 1382:        struct orlimit orl;
1.150     manu     1383: # endif
1.176     dsl      1384:        int which;
                   1385:
                   1386:        which = linux_to_bsd_limit(SCARG(uap, which));
                   1387:        if (which < 0)
                   1388:                return -which;
1.97      christos 1389:
1.176     dsl      1390:        bsd_to_linux_rlimit(&orl, &l->l_proc->p_rlimit[which]);
1.146     rpaulo   1391:
1.97      christos 1392:        return copyout(&orl, SCARG(uap, rlp), sizeof(orl));
                   1393: }
                   1394:
                   1395: int
1.190     dsl      1396: linux_sys_setrlimit(struct lwp *l, const struct linux_sys_setrlimit_args *uap, register_t *retval)
1.97      christos 1397: {
1.190     dsl      1398:        /* {
1.97      christos 1399:                syscallarg(int) which;
1.150     manu     1400: # ifdef LINUX_LARGEFILE64
1.144     manu     1401:                syscallarg(struct rlimit *) rlp;
1.150     manu     1402: # else
1.97      christos 1403:                syscallarg(struct orlimit *) rlp;
1.150     manu     1404: # endif
1.190     dsl      1405:        } */
1.97      christos 1406:        struct rlimit rl;
1.150     manu     1407: # ifdef LINUX_LARGEFILE64
1.144     manu     1408:        struct rlimit orl;
1.150     manu     1409: # else
1.97      christos 1410:        struct orlimit orl;
1.150     manu     1411: # endif
1.97      christos 1412:        int error;
1.176     dsl      1413:        int which;
1.97      christos 1414:
                   1415:        if ((error = copyin(SCARG(uap, rlp), &orl, sizeof(orl))) != 0)
                   1416:                return error;
1.176     dsl      1417:
                   1418:        which = linux_to_bsd_limit(SCARG(uap, which));
                   1419:        if (which < 0)
                   1420:                return -which;
                   1421:
1.97      christos 1422:        linux_to_bsd_rlimit(&rl, &orl);
1.176     dsl      1423:        return dosetrlimit(l, l->l_proc, which, &rl);
1.97      christos 1424: }
                   1425:
1.150     manu     1426: # if !defined(__mips__) && !defined(__amd64__)
1.98      rafal    1427: /* XXX: this doesn't look 100% common, at least mips doesn't have it */
1.97      christos 1428: int
1.190     dsl      1429: linux_sys_ugetrlimit(struct lwp *l, const struct linux_sys_ugetrlimit_args *uap, register_t *retval)
1.97      christos 1430: {
1.190     dsl      1431:        return linux_sys_getrlimit(l, (const void *)uap, retval);
1.87      jdolecek 1432: }
1.150     manu     1433: # endif
1.87      jdolecek 1434:
                   1435: /*
                   1436:  * This gets called for unsupported syscalls. The difference to sys_nosys()
                   1437:  * is that process does not get SIGSYS, the call just returns with ENOSYS.
                   1438:  * This is the way Linux does it and glibc depends on this behaviour.
                   1439:  */
                   1440: int
1.190     dsl      1441: linux_sys_nosys(struct lwp *l, const void *v, register_t *retval)
1.87      jdolecek 1442: {
                   1443:        return (ENOSYS);
1.67      erh      1444: }
1.150     manu     1445:
1.156     christos 1446: int
1.190     dsl      1447: linux_sys_getpriority(struct lwp *l, const struct linux_sys_getpriority_args *uap, register_t *retval)
1.156     christos 1448: {
1.190     dsl      1449:         /* {
1.156     christos 1450:                 syscallarg(int) which;
                   1451:                 syscallarg(int) who;
1.190     dsl      1452:         } */
1.156     christos 1453:         struct sys_getpriority_args bsa;
                   1454:         int error;
                   1455:
                   1456:         SCARG(&bsa, which) = SCARG(uap, which);
                   1457:         SCARG(&bsa, who) = SCARG(uap, who);
                   1458:
                   1459:         if ((error = sys_getpriority(l, &bsa, retval)))
                   1460:                 return error;
                   1461:
1.157     christos 1462:         *retval = NZERO - *retval;
1.156     christos 1463:
                   1464:         return 0;
                   1465: }
1.221     pooka    1466:
                   1467: int
1.228     chs      1468: linux_do_sys_utimensat(struct lwp *l, int fd, const char *path, struct timespec *tsp, int flags, register_t *retval)
1.226     njoly    1469: {
                   1470:        int follow, error;
                   1471:
1.228     chs      1472:        follow = (flags & LINUX_AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
1.226     njoly    1473:
1.228     chs      1474:        if (path == NULL && fd != AT_FDCWD) {
1.226     njoly    1475:                file_t *fp;
                   1476:
                   1477:                /* fd_getvnode() will use the descriptor for us */
1.228     chs      1478:                if ((error = fd_getvnode(fd, &fp)) != 0)
1.226     njoly    1479:                        return error;
                   1480:                error = do_sys_utimensat(l, AT_FDCWD, fp->f_data, NULL, 0,
                   1481:                    tsp, UIO_SYSSPACE);
1.228     chs      1482:                fd_putfile(fd);
1.226     njoly    1483:                return error;
                   1484:        }
                   1485:
1.228     chs      1486:        return do_sys_utimensat(l, fd, NULL, path, follow, tsp, UIO_SYSSPACE);
1.226     njoly    1487: }
                   1488:
1.221     pooka    1489: int
1.228     chs      1490: linux_sys_utimensat(struct lwp *l, const struct linux_sys_utimensat_args *uap,
                   1491:        register_t *retval)
1.221     pooka    1492: {
                   1493:        /* {
1.228     chs      1494:                syscallarg(int) fd;
1.221     pooka    1495:                syscallarg(const char *) path;
1.228     chs      1496:                syscallarg(const struct linux_timespec *) times;
                   1497:                syscallarg(int) flag;
1.221     pooka    1498:        } */
                   1499:        int error;
1.228     chs      1500:        struct linux_timespec lts[2];
                   1501:        struct timespec *tsp = NULL, ts[2];
1.221     pooka    1502:
                   1503:        if (SCARG(uap, times)) {
1.228     chs      1504:                error = copyin(SCARG(uap, times), &lts, sizeof(lts));
                   1505:                if (error != 0)
1.221     pooka    1506:                        return error;
1.228     chs      1507:                linux_to_native_timespec(&ts[0], &lts[0]);
                   1508:                linux_to_native_timespec(&ts[1], &lts[1]);
                   1509:                tsp = ts;
1.221     pooka    1510:        }
                   1511:
1.228     chs      1512:        return linux_do_sys_utimensat(l, SCARG(uap, fd), SCARG(uap, path),
                   1513:            tsp, SCARG(uap, flag), retval);
1.221     pooka    1514: }

CVSweb <webmaster@jp.NetBSD.org>