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

1.226   ! njoly       1: /*     $NetBSD: linux_misc.c,v 1.225 2013/09/15 12:58:34 njoly 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.226   ! njoly      60: __KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.225 2013/09/15 12:58:34 njoly 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.150     manu      116: #ifndef COMPAT_LINUX32
1.170     njoly     117: #include <compat/linux/common/linux_statfs.h>
1.150     manu      118: #include <compat/linux/common/linux_limit.h>
                    119: #endif
1.62      tron      120: #include <compat/linux/common/linux_ptrace.h>
1.67      erh       121: #include <compat/linux/common/linux_reboot.h>
1.84      manu      122: #include <compat/linux/common/linux_emuldata.h>
1.220     pooka     123: #include <compat/linux/common/linux_sched.h>
1.49      christos  124:
1.216     chs       125: #include <compat/linux/linux_syscallargs.h>
                    126:
1.150     manu      127: #ifndef COMPAT_LINUX32
1.73      jdolecek  128: const int linux_ptrace_request_map[] = {
1.62      tron      129:        LINUX_PTRACE_TRACEME,   PT_TRACE_ME,
                    130:        LINUX_PTRACE_PEEKTEXT,  PT_READ_I,
                    131:        LINUX_PTRACE_PEEKDATA,  PT_READ_D,
                    132:        LINUX_PTRACE_POKETEXT,  PT_WRITE_I,
                    133:        LINUX_PTRACE_POKEDATA,  PT_WRITE_D,
                    134:        LINUX_PTRACE_CONT,      PT_CONTINUE,
                    135:        LINUX_PTRACE_KILL,      PT_KILL,
                    136:        LINUX_PTRACE_ATTACH,    PT_ATTACH,
                    137:        LINUX_PTRACE_DETACH,    PT_DETACH,
1.150     manu      138: # ifdef PT_STEP
1.73      jdolecek  139:        LINUX_PTRACE_SINGLESTEP,        PT_STEP,
1.150     manu      140: # endif
1.170     njoly     141:        LINUX_PTRACE_SYSCALL,   PT_SYSCALL,
1.62      tron      142:        -1
                    143: };
1.1       fvdl      144:
1.132     jdolecek  145: const struct linux_mnttypes linux_fstypes[] = {
1.101     christos  146:        { MOUNT_FFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    147:        { MOUNT_NFS,            LINUX_NFS_SUPER_MAGIC           },
                    148:        { MOUNT_MFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    149:        { MOUNT_MSDOS,          LINUX_MSDOS_SUPER_MAGIC         },
                    150:        { MOUNT_LFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    151:        { MOUNT_FDESC,          LINUX_DEFAULT_SUPER_MAGIC       },
                    152:        { MOUNT_NULL,           LINUX_DEFAULT_SUPER_MAGIC       },
1.135     perry     153:        { MOUNT_OVERLAY,        LINUX_DEFAULT_SUPER_MAGIC       },
1.101     christos  154:        { MOUNT_UMAP,           LINUX_DEFAULT_SUPER_MAGIC       },
                    155:        { MOUNT_KERNFS,         LINUX_DEFAULT_SUPER_MAGIC       },
                    156:        { MOUNT_PROCFS,         LINUX_PROC_SUPER_MAGIC          },
                    157:        { MOUNT_AFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    158:        { MOUNT_CD9660,         LINUX_ISOFS_SUPER_MAGIC         },
                    159:        { MOUNT_UNION,          LINUX_DEFAULT_SUPER_MAGIC       },
                    160:        { MOUNT_ADOSFS,         LINUX_ADFS_SUPER_MAGIC          },
                    161:        { MOUNT_EXT2FS,         LINUX_EXT2_SUPER_MAGIC          },
                    162:        { MOUNT_CFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    163:        { MOUNT_CODA,           LINUX_CODA_SUPER_MAGIC          },
                    164:        { MOUNT_FILECORE,       LINUX_DEFAULT_SUPER_MAGIC       },
                    165:        { MOUNT_NTFS,           LINUX_DEFAULT_SUPER_MAGIC       },
1.134     christos  166:        { MOUNT_SMBFS,          LINUX_SMB_SUPER_MAGIC           },
1.140     jmmv      167:        { MOUNT_PTYFS,          LINUX_DEVPTS_SUPER_MAGIC        },
1.199     njoly     168:        { MOUNT_TMPFS,          LINUX_TMPFS_SUPER_MAGIC         }
1.101     christos  169: };
1.132     jdolecek  170: const int linux_fstypes_cnt = sizeof(linux_fstypes) / sizeof(linux_fstypes[0]);
1.101     christos  171:
1.150     manu      172: # ifdef DEBUG_LINUX
1.104     christos  173: #define DPRINTF(a)     uprintf a
1.150     manu      174: # else
1.104     christos  175: #define DPRINTF(a)
1.150     manu      176: # endif
1.104     christos  177:
1.47      erh       178: /* Local linux_misc.c functions: */
1.188     dsl       179: static void linux_to_bsd_mmap_args(struct sys_mmap_args *,
                    180:     const struct linux_sys_mmap_args *);
1.190     dsl       181: static int linux_mmap(struct lwp *, const struct linux_sys_mmap_args *,
1.188     dsl       182:     register_t *, off_t);
1.128     jdolecek  183:
1.26      christos  184:
1.1       fvdl      185: /*
                    186:  * The information on a terminated (or stopped) process needs
                    187:  * to be converted in order for Linux binaries to get a valid signal
                    188:  * number out of it.
                    189:  */
1.173     dsl       190: int
                    191: bsd_to_linux_wstat(int st)
1.1       fvdl      192: {
1.21      mycroft   193:
1.52      christos  194:        int sig;
                    195:
1.173     dsl       196:        if (WIFSIGNALED(st)) {
                    197:                sig = WTERMSIG(st);
1.52      christos  198:                if (sig >= 0 && sig < NSIG)
1.173     dsl       199:                        st= (st & ~0177) | native_to_linux_signo[sig];
                    200:        } else if (WIFSTOPPED(st)) {
                    201:                sig = WSTOPSIG(st);
1.52      christos  202:                if (sig >= 0 && sig < NSIG)
1.173     dsl       203:                        st = (st & ~0xff00) |
1.105     christos  204:                            (native_to_linux_signo[sig] << 8);
1.52      christos  205:        }
1.173     dsl       206:        return st;
1.1       fvdl      207: }
                    208:
                    209: /*
1.133     erh       210:  * wait4(2).  Passed on to the NetBSD call, surrounded by code to
                    211:  * reserve some space for a NetBSD-style wait status, and converting
                    212:  * it to what Linux wants.
1.1       fvdl      213:  */
                    214: int
1.190     dsl       215: linux_sys_wait4(struct lwp *l, const struct linux_sys_wait4_args *uap, register_t *retval)
1.20      thorpej   216: {
1.190     dsl       217:        /* {
1.1       fvdl      218:                syscallarg(int) pid;
                    219:                syscallarg(int *) status;
                    220:                syscallarg(int) options;
1.204     njoly     221:                syscallarg(struct rusage50 *) rusage;
1.190     dsl       222:        } */
1.210     rmind     223:        int error, status, options, linux_options, pid = SCARG(uap, pid);
                    224:        struct rusage50 ru50;
1.173     dsl       225:        struct rusage ru;
1.196     ad        226:        proc_t *p;
1.1       fvdl      227:
1.55      thorpej   228:        linux_options = SCARG(uap, options);
1.173     dsl       229:        options = WOPTSCHECKED;
1.133     erh       230:        if (linux_options & ~(LINUX_WAIT4_KNOWNFLAGS))
1.55      thorpej   231:                return (EINVAL);
                    232:
                    233:        if (linux_options & LINUX_WAIT4_WNOHANG)
                    234:                options |= WNOHANG;
                    235:        if (linux_options & LINUX_WAIT4_WUNTRACED)
                    236:                options |= WUNTRACED;
1.93      thorpej   237:        if (linux_options & LINUX_WAIT4_WALL)
                    238:                options |= WALLSIG;
1.55      thorpej   239:        if (linux_options & LINUX_WAIT4_WCLONE)
                    240:                options |= WALTSIG;
1.150     manu      241: # ifdef DIAGNOSTIC
1.133     erh       242:        if (linux_options & LINUX_WAIT4_WNOTHREAD)
                    243:                printf("WARNING: %s: linux process %d.%d called "
                    244:                       "waitpid with __WNOTHREAD set!",
1.173     dsl       245:                       __FILE__, l->l_proc->p_pid, l->l_lid);
1.133     erh       246:
1.150     manu      247: # endif
1.55      thorpej   248:
1.210     rmind     249:        error = do_sys_wait(&pid, &status, options,
                    250:            SCARG(uap, rusage) != NULL ? &ru : NULL);
1.1       fvdl      251:
1.190     dsl       252:        retval[0] = pid;
                    253:        if (pid == 0)
1.1       fvdl      254:                return error;
                    255:
1.210     rmind     256:        p = curproc;
                    257:        mutex_enter(p->p_lock);
1.196     ad        258:        sigdelset(&p->p_sigpend.sp_set, SIGCHLD); /* XXXAD ksiginfo leak */
1.210     rmind     259:        mutex_exit(p->p_lock);
1.18      fvdl      260:
1.204     njoly     261:        if (SCARG(uap, rusage) != NULL) {
                    262:                rusage_to_rusage50(&ru, &ru50);
1.174     dsl       263:                error = copyout(&ru, SCARG(uap, rusage), sizeof(ru));
1.204     njoly     264:        }
1.174     dsl       265:
                    266:        if (error == 0 && SCARG(uap, status) != NULL) {
1.173     dsl       267:                status = bsd_to_linux_wstat(status);
1.174     dsl       268:                error = copyout(&status, SCARG(uap, status), sizeof status);
1.16      fvdl      269:        }
1.1       fvdl      270:
1.174     dsl       271:        return error;
1.1       fvdl      272: }
                    273:
                    274: /*
1.216     chs       275:  * Linux brk(2).  Like native, but always return the new break value.
1.1       fvdl      276:  */
                    277: int
1.190     dsl       278: linux_sys_brk(struct lwp *l, const struct linux_sys_brk_args *uap, register_t *retval)
1.20      thorpej   279: {
1.190     dsl       280:        /* {
1.1       fvdl      281:                syscallarg(char *) nsize;
1.190     dsl       282:        } */
1.116     thorpej   283:        struct proc *p = l->l_proc;
1.216     chs       284:        struct vmspace *vm = p->p_vmspace;
1.21      mycroft   285:        struct sys_obreak_args oba;
1.1       fvdl      286:
1.216     chs       287:        SCARG(&oba, nsize) = SCARG(uap, nsize);
1.1       fvdl      288:
1.216     chs       289:        (void) sys_obreak(l, &oba, retval);
                    290:        retval[0] = (register_t)((char *)vm->vm_daddr + ptoa(vm->vm_dsize));
1.1       fvdl      291:        return 0;
                    292: }
                    293:
                    294: /*
1.2       fvdl      295:  * Implement the fs stat functions. Straightforward.
1.1       fvdl      296:  */
                    297: int
1.190     dsl       298: linux_sys_statfs(struct lwp *l, const struct linux_sys_statfs_args *uap, register_t *retval)
1.20      thorpej   299: {
1.190     dsl       300:        /* {
1.53      christos  301:                syscallarg(const char *) path;
1.1       fvdl      302:                syscallarg(struct linux_statfs *) sp;
1.190     dsl       303:        } */
1.172     dsl       304:        struct statvfs *sb;
1.2       fvdl      305:        struct linux_statfs ltmp;
                    306:        int error;
                    307:
1.172     dsl       308:        sb = STATVFSBUF_GET();
                    309:        error = do_sys_pstatvfs(l, SCARG(uap, path), ST_WAIT, sb);
                    310:        if (error == 0) {
                    311:                bsd_to_linux_statfs(sb, &ltmp);
                    312:                error = copyout(&ltmp, SCARG(uap, sp), sizeof ltmp);
                    313:        }
                    314:        STATVFSBUF_PUT(sb);
1.2       fvdl      315:
1.153     yamt      316:        return error;
1.1       fvdl      317: }
                    318:
                    319: int
1.190     dsl       320: linux_sys_fstatfs(struct lwp *l, const struct linux_sys_fstatfs_args *uap, register_t *retval)
1.20      thorpej   321: {
1.190     dsl       322:        /* {
1.2       fvdl      323:                syscallarg(int) fd;
1.1       fvdl      324:                syscallarg(struct linux_statfs *) sp;
1.190     dsl       325:        } */
1.172     dsl       326:        struct statvfs *sb;
1.2       fvdl      327:        struct linux_statfs ltmp;
                    328:        int error;
                    329:
1.172     dsl       330:        sb = STATVFSBUF_GET();
                    331:        error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
                    332:        if (error == 0) {
                    333:                bsd_to_linux_statfs(sb, &ltmp);
                    334:                error = copyout(&ltmp, SCARG(uap, sp), sizeof ltmp);
                    335:        }
                    336:        STATVFSBUF_PUT(sb);
1.2       fvdl      337:
1.153     yamt      338:        return error;
1.1       fvdl      339: }
1.82      fvdl      340:
1.1       fvdl      341: /*
                    342:  * uname(). Just copy the info from the various strings stored in the
                    343:  * kernel, and put it in the Linux utsname structure. That structure
                    344:  * is almost the same as the NetBSD one, only it has fields 65 characters
                    345:  * long, and an extra domainname field.
                    346:  */
                    347: int
1.190     dsl       348: linux_sys_uname(struct lwp *l, const struct linux_sys_uname_args *uap, register_t *retval)
1.20      thorpej   349: {
1.190     dsl       350:        /* {
1.1       fvdl      351:                syscallarg(struct linux_utsname *) up;
1.190     dsl       352:        } */
1.15      mycroft   353:        struct linux_utsname luts;
1.1       fvdl      354:
1.186     njoly     355:        strlcpy(luts.l_sysname, linux_sysname, sizeof(luts.l_sysname));
                    356:        strlcpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
                    357:        strlcpy(luts.l_release, linux_release, sizeof(luts.l_release));
                    358:        strlcpy(luts.l_version, linux_version, sizeof(luts.l_version));
                    359:        strlcpy(luts.l_machine, LINUX_UNAME_ARCH, sizeof(luts.l_machine));
                    360:        strlcpy(luts.l_domainname, domainname, sizeof(luts.l_domainname));
1.15      mycroft   361:
                    362:        return copyout(&luts, SCARG(uap, up), sizeof(luts));
                    363: }
                    364:
1.47      erh       365: /* Used directly on: alpha, mips, ppc, sparc, sparc64 */
                    366: /* Used indirectly on: arm, i386, m68k */
1.1       fvdl      367:
                    368: /*
1.47      erh       369:  * New type Linux mmap call.
                    370:  * Only called directly on machines with >= 6 free regs.
1.1       fvdl      371:  */
                    372: int
1.190     dsl       373: linux_sys_mmap(struct lwp *l, const struct linux_sys_mmap_args *uap, register_t *retval)
1.20      thorpej   374: {
1.190     dsl       375:        /* {
1.47      erh       376:                syscallarg(unsigned long) addr;
                    377:                syscallarg(size_t) len;
                    378:                syscallarg(int) prot;
                    379:                syscallarg(int) flags;
                    380:                syscallarg(int) fd;
1.94      manu      381:                syscallarg(linux_off_t) offset;
1.190     dsl       382:        } */
1.118     christos  383:
1.115     christos  384:        if (SCARG(uap, offset) & PAGE_MASK)
                    385:                return EINVAL;
                    386:
1.128     jdolecek  387:        return linux_mmap(l, uap, retval, SCARG(uap, offset));
1.118     christos  388: }
                    389:
                    390: /*
                    391:  * Guts of most architectures' mmap64() implementations.  This shares
                    392:  * its list of arguments with linux_sys_mmap().
                    393:  *
                    394:  * The difference in linux_sys_mmap2() is that "offset" is actually
                    395:  * (offset / pagesize), not an absolute byte count.  This translation
                    396:  * to pagesize offsets is done inside glibc between the mmap64() call
                    397:  * point, and the actual syscall.
                    398:  */
                    399: int
1.190     dsl       400: linux_sys_mmap2(struct lwp *l, const struct linux_sys_mmap2_args *uap, register_t *retval)
1.118     christos  401: {
1.190     dsl       402:        /* {
1.118     christos  403:                syscallarg(unsigned long) addr;
                    404:                syscallarg(size_t) len;
                    405:                syscallarg(int) prot;
                    406:                syscallarg(int) flags;
                    407:                syscallarg(int) fd;
                    408:                syscallarg(linux_off_t) offset;
1.190     dsl       409:        } */
1.128     jdolecek  410:
                    411:        return linux_mmap(l, uap, retval,
                    412:            ((off_t)SCARG(uap, offset)) << PAGE_SHIFT);
                    413: }
                    414:
                    415: /*
                    416:  * Massage arguments and call system mmap(2).
                    417:  */
                    418: static int
1.190     dsl       419: linux_mmap(struct lwp *l, const struct linux_sys_mmap_args *uap, register_t *retval, off_t offset)
1.128     jdolecek  420: {
1.118     christos  421:        struct sys_mmap_args cma;
1.128     jdolecek  422:        int error;
                    423:        size_t mmoff=0;
                    424:
1.190     dsl       425:        linux_to_bsd_mmap_args(&cma, uap);
                    426:        SCARG(&cma, pos) = offset;
                    427:
1.128     jdolecek  428:        if (SCARG(uap, flags) & LINUX_MAP_GROWSDOWN) {
                    429:                /*
                    430:                 * Request for stack-like memory segment. On linux, this
                    431:                 * works by mmap()ping (small) segment, which is automatically
                    432:                 * extended when page fault happens below the currently
                    433:                 * allocated area. We emulate this by allocating (typically
                    434:                 * bigger) segment sized at current stack size limit, and
                    435:                 * offsetting the requested and returned address accordingly.
                    436:                 * Since physical pages are only allocated on-demand, this
                    437:                 * is effectively identical.
                    438:                 */
                    439:                rlim_t ssl = l->l_proc->p_rlimit[RLIMIT_STACK].rlim_cur;
                    440:
1.190     dsl       441:                if (SCARG(&cma, len) < ssl) {
1.128     jdolecek  442:                        /* Compute the address offset */
                    443:                        mmoff = round_page(ssl) - SCARG(uap, len);
                    444:
1.190     dsl       445:                        if (SCARG(&cma, addr))
                    446:                                SCARG(&cma, addr) = (char *)SCARG(&cma, addr) - mmoff;
1.128     jdolecek  447:
1.190     dsl       448:                        SCARG(&cma, len) = (size_t) ssl;
1.128     jdolecek  449:                }
                    450:        }
1.118     christos  451:
1.128     jdolecek  452:        error = sys_mmap(l, &cma, retval);
                    453:        if (error)
                    454:                return (error);
                    455:
                    456:        /* Shift the returned address for stack-like segment if necessary */
1.190     dsl       457:        retval[0] += mmoff;
1.118     christos  458:
1.128     jdolecek  459:        return (0);
1.118     christos  460: }
                    461:
                    462: static void
1.189     dsl       463: linux_to_bsd_mmap_args(struct sys_mmap_args *cma, const struct linux_sys_mmap_args *uap)
1.118     christos  464: {
1.119     christos  465:        int flags = MAP_TRYFIXED, fl = SCARG(uap, flags);
1.135     perry     466:
1.103     christos  467:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_SHARED, MAP_SHARED);
                    468:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_PRIVATE, MAP_PRIVATE);
                    469:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_FIXED, MAP_FIXED);
                    470:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_ANON, MAP_ANON);
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);
                    606:        return uvm_map_protect(map, start, end, prot, FALSE);
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;
                    787:                }
                    788:                strcpy(idb.d_name, bdp->d_name);
1.217     chs       789:                idb.d_name[strlen(idb.d_name) + 1] = bdp->d_type;
1.167     christos  790:                if ((error = copyout((void *)&idb, outp, linux_reclen)))
1.107     christos  791:                        goto out;
                    792:                /* advance past this real entry */
                    793:                inp += reclen;
1.136     christos  794:                if (cookie)
                    795:                        off = *cookie++; /* each entry points to itself */
                    796:                else
                    797:                        off += reclen;
1.107     christos  798:                /* advance output past Linux-shaped entry */
                    799:                outp += linux_reclen;
                    800:                resid -= linux_reclen;
                    801:                if (oldcall)
                    802:                        break;
                    803:        }
                    804:
                    805:        /* if we squished out the whole block, try again */
1.214     he        806:        if (outp == (void *)SCARG(uap, dent)) {
                    807:                if (cookiebuf)
                    808:                        free(cookiebuf, M_TEMP);
                    809:                cookiebuf = NULL;
1.107     christos  810:                goto again;
1.214     he        811:        }
1.107     christos  812:        fp->f_offset = off;     /* update the vnode offset */
                    813:
                    814:        if (oldcall)
                    815:                nbytes = resid + linux_reclen;
                    816:
                    817: eof:
                    818:        *retval = nbytes - resid;
                    819: out:
1.215     hannken   820:        VOP_UNLOCK(vp);
1.107     christos  821:        if (cookiebuf)
                    822:                free(cookiebuf, M_TEMP);
1.138     christos  823:        free(tbuf, M_TEMP);
1.107     christos  824: out1:
1.194     ad        825:        fd_putfile(SCARG(uap, fd));
1.1       fvdl      826:        return error;
                    827: }
                    828:
                    829: /*
1.17      fvdl      830:  * Even when just using registers to pass arguments to syscalls you can
                    831:  * have 5 of them on the i386. So this newer version of select() does
                    832:  * this.
1.1       fvdl      833:  */
                    834: int
1.190     dsl       835: linux_sys_select(struct lwp *l, const struct linux_sys_select_args *uap, register_t *retval)
1.20      thorpej   836: {
1.190     dsl       837:        /* {
1.17      fvdl      838:                syscallarg(int) nfds;
                    839:                syscallarg(fd_set *) readfds;
                    840:                syscallarg(fd_set *) writefds;
                    841:                syscallarg(fd_set *) exceptfds;
1.203     christos  842:                syscallarg(struct timeval50 *) timeout;
1.190     dsl       843:        } */
1.20      thorpej   844:
1.116     thorpej   845:        return linux_select1(l, retval, SCARG(uap, nfds), SCARG(uap, readfds),
1.203     christos  846:            SCARG(uap, writefds), SCARG(uap, exceptfds),
                    847:            (struct linux_timeval *)SCARG(uap, timeout));
1.17      fvdl      848: }
                    849:
                    850: /*
                    851:  * Common code for the old and new versions of select(). A couple of
                    852:  * things are important:
                    853:  * 1) return the amount of time left in the 'timeout' parameter
                    854:  * 2) select never returns ERESTART on Linux, always return EINTR
                    855:  */
                    856: int
1.211     rmind     857: linux_select1(struct lwp *l, register_t *retval, int nfds, fd_set *readfds,
                    858:     fd_set *writefds, fd_set *exceptfds, struct linux_timeval *timeout)
1.17      fvdl      859: {
1.207     christos  860:        struct timespec ts0, ts1, uts, *ts = NULL;
1.203     christos  861:        struct linux_timeval ltv;
1.1       fvdl      862:        int error;
                    863:
1.7       fvdl      864:        /*
                    865:         * Store current time for computation of the amount of
                    866:         * time left.
                    867:         */
1.17      fvdl      868:        if (timeout) {
1.203     christos  869:                if ((error = copyin(timeout, &ltv, sizeof(ltv))))
1.13      mycroft   870:                        return error;
1.207     christos  871:                uts.tv_sec = ltv.tv_sec;
                    872:                uts.tv_nsec = ltv.tv_usec * 1000;
                    873:                if (itimespecfix(&uts)) {
1.13      mycroft   874:                        /*
                    875:                         * The timeval was invalid.  Convert it to something
                    876:                         * valid that will act as it does under Linux.
                    877:                         */
1.207     christos  878:                        uts.tv_sec += uts.tv_nsec / 1000000000;
                    879:                        uts.tv_nsec %= 1000000000;
                    880:                        if (uts.tv_nsec < 0) {
                    881:                                uts.tv_sec -= 1;
                    882:                                uts.tv_nsec += 1000000000;
1.13      mycroft   883:                        }
1.207     christos  884:                        if (uts.tv_sec < 0)
                    885:                                timespecclear(&uts);
1.13      mycroft   886:                }
1.207     christos  887:                ts = &uts;
                    888:                nanotime(&ts0);
1.13      mycroft   889:        }
1.7       fvdl      890:
1.211     rmind     891:        error = selcommon(retval, nfds, readfds, writefds, exceptfds, ts, NULL);
1.177     dsl       892:
1.10      mycroft   893:        if (error) {
                    894:                /*
                    895:                 * See fs/select.c in the Linux kernel.  Without this,
                    896:                 * Maelstrom doesn't work.
                    897:                 */
                    898:                if (error == ERESTART)
                    899:                        error = EINTR;
1.7       fvdl      900:                return error;
1.10      mycroft   901:        }
1.7       fvdl      902:
1.17      fvdl      903:        if (timeout) {
1.14      mycroft   904:                if (*retval) {
1.7       fvdl      905:                        /*
1.13      mycroft   906:                         * Compute how much time was left of the timeout,
1.7       fvdl      907:                         * by subtracting the current time and the time
                    908:                         * before we started the call, and subtracting
                    909:                         * that result from the user-supplied value.
                    910:                         */
1.207     christos  911:                        nanotime(&ts1);
                    912:                        timespecsub(&ts1, &ts0, &ts1);
                    913:                        timespecsub(&uts, &ts1, &uts);
                    914:                        if (uts.tv_sec < 0)
                    915:                                timespecclear(&uts);
1.14      mycroft   916:                } else
1.207     christos  917:                        timespecclear(&uts);
                    918:                ltv.tv_sec = uts.tv_sec;
                    919:                ltv.tv_usec = uts.tv_nsec / 1000;
1.203     christos  920:                if ((error = copyout(&ltv, timeout, sizeof(ltv))))
1.7       fvdl      921:                        return error;
                    922:        }
1.13      mycroft   923:
1.7       fvdl      924:        return 0;
1.1       fvdl      925: }
                    926:
1.220     pooka     927: int
                    928: linux_sys_ppoll(struct lwp *l,
                    929:        const struct linux_sys_ppoll_args *uap, register_t *retval)
                    930: {
                    931:        /* {
                    932:                syscallarg(struct pollfd *) fds;
                    933:                syscallarg(int) nfds;
                    934:                syscallarg(struct linux_timespec *) timeout;
                    935:                syscallarg(linux_sigset_t *) sigset;
                    936:        } */
                    937:        struct linux_timespec lts0, *lts;
                    938:        struct timespec ts0, *ts = NULL;
                    939:        linux_sigset_t lsigmask0, *lsigmask;
                    940:        sigset_t sigmask0, *sigmask = NULL;
                    941:        int error;
                    942:
                    943:        lts = SCARG(uap, timeout);
                    944:        if (lts) {
                    945:                if ((error = copyin(lts, &lts0, sizeof(lts0))) != 0)
                    946:                        return error;
                    947:                linux_to_native_timespec(&ts0, &lts0);
                    948:                ts = &ts0;
                    949:        }
                    950:
                    951:        lsigmask = SCARG(uap, sigset);
                    952:        if (lsigmask) {
                    953:                if ((error = copyin(lsigmask, &lsigmask0, sizeof(lsigmask0))))
                    954:                        return error;
                    955:                linux_to_native_sigset(&sigmask0, &lsigmask0);
                    956:                sigmask = &sigmask0;
                    957:        }
                    958:
                    959:        return pollcommon(retval, SCARG(uap, fds), SCARG(uap, nfds),
                    960:            ts, sigmask);
                    961: }
                    962:
1.1       fvdl      963: /*
1.6       fvdl      964:  * Set the 'personality' (emulation mode) for the current process. Only
                    965:  * accept the Linux personality here (0). This call is needed because
                    966:  * the Linux ELF crt0 issues it in an ugly kludge to make sure that
                    967:  * ELF binaries run in Linux mode, not SVR4 mode.
                    968:  */
                    969: int
1.190     dsl       970: linux_sys_personality(struct lwp *l, const struct linux_sys_personality_args *uap, register_t *retval)
1.20      thorpej   971: {
1.190     dsl       972:        /* {
1.212     njoly     973:                syscallarg(unsigned long) per;
1.190     dsl       974:        } */
1.218     chs       975:        struct linux_emuldata *led;
                    976:        int per;
1.20      thorpej   977:
1.218     chs       978:        per = SCARG(uap, per);
                    979:        led = l->l_emuldata;
                    980:        if (per == LINUX_PER_QUERY) {
                    981:                retval[0] = led->led_personality;
                    982:                return 0;
                    983:        }
                    984:
                    985:        switch (per & LINUX_PER_MASK) {
1.205     njoly     986:        case LINUX_PER_LINUX:
1.218     chs       987:        case LINUX_PER_LINUX32:
                    988:                led->led_personality = per;
1.205     njoly     989:                break;
1.218     chs       990:
1.205     njoly     991:        default:
1.6       fvdl      992:                return EINVAL;
1.205     njoly     993:        }
                    994:
1.218     chs       995:        retval[0] = per;
1.1       fvdl      996:        return 0;
1.18      fvdl      997: }
1.81      fvdl      998:
1.63      abs       999: /*
1.64      abs      1000:  * We have nonexistent fsuid equal to uid.
                   1001:  * If modification is requested, refuse.
1.63      abs      1002:  */
                   1003: int
1.190     dsl      1004: linux_sys_setfsuid(struct lwp *l, const struct linux_sys_setfsuid_args *uap, register_t *retval)
1.63      abs      1005: {
1.190     dsl      1006:         /* {
1.63      abs      1007:                 syscallarg(uid_t) uid;
1.190     dsl      1008:         } */
1.63      abs      1009:         uid_t uid;
                   1010:
                   1011:         uid = SCARG(uap, uid);
1.158     ad       1012:         if (kauth_cred_getuid(l->l_cred) != uid)
1.190     dsl      1013:                 return sys_nosys(l, uap, retval);
1.191     njoly    1014:
                   1015:         *retval = uid;
                   1016:         return 0;
1.63      abs      1017: }
                   1018:
                   1019: int
1.191     njoly    1020: linux_sys_setfsgid(struct lwp *l, const struct linux_sys_setfsgid_args *uap, register_t *retval)
1.63      abs      1021: {
1.191     njoly    1022:        /* {
                   1023:                syscallarg(gid_t) gid;
                   1024:        } */
                   1025:        gid_t gid;
                   1026:
                   1027:        gid = SCARG(uap, gid);
                   1028:        if (kauth_cred_getgid(l->l_cred) != gid)
                   1029:                return sys_nosys(l, uap, retval);
                   1030:
                   1031:        *retval = gid;
                   1032:        return 0;
1.27      fvdl     1033: }
                   1034:
                   1035: int
1.190     dsl      1036: linux_sys_setresuid(struct lwp *l, const struct linux_sys_setresuid_args *uap, register_t *retval)
1.57      thorpej  1037: {
1.190     dsl      1038:        /* {
1.57      thorpej  1039:                syscallarg(uid_t) ruid;
                   1040:                syscallarg(uid_t) euid;
                   1041:                syscallarg(uid_t) suid;
1.190     dsl      1042:        } */
1.57      thorpej  1043:
                   1044:        /*
                   1045:         * Note: These checks are a little different than the NetBSD
                   1046:         * setreuid(2) call performs.  This precisely follows the
                   1047:         * behavior of the Linux kernel.
                   1048:         */
                   1049:
1.117     dsl      1050:        return do_setresuid(l, SCARG(uap, ruid), SCARG(uap, euid),
                   1051:                            SCARG(uap, suid),
                   1052:                            ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S |
                   1053:                            ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
                   1054:                            ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S );
1.57      thorpej  1055: }
                   1056:
                   1057: int
1.190     dsl      1058: linux_sys_getresuid(struct lwp *l, const struct linux_sys_getresuid_args *uap, register_t *retval)
1.57      thorpej  1059: {
1.190     dsl      1060:        /* {
1.57      thorpej  1061:                syscallarg(uid_t *) ruid;
                   1062:                syscallarg(uid_t *) euid;
                   1063:                syscallarg(uid_t *) suid;
1.190     dsl      1064:        } */
1.158     ad       1065:        kauth_cred_t pc = l->l_cred;
1.57      thorpej  1066:        int error;
1.154     elad     1067:        uid_t uid;
1.57      thorpej  1068:
                   1069:        /*
                   1070:         * Linux copies these values out to userspace like so:
                   1071:         *
                   1072:         *      1. Copy out ruid.
                   1073:         *      2. If that succeeds, copy out euid.
                   1074:         *      3. If both of those succeed, copy out suid.
                   1075:         */
1.154     elad     1076:        uid = kauth_cred_getuid(pc);
                   1077:        if ((error = copyout(&uid, SCARG(uap, ruid), sizeof(uid_t))) != 0)
1.57      thorpej  1078:                return (error);
                   1079:
1.154     elad     1080:        uid = kauth_cred_geteuid(pc);
                   1081:        if ((error = copyout(&uid, SCARG(uap, euid), sizeof(uid_t))) != 0)
1.57      thorpej  1082:                return (error);
                   1083:
1.154     elad     1084:        uid = kauth_cred_getsvuid(pc);
                   1085:
                   1086:        return (copyout(&uid, SCARG(uap, suid), sizeof(uid_t)));
1.78      fvdl     1087: }
1.62      tron     1088:
                   1089: int
1.190     dsl      1090: linux_sys_ptrace(struct lwp *l, const struct linux_sys_ptrace_args *uap, register_t *retval)
1.62      tron     1091: {
1.190     dsl      1092:        /* {
1.88      manu     1093:                i386, m68k, powerpc: T=int
1.137     manu     1094:                alpha, amd64: T=long
1.66      erh      1095:                syscallarg(T) request;
                   1096:                syscallarg(T) pid;
                   1097:                syscallarg(T) addr;
                   1098:                syscallarg(T) data;
1.190     dsl      1099:        } */
1.73      jdolecek 1100:        const int *ptr;
                   1101:        int request;
1.89      manu     1102:        int error;
1.62      tron     1103:
                   1104:        ptr = linux_ptrace_request_map;
                   1105:        request = SCARG(uap, request);
                   1106:        while (*ptr != -1)
                   1107:                if (*ptr++ == request) {
                   1108:                        struct sys_ptrace_args pta;
                   1109:
                   1110:                        SCARG(&pta, req) = *ptr;
                   1111:                        SCARG(&pta, pid) = SCARG(uap, pid);
1.167     christos 1112:                        SCARG(&pta, addr) = (void *)SCARG(uap, addr);
1.62      tron     1113:                        SCARG(&pta, data) = SCARG(uap, data);
                   1114:
1.73      jdolecek 1115:                        /*
                   1116:                         * Linux ptrace(PTRACE_CONT, pid, 0, 0) means actually
1.90      jdolecek 1117:                         * to continue where the process left off previously.
1.202     ad       1118:                         * The same thing is achieved by addr == (void *) 1
1.90      jdolecek 1119:                         * on NetBSD, so rewrite 'addr' appropriately.
1.73      jdolecek 1120:                         */
                   1121:                        if (request == LINUX_PTRACE_CONT && SCARG(uap, addr)==0)
1.167     christos 1122:                                SCARG(&pta, addr) = (void *) 1;
1.135     perry    1123:
1.202     ad       1124:                        error = sysent[SYS_ptrace].sy_call(l, &pta, retval);
1.135     perry    1125:                        if (error)
1.92      manu     1126:                                return error;
                   1127:                        switch (request) {
                   1128:                        case LINUX_PTRACE_PEEKTEXT:
                   1129:                        case LINUX_PTRACE_PEEKDATA:
1.135     perry    1130:                                error = copyout (retval,
1.167     christos 1131:                                    (void *)SCARG(uap, data),
1.137     manu     1132:                                    sizeof *retval);
1.92      manu     1133:                                *retval = SCARG(uap, data);
                   1134:                                break;
1.135     perry    1135:                        default:
1.92      manu     1136:                                break;
                   1137:                        }
1.89      manu     1138:                        return error;
1.62      tron     1139:                }
                   1140:                else
                   1141:                        ptr++;
                   1142:
1.116     thorpej  1143:        return LINUX_SYS_PTRACE_ARCH(l, uap, retval);
1.1       fvdl     1144: }
1.67      erh      1145:
                   1146: int
1.190     dsl      1147: linux_sys_reboot(struct lwp *l, const struct linux_sys_reboot_args *uap, register_t *retval)
1.67      erh      1148: {
1.190     dsl      1149:        /* {
1.67      erh      1150:                syscallarg(int) magic1;
                   1151:                syscallarg(int) magic2;
                   1152:                syscallarg(int) cmd;
                   1153:                syscallarg(void *) arg;
1.190     dsl      1154:        } */
1.67      erh      1155:        struct sys_reboot_args /* {
                   1156:                syscallarg(int) opt;
                   1157:                syscallarg(char *) bootstr;
                   1158:        } */ sra;
                   1159:        int error;
                   1160:
1.164     elad     1161:        if ((error = kauth_authorize_system(l->l_cred,
                   1162:            KAUTH_SYSTEM_REBOOT, 0, NULL, NULL, NULL)) != 0)
1.67      erh      1163:                return(error);
                   1164:
                   1165:        if (SCARG(uap, magic1) != LINUX_REBOOT_MAGIC1)
                   1166:                return(EINVAL);
                   1167:        if (SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2 &&
                   1168:            SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2A &&
                   1169:            SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2B)
                   1170:                return(EINVAL);
                   1171:
1.200     gmcgarry 1172:        switch ((unsigned long)SCARG(uap, cmd)) {
1.67      erh      1173:        case LINUX_REBOOT_CMD_RESTART:
                   1174:                SCARG(&sra, opt) = RB_AUTOBOOT;
                   1175:                break;
                   1176:        case LINUX_REBOOT_CMD_HALT:
                   1177:                SCARG(&sra, opt) = RB_HALT;
                   1178:                break;
                   1179:        case LINUX_REBOOT_CMD_POWER_OFF:
                   1180:                SCARG(&sra, opt) = RB_HALT|RB_POWERDOWN;
                   1181:                break;
                   1182:        case LINUX_REBOOT_CMD_RESTART2:
                   1183:                /* Reboot with an argument. */
                   1184:                SCARG(&sra, opt) = RB_AUTOBOOT|RB_STRING;
                   1185:                SCARG(&sra, bootstr) = SCARG(uap, arg);
                   1186:                break;
                   1187:        case LINUX_REBOOT_CMD_CAD_ON:
                   1188:                return(EINVAL); /* We don't implement ctrl-alt-delete */
                   1189:        case LINUX_REBOOT_CMD_CAD_OFF:
                   1190:                return(0);
                   1191:        default:
                   1192:                return(EINVAL);
                   1193:        }
                   1194:
1.116     thorpej  1195:        return(sys_reboot(l, &sra, retval));
1.75      jdolecek 1196: }
                   1197:
                   1198: /*
                   1199:  * Copy of compat_12_sys_swapon().
                   1200:  */
                   1201: int
1.190     dsl      1202: linux_sys_swapon(struct lwp *l, const struct linux_sys_swapon_args *uap, register_t *retval)
1.75      jdolecek 1203: {
1.190     dsl      1204:        /* {
                   1205:                syscallarg(const char *) name;
                   1206:        } */
1.75      jdolecek 1207:        struct sys_swapctl_args ua;
                   1208:
                   1209:        SCARG(&ua, cmd) = SWAP_ON;
1.139     drochner 1210:        SCARG(&ua, arg) = (void *)__UNCONST(SCARG(uap, name));
1.75      jdolecek 1211:        SCARG(&ua, misc) = 0;   /* priority */
1.116     thorpej  1212:        return (sys_swapctl(l, &ua, retval));
1.76      jdolecek 1213: }
                   1214:
                   1215: /*
                   1216:  * Stop swapping to the file or block device specified by path.
                   1217:  */
                   1218: int
1.190     dsl      1219: linux_sys_swapoff(struct lwp *l, const struct linux_sys_swapoff_args *uap, register_t *retval)
1.76      jdolecek 1220: {
1.190     dsl      1221:        /* {
                   1222:                syscallarg(const char *) path;
                   1223:        } */
1.76      jdolecek 1224:        struct sys_swapctl_args ua;
                   1225:
                   1226:        SCARG(&ua, cmd) = SWAP_OFF;
1.138     christos 1227:        SCARG(&ua, arg) = __UNCONST(SCARG(uap, path)); /*XXXUNCONST*/
1.116     thorpej  1228:        return (sys_swapctl(l, &ua, retval));
1.75      jdolecek 1229: }
                   1230:
                   1231: /*
                   1232:  * Copy of compat_09_sys_setdomainname()
                   1233:  */
                   1234: /* ARGSUSED */
                   1235: int
1.190     dsl      1236: linux_sys_setdomainname(struct lwp *l, const struct linux_sys_setdomainname_args *uap, register_t *retval)
1.75      jdolecek 1237: {
1.190     dsl      1238:        /* {
1.75      jdolecek 1239:                syscallarg(char *) domainname;
                   1240:                syscallarg(int) len;
1.190     dsl      1241:        } */
1.122     atatat   1242:        int name[2];
1.75      jdolecek 1243:
1.122     atatat   1244:        name[0] = CTL_KERN;
                   1245:        name[1] = KERN_DOMAINNAME;
                   1246:        return (old_sysctl(&name[0], 2, 0, 0, SCARG(uap, domainname),
                   1247:                            SCARG(uap, len), l));
1.77      augustss 1248: }
                   1249:
                   1250: /*
                   1251:  * sysinfo()
                   1252:  */
                   1253: /* ARGSUSED */
                   1254: int
1.190     dsl      1255: linux_sys_sysinfo(struct lwp *l, const struct linux_sys_sysinfo_args *uap, register_t *retval)
1.77      augustss 1256: {
1.190     dsl      1257:        /* {
1.77      augustss 1258:                syscallarg(struct linux_sysinfo *) arg;
1.190     dsl      1259:        } */
1.77      augustss 1260:        struct linux_sysinfo si;
                   1261:        struct loadavg *la;
                   1262:
1.155     kardel   1263:        si.uptime = time_uptime;
1.77      augustss 1264:        la = &averunnable;
                   1265:        si.loads[0] = la->ldavg[0] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
                   1266:        si.loads[1] = la->ldavg[1] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
                   1267:        si.loads[2] = la->ldavg[2] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
1.162     manu     1268:        si.totalram = ctob((u_long)physmem);
                   1269:        si.freeram = (u_long)uvmexp.free * uvmexp.pagesize;
1.77      augustss 1270:        si.sharedram = 0;       /* XXX */
1.162     manu     1271:        si.bufferram = (u_long)uvmexp.filepages * uvmexp.pagesize;
                   1272:        si.totalswap = (u_long)uvmexp.swpages * uvmexp.pagesize;
                   1273:        si.freeswap =
                   1274:            (u_long)(uvmexp.swpages - uvmexp.swpginuse) * uvmexp.pagesize;
1.77      augustss 1275:        si.procs = nprocs;
                   1276:
                   1277:        /* The following are only present in newer Linux kernels. */
                   1278:        si.totalbig = 0;
                   1279:        si.freebig = 0;
                   1280:        si.mem_unit = 1;
                   1281:
                   1282:        return (copyout(&si, SCARG(uap, arg), sizeof si));
1.97      christos 1283: }
                   1284:
                   1285: int
1.190     dsl      1286: linux_sys_getrlimit(struct lwp *l, const struct linux_sys_getrlimit_args *uap, register_t *retval)
1.97      christos 1287: {
1.190     dsl      1288:        /* {
1.97      christos 1289:                syscallarg(int) which;
1.150     manu     1290: # ifdef LINUX_LARGEFILE64
1.144     manu     1291:                syscallarg(struct rlimit *) rlp;
1.150     manu     1292: # else
1.97      christos 1293:                syscallarg(struct orlimit *) rlp;
1.150     manu     1294: # endif
1.190     dsl      1295:        } */
1.150     manu     1296: # ifdef LINUX_LARGEFILE64
1.144     manu     1297:        struct rlimit orl;
1.150     manu     1298: # else
1.97      christos 1299:        struct orlimit orl;
1.150     manu     1300: # endif
1.176     dsl      1301:        int which;
                   1302:
                   1303:        which = linux_to_bsd_limit(SCARG(uap, which));
                   1304:        if (which < 0)
                   1305:                return -which;
1.97      christos 1306:
1.176     dsl      1307:        bsd_to_linux_rlimit(&orl, &l->l_proc->p_rlimit[which]);
1.146     rpaulo   1308:
1.97      christos 1309:        return copyout(&orl, SCARG(uap, rlp), sizeof(orl));
                   1310: }
                   1311:
                   1312: int
1.190     dsl      1313: linux_sys_setrlimit(struct lwp *l, const struct linux_sys_setrlimit_args *uap, register_t *retval)
1.97      christos 1314: {
1.190     dsl      1315:        /* {
1.97      christos 1316:                syscallarg(int) which;
1.150     manu     1317: # ifdef LINUX_LARGEFILE64
1.144     manu     1318:                syscallarg(struct rlimit *) rlp;
1.150     manu     1319: # else
1.97      christos 1320:                syscallarg(struct orlimit *) rlp;
1.150     manu     1321: # endif
1.190     dsl      1322:        } */
1.97      christos 1323:        struct rlimit rl;
1.150     manu     1324: # ifdef LINUX_LARGEFILE64
1.144     manu     1325:        struct rlimit orl;
1.150     manu     1326: # else
1.97      christos 1327:        struct orlimit orl;
1.150     manu     1328: # endif
1.97      christos 1329:        int error;
1.176     dsl      1330:        int which;
1.97      christos 1331:
                   1332:        if ((error = copyin(SCARG(uap, rlp), &orl, sizeof(orl))) != 0)
                   1333:                return error;
1.176     dsl      1334:
                   1335:        which = linux_to_bsd_limit(SCARG(uap, which));
                   1336:        if (which < 0)
                   1337:                return -which;
                   1338:
1.97      christos 1339:        linux_to_bsd_rlimit(&rl, &orl);
1.176     dsl      1340:        return dosetrlimit(l, l->l_proc, which, &rl);
1.97      christos 1341: }
                   1342:
1.150     manu     1343: # if !defined(__mips__) && !defined(__amd64__)
1.98      rafal    1344: /* XXX: this doesn't look 100% common, at least mips doesn't have it */
1.97      christos 1345: int
1.190     dsl      1346: linux_sys_ugetrlimit(struct lwp *l, const struct linux_sys_ugetrlimit_args *uap, register_t *retval)
1.97      christos 1347: {
1.190     dsl      1348:        return linux_sys_getrlimit(l, (const void *)uap, retval);
1.87      jdolecek 1349: }
1.150     manu     1350: # endif
1.87      jdolecek 1351:
                   1352: /*
                   1353:  * This gets called for unsupported syscalls. The difference to sys_nosys()
                   1354:  * is that process does not get SIGSYS, the call just returns with ENOSYS.
                   1355:  * This is the way Linux does it and glibc depends on this behaviour.
                   1356:  */
                   1357: int
1.190     dsl      1358: linux_sys_nosys(struct lwp *l, const void *v, register_t *retval)
1.87      jdolecek 1359: {
                   1360:        return (ENOSYS);
1.67      erh      1361: }
1.150     manu     1362:
1.156     christos 1363: int
1.190     dsl      1364: linux_sys_getpriority(struct lwp *l, const struct linux_sys_getpriority_args *uap, register_t *retval)
1.156     christos 1365: {
1.190     dsl      1366:         /* {
1.156     christos 1367:                 syscallarg(int) which;
                   1368:                 syscallarg(int) who;
1.190     dsl      1369:         } */
1.156     christos 1370:         struct sys_getpriority_args bsa;
                   1371:         int error;
                   1372:
                   1373:         SCARG(&bsa, which) = SCARG(uap, which);
                   1374:         SCARG(&bsa, who) = SCARG(uap, who);
                   1375:
                   1376:         if ((error = sys_getpriority(l, &bsa, retval)))
                   1377:                 return error;
                   1378:
1.157     christos 1379:         *retval = NZERO - *retval;
1.156     christos 1380:
                   1381:         return 0;
                   1382: }
1.221     pooka    1383:
                   1384: int
                   1385: linux_sys_utimes(struct lwp *l, const struct linux_sys_utimes_args *uap, register_t *retval)
                   1386: {
                   1387:        /* {
                   1388:                syscallarg(const char *) path;
                   1389:                syscallarg(const struct linux_timeval) *times;
                   1390:        } */
                   1391:        struct linux_timeval ltv[2];
                   1392:        struct timeval tv[2];
                   1393:        struct timeval *tptr = NULL;
                   1394:        int error;
                   1395:
                   1396:        if (SCARG(uap, times)) {
                   1397:                if ((error = copyin(SCARG(uap, times), &ltv, sizeof(ltv))))
                   1398:                        return error;
                   1399:
                   1400:                tv[0].tv_sec = ltv[0].tv_sec;
                   1401:                tv[0].tv_usec = ltv[0].tv_usec;
                   1402:                tv[1].tv_sec = ltv[1].tv_sec;
                   1403:                tv[1].tv_usec = ltv[1].tv_usec;
                   1404:
                   1405:                tptr = tv;
                   1406:        }
                   1407:
                   1408:        return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW,
                   1409:            tptr, UIO_SYSSPACE);
                   1410: }
                   1411:
1.226   ! njoly    1412: int
        !          1413: linux_sys_utimensat(struct lwp *l, const struct linux_sys_utimensat_args *uap,
        !          1414:        register_t *retval)
        !          1415: {
        !          1416:        /* {
        !          1417:                syscallarg(int) fd;
        !          1418:                syscallarg(const char *) path;
        !          1419:                syscallarg(const struct linux_timespec *) times;
        !          1420:                syscallarg(int) flag;
        !          1421:        } */
        !          1422:        int follow, error;
        !          1423:        struct linux_timespec lts[2];
        !          1424:        struct timespec *tsp = NULL, ts[2];
        !          1425:
        !          1426:        follow = (SCARG(uap, flag) & LINUX_AT_SYMLINK_NOFOLLOW) ?
        !          1427:            NOFOLLOW : FOLLOW;
        !          1428:
        !          1429:        if (SCARG(uap, times)) {
        !          1430:                error = copyin(SCARG(uap, times), &lts, sizeof(lts));
        !          1431:                if (error != 0)
        !          1432:                        return error;
        !          1433:                linux_to_native_timespec(&ts[0], &lts[0]);
        !          1434:                linux_to_native_timespec(&ts[1], &lts[1]);
        !          1435:                tsp = ts;
        !          1436:        }
        !          1437:
        !          1438:        if (SCARG(uap, path) == NULL && SCARG(uap, fd) != AT_FDCWD) {
        !          1439:                file_t *fp;
        !          1440:
        !          1441:                /* fd_getvnode() will use the descriptor for us */
        !          1442:                if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
        !          1443:                        return error;
        !          1444:                error = do_sys_utimensat(l, AT_FDCWD, fp->f_data, NULL, 0,
        !          1445:                    tsp, UIO_SYSSPACE);
        !          1446:                fd_putfile(SCARG(uap, fd));
        !          1447:                return error;
        !          1448:        }
        !          1449:
        !          1450:        return do_sys_utimensat(l, SCARG(uap, fd), NULL,
        !          1451:            SCARG(uap, path), follow, tsp, UIO_SYSSPACE);
        !          1452:
        !          1453: }
        !          1454:
1.221     pooka    1455: int linux_sys_lutimes(struct lwp *, const struct linux_sys_utimes_args *, register_t *);
                   1456: int
                   1457: linux_sys_lutimes(struct lwp *l, const struct linux_sys_utimes_args *uap, register_t *retval)
                   1458: {
                   1459:        /* {
                   1460:                syscallarg(const char *) path;
                   1461:                syscallarg(const struct linux_timeval) *times;
                   1462:        } */
                   1463:        struct linux_timeval ltv[2];
                   1464:        struct timeval tv[2];
                   1465:        struct timeval *tptr = NULL;
                   1466:        int error;
                   1467:
                   1468:        if (SCARG(uap, times)) {
                   1469:                if ((error = copyin(SCARG(uap, times), &ltv, sizeof(ltv))))
                   1470:                        return error;
                   1471:
                   1472:                tv[0].tv_sec = ltv[0].tv_sec;
                   1473:                tv[0].tv_usec = ltv[0].tv_usec;
                   1474:                tv[1].tv_sec = ltv[1].tv_sec;
                   1475:                tv[1].tv_usec = ltv[1].tv_usec;
                   1476:
                   1477:                tptr = tv;
                   1478:        }
                   1479:
                   1480:        return do_sys_utimes(l, NULL, SCARG(uap, path), NOFOLLOW,
                   1481:            tptr, UIO_SYSSPACE);
                   1482: }
1.222     pooka    1483: #endif /* !COMPAT_LINUX32 */

CVSweb <webmaster@jp.NetBSD.org>