diff options
| author | 2016-03-02 15:41:47 +0000 | |
|---|---|---|
| committer | 2016-03-02 15:41:47 +0000 | |
| commit | 3ff801c032f3258b94ac6d01d574c0da4c0cc94a (patch) | |
| tree | e685de69d6a67343dc4896743c70fd8a77574cc1 /sys/compat/linux/linux_misc.c | |
| parent | Handle wcwidth() and mbtowc() failures in better style and drop (diff) | |
| download | wireguard-openbsd-3ff801c032f3258b94ac6d01d574c0da4c0cc94a.tar.xz wireguard-openbsd-3ff801c032f3258b94ac6d01d574c0da4c0cc94a.zip | |
remove the Linux emulation code, no longer referenced by anything
Diffstat (limited to 'sys/compat/linux/linux_misc.c')
| -rw-r--r-- | sys/compat/linux/linux_misc.c | 1720 |
1 files changed, 0 insertions, 1720 deletions
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c deleted file mode 100644 index a55274f1245..00000000000 --- a/sys/compat/linux/linux_misc.c +++ /dev/null @@ -1,1720 +0,0 @@ -/* $OpenBSD: linux_misc.c,v 1.95 2015/09/13 17:08:03 guenther Exp $ */ -/* $NetBSD: linux_misc.c,v 1.27 1996/05/20 01:59:21 fvdl Exp $ */ - -/*- - * Copyright (c) 1995, 1998, 1999 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Frank van der Linden and Eric Haszlakiewicz; by Jason R. Thorpe - * of the Numerical Aerospace Simulation Facility, NASA Ames Research Center. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Linux compatibility module. Try to deal with various Linux system calls. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/namei.h> -#include <sys/proc.h> -#include <sys/dirent.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <sys/filedesc.h> -#include <sys/ioctl.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/mman.h> -#include <sys/mount.h> -#include <sys/ptrace.h> -#include <sys/resource.h> -#include <sys/swap.h> -#include <sys/resourcevar.h> -#include <sys/signal.h> -#include <sys/signalvar.h> -#include <sys/socket.h> -#include <sys/sysctl.h> -#include <sys/time.h> -#include <sys/vnode.h> -#include <sys/uio.h> -#include <sys/wait.h> -#include <sys/utsname.h> -#include <sys/unistd.h> - -#include <sys/syscallargs.h> - -#include <uvm/uvm_extern.h> - -#include <compat/linux/linux_types.h> -#include <compat/linux/linux_time.h> -#include <compat/linux/linux_fcntl.h> -#include <compat/linux/linux_misc.h> -#include <compat/linux/linux_mmap.h> -#include <compat/linux/linux_sched.h> -#include <compat/linux/linux_signal.h> -#include <compat/linux/linux_syscallargs.h> -#include <compat/linux/linux_util.h> -#include <compat/linux/linux_dirent.h> -#include <compat/linux/linux_emuldata.h> - -#include <compat/common/compat_dir.h> - -/* linux_misc.c */ -void bsd_to_linux_statfs(const struct statfs *, struct linux_statfs *); -void bsd_to_linux_statfs64(const struct statfs *, struct linux_statfs64 *); -int linux_select1(struct proc *, register_t *, int, fd_set *, - fd_set *, fd_set *, struct linux_timeval *); -int getdents_common(struct proc *, void *, register_t *, int); -void linux_to_bsd_mmap_args(struct sys_mmap_args *, - const struct linux_sys_mmap2_args *); -void bsd_to_linux_rusage(struct linux_rusage *, const struct rusage *); -void bsd_to_linux_wstat(int *); - - -/* - * The information on a terminated (or stopped) process needs - * to be converted in order for Linux binaries to get a valid signal - * number out of it. - */ -void -bsd_to_linux_wstat(status) - int *status; -{ - - if (WIFSIGNALED(*status)) - *status = (*status & ~0177) | - bsd_to_linux_sig[WTERMSIG(*status)]; - else if (WIFSTOPPED(*status)) - *status = (*status & ~0xff00) | - (bsd_to_linux_sig[WSTOPSIG(*status)] << 8); -} - -/* - * Convert an rusage to Linux format: small time_t in the timevals - */ -void -bsd_to_linux_rusage(struct linux_rusage *lrup, const struct rusage *rup) -{ - bsd_to_linux_timeval(&lrup->ru_utime, &rup->ru_utime); - bsd_to_linux_timeval(&lrup->ru_utime, &rup->ru_utime); - memcpy(&lrup->ru_maxrss, &rup->ru_maxrss, - offsetof(struct rusage, ru_nivcsw) - - offsetof(struct rusage, ru_maxrss) + - sizeof(lrup->ru_nivcsw)); -} - -/* - * waitpid(2). Just forward on to linux_sys_wait4 with a NULL rusage. - */ -int -linux_sys_waitpid(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_waitpid_args /* { - syscallarg(int) pid; - syscallarg(int *) status; - syscallarg(int) options; - } */ *uap = v; - struct sys_wait4_args linux_w4a; - - SCARG(&linux_w4a, pid) = SCARG(uap, pid); - SCARG(&linux_w4a, status) = SCARG(uap, status); - SCARG(&linux_w4a, options) = SCARG(uap, options); - SCARG(&linux_w4a, rusage) = NULL; - - return (linux_sys_wait4(p, &linux_w4a, retval)); -} - -/* - * wait4(2): handle conversion of the options on entry and status and rusage - * on return. - */ -int -linux_sys_wait4(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_wait4_args /* { - syscallarg(int) pid; - syscallarg(int *) status; - syscallarg(int) options; - syscallarg(struct linux_rusage *) rusage; - } */ *uap = v; - struct rusage ru; - int error, status, linux_options, options; - - linux_options = SCARG(uap, options); - options = 0; - if (linux_options & ~(LINUX_WAIT4_WNOHANG|LINUX_WAIT4_WUNTRACED)) - return (EINVAL); - - if (linux_options & LINUX_WAIT4_WNOHANG) - options |= WNOHANG; - if (linux_options & LINUX_WAIT4_WUNTRACED) - options |= WUNTRACED; - - if ((error = dowait4(p, SCARG(uap, pid), - SCARG(uap, status) ? &status : NULL, options, - SCARG(uap, rusage) ? &ru : NULL, retval))) - return error; - - atomic_clearbits_int(&p->p_siglist, sigmask(SIGCHLD)); - - if (SCARG(uap, rusage) != NULL) { - struct linux_rusage lru; - - bsd_to_linux_rusage(&lru, &ru); - if ((error = copyout(&lru, SCARG(uap, rusage), sizeof lru))) - return error; - } - if (SCARG(uap, status) != NULL) { - bsd_to_linux_wstat(&status); - return copyout(&status, SCARG(uap, status), sizeof status); - } - - return 0; -} - -/* - * getrusage(2): convert rusage on return - */ -int -linux_sys_getrusage(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_getrusage_args /* { - syscallarg(int) who; - syscallarg(struct linux_rusage *) rusage; - } */ *uap = v; - struct rusage ru; - int error; - - error = dogetrusage(p, SCARG(uap, who), &ru); - if (error == 0) { - struct linux_rusage lru; - - bsd_to_linux_rusage(&lru, &ru); - error = copyout(&lru, SCARG(uap, rusage), sizeof lru); - } - return error; -} - - -int -linux_sys_setresgid16(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_setresgid16_args /* { - syscallarg(u_int16_t) rgid; - syscallarg(u_int16_t) egid; - syscallarg(u_int16_t) sgid; - } */ *uap = v; - struct sys_setresgid_args nuap; - u_int16_t rgid, egid, sgid; - - rgid = SCARG(uap, rgid); - SCARG(&nuap, rgid) = (rgid == (u_int16_t)-1) ? (gid_t)-1 : rgid; - egid = SCARG(uap, egid); - SCARG(&nuap, egid) = (egid == (u_int16_t)-1) ? (gid_t)-1 : egid; - sgid = SCARG(uap, sgid); - SCARG(&nuap, sgid) = (sgid == (u_int16_t)-1) ? (gid_t)-1 : sgid; - - return sys_setresgid(p, &nuap, retval); -} - -int -linux_sys_getresgid16(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_getresgid16_args /* { - syscallarg(u_int16_t *) rgid; - syscallarg(u_int16_t *) egid; - syscallarg(u_int16_t *) sgid; - } */ *uap = v; - struct sys_getresgid_args nuap; - - SCARG(&nuap, rgid) = (gid_t *)SCARG(uap, rgid); - SCARG(&nuap, egid) = (gid_t *)SCARG(uap, egid); - SCARG(&nuap, sgid) = (gid_t *)SCARG(uap, sgid); - - return sys_getresgid(p, &nuap, retval); -} - -int -linux_sys_setresuid16(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_setresuid16_args /* { - syscallarg(u_int16_t) ruid; - syscallarg(u_int16_t) euid; - syscallarg(u_int16_t) suid; - } */ *uap = v; - struct sys_setresuid_args nuap; - u_int16_t ruid, euid, suid; - - ruid = SCARG(uap, ruid); - SCARG(&nuap, ruid) = (ruid == (u_int16_t)-1) ? (uid_t)-1 : ruid; - euid = SCARG(uap, euid); - SCARG(&nuap, euid) = (euid == (u_int16_t)-1) ? (uid_t)-1 : euid; - suid = SCARG(uap, suid); - SCARG(&nuap, suid) = (suid == (u_int16_t)-1) ? (uid_t)-1 : suid; - - return sys_setresuid(p, &nuap, retval); -} - -int -linux_sys_getresuid16(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_getresuid16_args /* { - syscallarg(u_int16_t *) ruid; - syscallarg(u_int16_t *) euid; - syscallarg(u_int16_t *) suid; - } */ *uap = v; - struct sys_getresuid_args nuap; - - SCARG(&nuap, ruid) = (uid_t *)SCARG(uap, ruid); - SCARG(&nuap, euid) = (uid_t *)SCARG(uap, euid); - SCARG(&nuap, suid) = (uid_t *)SCARG(uap, suid); - - return sys_getresuid(p, &nuap, retval); -} - -/* - * This is the old brk(2) call. I don't think anything in the Linux - * world uses this anymore - */ -int -linux_sys_break(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ -#if 0 - struct linux_sys_brk_args /* { - syscallarg(char *) nsize; - } */ *uap = v; -#endif - - return ENOSYS; -} - -/* - * Linux brk(2). The check if the new address is >= the old one is - * done in the kernel in Linux. OpenBSD does it in the library. - */ -int -linux_sys_brk(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_brk_args /* { - syscallarg(char *) nsize; - } */ *uap = v; - char *nbrk = SCARG(uap, nsize); - struct sys_obreak_args oba; - struct vmspace *vm = p->p_vmspace; - struct linux_emuldata *ed = (struct linux_emuldata*)p->p_emuldata; - - SCARG(&oba, nsize) = nbrk; - - if ((caddr_t) nbrk > vm->vm_daddr && sys_obreak(p, &oba, retval) == 0) - ed->p_break = (char*)nbrk; - else - nbrk = ed->p_break; - - retval[0] = (register_t)nbrk; - - return 0; -} - -/* - * I wonder why Linux has gettimeofday() _and_ time().. Still, we - * need to deal with it. - */ -int -linux_sys_time(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_time_args /* { - linux_time_t *t; - } */ *uap = v; - struct timeval atv; - linux_time_t tt; - int error; - - microtime(&atv); - - if (atv.tv_sec > LINUX_TIME_MAX) - return (EOVERFLOW); - tt = (linux_time_t)atv.tv_sec; - if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt))) - return error; - - retval[0] = tt; - return 0; -} - -/* - * Convert BSD statfs structure to Linux statfs structure. - * The Linux structure has less fields, and it also wants - * the length of a name in a dir entry in a field, which - * we fake (probably the wrong way). - */ -void -bsd_to_linux_statfs(const struct statfs *bsp, struct linux_statfs *lsp) -{ - - /* - * Convert BSD filesystem names to Linux filesystem type numbers - * where possible. Linux statfs uses a value of -1 to indicate - * an unsupported field. - */ - if (!strcmp(bsp->f_fstypename, MOUNT_FFS) || - !strcmp(bsp->f_fstypename, MOUNT_MFS)) - lsp->l_ftype = LINUX_FSTYPE_FFS; - else if (!strcmp(bsp->f_fstypename, MOUNT_NFS)) - lsp->l_ftype = LINUX_FSTYPE_NFS; - else if (!strcmp(bsp->f_fstypename, MOUNT_MSDOS)) - lsp->l_ftype = LINUX_FSTYPE_MSDOS; - else if (!strcmp(bsp->f_fstypename, MOUNT_EXT2FS)) - lsp->l_ftype = LINUX_FSTYPE_EXT2FS; - else if (!strcmp(bsp->f_fstypename, MOUNT_CD9660)) - lsp->l_ftype = LINUX_FSTYPE_CD9660; - else if (!strcmp(bsp->f_fstypename, MOUNT_NCPFS)) - lsp->l_ftype = LINUX_FSTYPE_NCPFS; - else if (!strcmp(bsp->f_fstypename, MOUNT_NTFS)) - lsp->l_ftype = LINUX_FSTYPE_NTFS; - else if (!strcmp(bsp->f_fstypename, MOUNT_UDF)) - lsp->l_ftype = LINUX_FSTYPE_UDF; - else if (!strcmp(bsp->f_fstypename, MOUNT_AFS)) - lsp->l_ftype = LINUX_FSTYPE_AFS; - else - lsp->l_ftype = -1; - - lsp->l_fbsize = bsp->f_bsize; - lsp->l_fblocks = bsp->f_blocks; - lsp->l_fbfree = bsp->f_bfree; - lsp->l_fbavail = bsp->f_bavail; - lsp->l_ffiles = bsp->f_files; - lsp->l_fffree = bsp->f_ffree; - lsp->l_ffsid.val[0] = bsp->f_fsid.val[0]; - lsp->l_ffsid.val[1] = bsp->f_fsid.val[1]; - lsp->l_fnamelen = MAXNAMLEN; /* XXX */ -} - -/* - * Implement the fs stat functions. Straightforward. - */ -int -linux_sys_statfs(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_statfs_args /* { - syscallarg(char *) path; - syscallarg(struct linux_statfs *) sp; - } */ *uap = v; - struct statfs btmp, *bsp; - struct linux_statfs ltmp; - struct sys_statfs_args bsa; - caddr_t sg; - int error; - - sg = stackgap_init(p); - bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs)); - - LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); - - SCARG(&bsa, path) = SCARG(uap, path); - SCARG(&bsa, buf) = bsp; - - if ((error = sys_statfs(p, &bsa, retval))) - return error; - - if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp))) - return error; - - bsd_to_linux_statfs(&btmp, <mp); - - return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp); -} - -void -bsd_to_linux_statfs64(const struct statfs *bsp, struct linux_statfs64 *lsp) -{ - - /* - * Convert BSD filesystem names to Linux filesystem type numbers - * where possible. Linux statfs uses a value of -1 to indicate - * an unsupported field. - */ - if (!strcmp(bsp->f_fstypename, MOUNT_FFS) || - !strcmp(bsp->f_fstypename, MOUNT_MFS)) - lsp->l_ftype = LINUX_FSTYPE_FFS; - else if (!strcmp(bsp->f_fstypename, MOUNT_NFS)) - lsp->l_ftype = LINUX_FSTYPE_NFS; - else if (!strcmp(bsp->f_fstypename, MOUNT_MSDOS)) - lsp->l_ftype = LINUX_FSTYPE_MSDOS; - else if (!strcmp(bsp->f_fstypename, MOUNT_EXT2FS)) - lsp->l_ftype = LINUX_FSTYPE_EXT2FS; - else if (!strcmp(bsp->f_fstypename, MOUNT_CD9660)) - lsp->l_ftype = LINUX_FSTYPE_CD9660; - else if (!strcmp(bsp->f_fstypename, MOUNT_NCPFS)) - lsp->l_ftype = LINUX_FSTYPE_NCPFS; - else if (!strcmp(bsp->f_fstypename, MOUNT_NTFS)) - lsp->l_ftype = LINUX_FSTYPE_NTFS; - else if (!strcmp(bsp->f_fstypename, MOUNT_UDF)) - lsp->l_ftype = LINUX_FSTYPE_UDF; - else if (!strcmp(bsp->f_fstypename, MOUNT_AFS)) - lsp->l_ftype = LINUX_FSTYPE_AFS; - else - lsp->l_ftype = -1; - - lsp->l_fbsize = bsp->f_bsize; - lsp->l_fblocks = bsp->f_blocks; - lsp->l_fbfree = bsp->f_bfree; - lsp->l_fbavail = bsp->f_bavail; - lsp->l_ffiles = bsp->f_files; - lsp->l_fffree = bsp->f_ffree; - lsp->l_ffsid.val[0] = bsp->f_fsid.val[0]; - lsp->l_ffsid.val[1] = bsp->f_fsid.val[1]; - lsp->l_fnamelen = MAXNAMLEN; /* XXX */ -} - -int -linux_sys_statfs64(struct proc *p, void *v, register_t *retval) -{ - struct linux_sys_statfs64_args /* { - syscallarg(char *) path; - syscallarg(struct linux_statfs64 *) sp; - } */ *uap = v; - struct statfs btmp, *bsp; - struct linux_statfs64 ltmp; - struct sys_statfs_args bsa; - caddr_t sg; - int error; - - sg = stackgap_init(p); - bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs)); - - LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); - - SCARG(&bsa, path) = SCARG(uap, path); - SCARG(&bsa, buf) = bsp; - - if ((error = sys_statfs(p, &bsa, retval))) - return error; - - if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp))) - return error; - - bsd_to_linux_statfs64(&btmp, <mp); - - return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp); -} - -int -linux_sys_fstatfs(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_fstatfs_args /* { - syscallarg(int) fd; - syscallarg(struct linux_statfs *) sp; - } */ *uap = v; - struct statfs btmp, *bsp; - struct linux_statfs ltmp; - struct sys_fstatfs_args bsa; - caddr_t sg; - int error; - - sg = stackgap_init(p); - bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs)); - - SCARG(&bsa, fd) = SCARG(uap, fd); - SCARG(&bsa, buf) = bsp; - - if ((error = sys_fstatfs(p, &bsa, retval))) - return error; - - if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp))) - return error; - - bsd_to_linux_statfs(&btmp, <mp); - - return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp); -} - -int -linux_sys_fstatfs64(struct proc *p, void *v, register_t *retval) -{ - struct linux_sys_fstatfs64_args /* { - syscallarg(int) fd; - syscallarg(struct linux_statfs64 *) sp; - } */ *uap = v; - struct statfs btmp, *bsp; - struct linux_statfs64 ltmp; - struct sys_fstatfs_args bsa; - caddr_t sg; - int error; - - sg = stackgap_init(p); - bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs)); - - SCARG(&bsa, fd) = SCARG(uap, fd); - SCARG(&bsa, buf) = bsp; - - if ((error = sys_fstatfs(p, &bsa, retval))) - return error; - - if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp))) - return error; - - bsd_to_linux_statfs64(&btmp, <mp); - - return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp); -} -/* - * uname(). Just copy the info from the various strings stored in the - * kernel, and put it in the Linux utsname structure. That structure - * is almost the same as the OpenBSD one, only it has fields 65 characters - * long, and an extra domainname field. - */ -int -linux_sys_uname(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_uname_args /* { - syscallarg(struct linux_utsname *) up; - } */ *uap = v; - extern char hostname[], machine[], domainname[]; - struct linux_utsname luts; - int len; - char *cp; - - strlcpy(luts.l_sysname, ostype, sizeof(luts.l_sysname)); - strlcpy(luts.l_nodename, hostname, sizeof(luts.l_nodename)); - strlcpy(luts.l_release, osrelease, sizeof(luts.l_release)); - strlcpy(luts.l_version, version, sizeof(luts.l_version)); - strlcpy(luts.l_machine, machine, sizeof(luts.l_machine)); - strlcpy(luts.l_domainname, domainname, sizeof(luts.l_domainname)); - - /* This part taken from the uname() in libc */ - len = sizeof(luts.l_version); - for (cp = luts.l_version; len--; ++cp) - if (*cp == '\n' || *cp == '\t') - *cp = (len > 1) ? ' ' : '\0'; - - return copyout(&luts, SCARG(uap, up), sizeof(luts)); -} - -int -linux_sys_olduname(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_uname_args /* { - syscallarg(struct linux_oldutsname *) up; - } */ *uap = v; - extern char hostname[], machine[]; - struct linux_oldutsname luts; - int len; - char *cp; - - strlcpy(luts.l_sysname, ostype, sizeof(luts.l_sysname)); - strlcpy(luts.l_nodename, hostname, sizeof(luts.l_nodename)); - strlcpy(luts.l_release, osrelease, sizeof(luts.l_release)); - strlcpy(luts.l_version, version, sizeof(luts.l_version)); - strlcpy(luts.l_machine, machine, sizeof(luts.l_machine)); - - /* This part taken from the uname() in libc */ - len = sizeof(luts.l_version); - for (cp = luts.l_version; len--; ++cp) - if (*cp == '\n' || *cp == '\t') - *cp = (len > 1) ? ' ' : '\0'; - - return copyout(&luts, SCARG(uap, up), sizeof(luts)); -} - -int -linux_sys_oldolduname(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_uname_args /* { - syscallarg(struct linux_oldoldutsname *) up; - } */ *uap = v; - extern char hostname[], machine[]; - struct linux_oldoldutsname luts; - int len; - char *cp; - - strlcpy(luts.l_sysname, ostype, sizeof(luts.l_sysname)); - strlcpy(luts.l_nodename, hostname, sizeof(luts.l_nodename)); - strlcpy(luts.l_release, osrelease, sizeof(luts.l_release)); - strlcpy(luts.l_version, version, sizeof(luts.l_version)); - strlcpy(luts.l_machine, machine, sizeof(luts.l_machine)); - - /* This part taken from the uname() in libc */ - len = sizeof(luts.l_version); - for (cp = luts.l_version; len--; ++cp) - if (*cp == '\n' || *cp == '\t') - *cp = (len > 1) ? ' ' : '\0'; - - return copyout(&luts, SCARG(uap, up), sizeof(luts)); -} - -int -linux_sys_sethostname(struct proc *p, void *v, register_t *retval) -{ - struct linux_sys_sethostname_args *uap = v; - int name; - int error; - - if ((error = suser(p, 0)) != 0) - return (error); - name = KERN_HOSTNAME; - return (kern_sysctl(&name, 1, 0, 0, SCARG(uap, hostname), - SCARG(uap, len), p)); -} - -/* - * Linux wants to pass everything to a syscall in registers. However, - * mmap() has 6 of them. Oops: out of register error. They just pass - * everything in a structure. - */ -int -linux_sys_mmap(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_mmap_args /* { - syscallarg(struct linux_mmap *) lmp; - } */ *uap = v; - struct linux_mmap lmap; - struct linux_sys_mmap2_args nlmap; - struct sys_mmap_args cma; - int error; - - if ((error = copyin(SCARG(uap, lmp), &lmap, sizeof lmap))) - return error; - - if (lmap.lm_pos & PAGE_MASK) - return EINVAL; - - /* repackage into something sane */ - SCARG(&nlmap,addr) = (unsigned long)lmap.lm_addr; - SCARG(&nlmap,len) = lmap.lm_len; - SCARG(&nlmap,prot) = lmap.lm_prot; - SCARG(&nlmap,flags) = lmap.lm_flags; - SCARG(&nlmap,fd) = lmap.lm_fd; - SCARG(&nlmap,offset) = (unsigned)lmap.lm_pos; - - linux_to_bsd_mmap_args(&cma, &nlmap); - SCARG(&cma, pos) = (off_t)SCARG(&nlmap, offset); - - return sys_mmap(p, &cma, retval); -} - -/* - * Guts of most architectures' mmap64() implementations. This shares - * its list of arguments with linux_sys_mmap(). - * - * The difference in linux_sys_mmap2() is that "offset" is actually - * (offset / pagesize), not an absolute byte count. This translation - * to pagesize offsets is done inside glibc between the mmap64() call - * point, and the actual syscall. - */ -int -linux_sys_mmap2(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_mmap2_args /* { - syscallarg(unsigned long) addr; - syscallarg(size_t) len; - syscallarg(int) prot; - syscallarg(int) flags; - syscallarg(int) fd; - syscallarg(linux_off_t) offset; - } */ *uap = v; - struct sys_mmap_args cma; - - linux_to_bsd_mmap_args(&cma, uap); - SCARG(&cma, pos) = ((off_t)SCARG(uap, offset)) << PAGE_SHIFT; - - return sys_mmap(p, &cma, retval); -} - -void -linux_to_bsd_mmap_args(cma, uap) - struct sys_mmap_args *cma; - const struct linux_sys_mmap2_args *uap; -{ - int flags = 0, fl = SCARG(uap, flags); - - flags |= cvtto_bsd_mask(fl, LINUX_MAP_SHARED, MAP_SHARED); - flags |= cvtto_bsd_mask(fl, LINUX_MAP_PRIVATE, MAP_PRIVATE); - flags |= cvtto_bsd_mask(fl, LINUX_MAP_FIXED, MAP_FIXED); - flags |= cvtto_bsd_mask(fl, LINUX_MAP_ANON, MAP_ANON); - /* XXX XAX ERH: Any other flags here? There are more defined... */ - - SCARG(cma, addr) = (void *)SCARG(uap, addr); - SCARG(cma, len) = SCARG(uap, len); - SCARG(cma, prot) = SCARG(uap, prot); - if (SCARG(cma, prot) & PROT_WRITE) /* XXX */ - SCARG(cma, prot) |= PROT_READ; - SCARG(cma, flags) = flags; - SCARG(cma, fd) = flags & MAP_ANON ? -1 : SCARG(uap, fd); - SCARG(cma, pad) = 0; -} - -int -linux_sys_mremap(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - - struct linux_sys_mremap_args /* { - syscallarg(void *) old_address; - syscallarg(size_t) old_size; - syscallarg(size_t) new_size; - syscallarg(u_long) flags; - } */ *uap = v; - struct sys_munmap_args mua; - size_t old_size, new_size; - int error; - - old_size = round_page(SCARG(uap, old_size)); - new_size = round_page(SCARG(uap, new_size)); - - /* - * Growing mapped region. - */ - if (new_size > old_size) { - /* - * XXX Implement me. What we probably want to do is - * XXX dig out the guts of the old mapping, mmap that - * XXX object again with the new size, then munmap - * XXX the old mapping. - */ - *retval = 0; - return (ENOMEM); - } - /* - * Shrinking mapped region. - */ - if (new_size < old_size) { - SCARG(&mua, addr) = (caddr_t)SCARG(uap, old_address) + new_size; - SCARG(&mua, len) = old_size - new_size; - error = sys_munmap(p, &mua, retval); - *retval = error ? 0 : (register_t)SCARG(uap, old_address); - return (error); - } - - /* - * No change. - */ - *retval = (register_t)SCARG(uap, old_address); - return (0); - -} - -/* - * This code is partly stolen from src/lib/libc/gen/times.c - * XXX - CLK_TCK isn't declared in /sys, just in <time.h>, done here - */ - -#define CLK_TCK 100 -#define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) - -int -linux_sys_times(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_times_args /* { - syscallarg(struct linux_tms *) tms; - } */ *uap = v; - struct timeval t, ut, st; - struct linux_tms ltms; - time_t ticks; - int error; - - calcru(&p->p_p->ps_tu, &ut, &st, NULL); - - ticks = CONVTCK(ut); - if (ticks > LINUX_TIME_MAX) - return EOVERFLOW; - ltms.ltms_utime = (linux_clock_t)ticks; - - ticks = CONVTCK(st); - if (ticks > LINUX_TIME_MAX) - return EOVERFLOW; - ltms.ltms_stime = (linux_clock_t)ticks; - - ticks = CONVTCK(p->p_p->ps_cru.ru_utime); - if (ticks > LINUX_TIME_MAX) - return EOVERFLOW; - ltms.ltms_cutime = (linux_clock_t)ticks; - - ticks = CONVTCK(p->p_p->ps_cru.ru_stime); - if (ticks > LINUX_TIME_MAX) - return EOVERFLOW; - ltms.ltms_cstime = (linux_clock_t)ticks; - - if ((error = copyout(<ms, SCARG(uap, tms), sizeof ltms))) - return error; - - microuptime(&t); - - retval[0] = ((linux_clock_t)(CONVTCK(t))); - return 0; -} - -/* - * Alarm. This is a libc call which uses setitimer(2) in OpenBSD. - * Fiddle with the timers to make it work. - */ -int -linux_sys_alarm(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_alarm_args /* { - syscallarg(unsigned int) secs; - } */ *uap = v; - struct process *pr; - struct itimerval *itp, it; - struct timeval tv; - int s; - int timo; - linux_time_t seconds_due = 0; - - pr = p->p_p; - itp = &pr->ps_timer[ITIMER_REAL]; - s = splclock(); - /* - * Clear any pending timer alarms. - */ - getmicrouptime(&tv); - timeout_del(&pr->ps_realit_to); - timerclear(&itp->it_interval); - if (timerisset(&itp->it_value) && - timercmp(&itp->it_value, &tv, >)) - timersub(&itp->it_value, &tv, &itp->it_value); - /* - * Return how many seconds were left (rounded up) - */ - if (itp->it_value.tv_sec > LINUX_TIME_MAX) { - splx(s); - return EOVERFLOW; - } - seconds_due = (linux_time_t)itp->it_value.tv_sec; - if (itp->it_value.tv_usec) { - if (seconds_due == LINUX_TIME_MAX) { - splx(s); - return EOVERFLOW; - } - seconds_due++; - } - retval[0] = seconds_due; - - /* - * alarm(0) just resets the timer. - */ - if (SCARG(uap, secs) == 0) { - timerclear(&itp->it_value); - splx(s); - return 0; - } - - /* - * Check the new alarm time for sanity, and set it. - */ - timerclear(&it.it_interval); - it.it_value.tv_sec = SCARG(uap, secs); - it.it_value.tv_usec = 0; - if (itimerfix(&it.it_value)) { - splx(s); - return (EINVAL); - } - - if (timerisset(&it.it_value)) { - timo = tvtohz(&it.it_value); - timeradd(&it.it_value, &tv, &it.it_value); - timeout_add(&pr->ps_realit_to, timo); - } - pr->ps_timer[ITIMER_REAL] = it; - splx(s); - - return 0; -} - -/* - * utime(). Do conversion to things that utimes() understands, - * and pass it on. - */ -int -linux_sys_utime(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_utime_args /* { - syscallarg(char *) path; - syscallarg(struct linux_utimbuf *)times; - } */ *uap = v; - caddr_t sg; - int error; - struct sys_utimes_args ua; - struct timeval tv[2], *tvp; - struct linux_utimbuf lut; - - sg = stackgap_init(p); - tvp = (struct timeval *) stackgap_alloc(&sg, sizeof(tv)); - LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); - - SCARG(&ua, path) = SCARG(uap, path); - - if (SCARG(uap, times) != NULL) { - if ((error = copyin(SCARG(uap, times), &lut, sizeof lut))) - return error; - tv[0].tv_usec = tv[1].tv_usec = 0; - tv[0].tv_sec = lut.l_actime; - tv[1].tv_sec = lut.l_modtime; - if ((error = copyout(tv, tvp, sizeof tv))) - return error; - SCARG(&ua, tptr) = tvp; - } - else - SCARG(&ua, tptr) = NULL; - - return sys_utimes(p, &ua, retval); -} - -/* - * The old Linux readdir was only able to read one entry at a time, - * even though it had a 'count' argument. In fact, the emulation - * of the old call was better than the original, because it did handle - * the count arg properly. Don't bother with it anymore now, and use - * it to distinguish between old and new. The difference is that the - * newer one actually does multiple entries, and the reclen field - * really is the reclen, not the namelength. - */ -int -linux_sys_readdir(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_readdir_args /* { - syscallarg(int) fd; - syscallarg(struct linux_dirent *) dent; - syscallarg(unsigned int) count; - } */ *uap = v; - - SCARG(uap, count) = 1; - - return linux_sys_getdents(p, uap, retval); -} - -/* - * Linux 'readdir' call. This code is mostly taken from the - * SunOS getdents call (see compat/sunos/sunos_misc.c), though - * an attempt has been made to keep it a little cleaner (failing - * miserably, because of the cruft needed if count 1 is passed). - * - * The d_off field should contain the offset of the next valid entry, - * but in Linux it has the offset of the entry itself. We emulate - * that bug here. - * - * Read in BSD-style entries, convert them, and copy them out. - * - * Note that this doesn't handle union-mounted filesystems. - */ -int linux_readdir_callback(void *, struct dirent *); - -struct linux_readdir_callback_args { - caddr_t outp; - int resid; - int oldcall; - int is64bit; -}; - -int -linux_readdir_callback(arg, bdp) - void *arg; - struct dirent *bdp; -{ - struct linux_dirent64 idb64; - struct linux_dirent idb; - struct linux_readdir_callback_args *cb = arg; - int linux_reclen; - int error; - - if (cb->oldcall == 2) - return (ENOMEM); - - linux_reclen = (cb->is64bit) ? - LINUX_RECLEN(&idb64, bdp->d_namlen) : - LINUX_RECLEN(&idb, bdp->d_namlen); - - if (cb->resid < linux_reclen) - return (ENOMEM); - - if (cb->is64bit) { - idb64.d_ino = (linux_ino64_t)bdp->d_fileno; - idb64.d_off = (linux_off64_t)bdp->d_off; - idb64.d_reclen = (u_short)linux_reclen; - idb64.d_type = bdp->d_type; - strlcpy(idb64.d_name, bdp->d_name, sizeof(idb64.d_name)); - error = copyout((caddr_t)&idb64, cb->outp, linux_reclen); - } else { - if (bdp->d_fileno > LINUX_INO_MAX) - return EOVERFLOW; - idb.d_ino = (linux_ino_t)bdp->d_fileno; - if (cb->oldcall) { - /* - * The old readdir() call misuses the offset - * and reclen fields. - */ - idb.d_off = (linux_off_t)linux_reclen; - idb.d_reclen = (u_short)bdp->d_namlen; - } else { - idb.d_off = (linux_off_t)bdp->d_off; - idb.d_reclen = (u_short)linux_reclen; - } - strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name)); - error = copyout((caddr_t)&idb, cb->outp, linux_reclen); - } - if (error) - return (error); - - /* advance output past Linux-shaped entry */ - cb->outp += linux_reclen; - cb->resid -= linux_reclen; - - if (cb->oldcall == 1) - ++cb->oldcall; - - return (0); -} - -int -linux_sys_getdents64(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - return getdents_common(p, v, retval, 1); -} - -int -linux_sys_getdents(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - return getdents_common(p, v, retval, 0); -} - -int -getdents_common(p, v, retval, is64bit) - struct proc *p; - void *v; - register_t *retval; - int is64bit; -{ - struct linux_sys_getdents_args /* { - syscallarg(int) fd; - syscallarg(void *) dirent; - syscallarg(unsigned) count; - } */ *uap = v; - struct linux_readdir_callback_args args; - struct file *fp; - int error; - int nbytes = SCARG(uap, count); - - if ((error = getvnode(p, SCARG(uap, fd), &fp)) != 0) - return (error); - - if (nbytes == 1) { /* emulating old, broken behaviour */ - /* readdir(2) case. Always struct dirent. */ - if (is64bit) { - FRELE(fp, p); - return (EINVAL); - } - nbytes = sizeof(struct linux_dirent); - args.oldcall = 1; - } else { - args.oldcall = 0; - } - - args.resid = nbytes; - args.outp = (caddr_t)SCARG(uap, dirent); - args.is64bit = is64bit; - - if ((error = readdir_with_callback(fp, &fp->f_offset, nbytes, - linux_readdir_callback, &args)) != 0) - goto exit; - - *retval = nbytes - args.resid; - - exit: - FRELE(fp, p); - return (error); -} - -/* - * Not sure why the arguments to this older version of select() were put - * into a structure, because there are 5, and that can be handled all - * in registers on the i386 like Linux wants to. - */ -int -linux_sys_oldselect(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_oldselect_args /* { - syscallarg(struct linux_select *) lsp; - } */ *uap = v; - struct linux_select ls; - int error; - - if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls)))) - return error; - - return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds, - ls.exceptfds, ls.timeout); -} - -/* - * Even when just using registers to pass arguments to syscalls you can - * have 5 of them on the i386. So this newer version of select() does - * this. - */ -int -linux_sys_select(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_select_args /* { - syscallarg(int) nfds; - syscallarg(fd_set *) readfds; - syscallarg(fd_set *) writefds; - syscallarg(fd_set *) exceptfds; - syscallarg(struct linux_timeval *) timeout; - } */ *uap = v; - - return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds), - SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout)); -} - -/* - * Common code for the old and new versions of select(). A couple of - * things are important: - * 1) return the amount of time left in the 'timeout' parameter - * 2) select never returns ERESTART on Linux, always return EINTR - */ -int -linux_select1(struct proc *p, register_t *retval, int nfds, fd_set *readfds, - fd_set *writefds, fd_set *exceptfds, struct linux_timeval *timeout) -{ - struct sys_select_args bsa; - struct linux_timeval lutv; - struct timeval tv0, tv1, utv, *tvp; - caddr_t sg; - int error; - - SCARG(&bsa, nd) = nfds; - SCARG(&bsa, in) = readfds; - SCARG(&bsa, ou) = writefds; - SCARG(&bsa, ex) = exceptfds; - - /* - * Store current time for computation of the amount of - * time left. - */ - if (timeout) { - if ((error = copyin(timeout, &lutv, sizeof(lutv)))) - return error; - linux_to_bsd_timeval(&utv, &lutv); - if (itimerfix(&utv)) { - /* - * The timeval was invalid. Convert it to something - * valid that will act as it does under Linux. - */ - utv.tv_sec += utv.tv_usec / 1000000; - utv.tv_usec %= 1000000; - if (utv.tv_usec < 0) { - utv.tv_sec -= 1; - utv.tv_usec += 1000000; - } - if (utv.tv_sec < 0) - timerclear(&utv); - } - - sg = stackgap_init(p); - tvp = stackgap_alloc(&sg, sizeof(utv)); - if ((error = copyout(&utv, tvp, sizeof(utv)))) - return error; - SCARG(&bsa, tv) = tvp; - microtime(&tv0); - } else - SCARG(&bsa, tv) = NULL; - - error = sys_select(p, &bsa, retval); - if (error) { - /* - * See fs/select.c in the Linux kernel. Without this, - * Maelstrom doesn't work. - */ - if (error == ERESTART) - error = EINTR; - else if (error != EINTR) - return error; - } - - if (timeout) { - if (*retval) { - /* - * Compute how much time was left of the timeout, - * by subtracting the current time and the time - * before we started the call, and subtracting - * that result from the user-supplied value. - */ - microtime(&tv1); - timersub(&tv1, &tv0, &tv1); - timersub(&utv, &tv1, &utv); - if (utv.tv_sec < 0) - timerclear(&utv); - } else - timerclear(&utv); - bsd_to_linux_timeval(&lutv, &utv); /* can't fail */ - if ((error = copyout(&lutv, timeout, sizeof(lutv)))) - return error; - } - - return (error); -} - -/* - * Get the process group of a certain process. Look it up - * and return the value. - */ -int -linux_sys_getpgid(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_getpgid_args /* { - syscallarg(int) pid; - } */ *uap = v; - struct process *targpr; - - if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != p->p_p->ps_pid) { - if ((targpr = prfind(SCARG(uap, pid))) == 0) - return ESRCH; - } - else - targpr = p->p_p; - - retval[0] = targpr->ps_pgid; - return 0; -} - -/* - * Set the 'personality' (emulation mode) for the current process. Only - * accept the Linux personality here (0). This call is needed because - * the Linux ELF crt0 issues it in an ugly kludge to make sure that - * ELF binaries run in Linux mode, not SVR4 mode. - */ -int -linux_sys_personality(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_personality_args /* { - syscallarg(int) per; - } */ *uap = v; - - if (SCARG(uap, per) != 0) - return EINVAL; - retval[0] = 0; - return 0; -} - -/* - * The calls are here because of type conversions. - */ -int -linux_sys_setreuid16(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_setreuid16_args /* { - syscallarg(int) ruid; - syscallarg(int) euid; - } */ *uap = v; - struct sys_setreuid_args bsa; - - SCARG(&bsa, ruid) = ((linux_uid_t)SCARG(uap, ruid) == (linux_uid_t)-1) ? - (uid_t)-1 : SCARG(uap, ruid); - SCARG(&bsa, euid) = ((linux_uid_t)SCARG(uap, euid) == (linux_uid_t)-1) ? - (uid_t)-1 : SCARG(uap, euid); - - return sys_setreuid(p, &bsa, retval); -} - -int -linux_sys_setregid16(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_setregid16_args /* { - syscallarg(int) rgid; - syscallarg(int) egid; - } */ *uap = v; - struct sys_setregid_args bsa; - - SCARG(&bsa, rgid) = ((linux_gid_t)SCARG(uap, rgid) == (linux_gid_t)-1) ? - (uid_t)-1 : SCARG(uap, rgid); - SCARG(&bsa, egid) = ((linux_gid_t)SCARG(uap, egid) == (linux_gid_t)-1) ? - (uid_t)-1 : SCARG(uap, egid); - - return sys_setregid(p, &bsa, retval); -} - -int -linux_sys___sysctl(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys___sysctl_args /* { - syscallarg(struct linux___sysctl *) lsp; - } */ *uap = v; - struct linux___sysctl ls; - struct sys_sysctl_args bsa; - int error; - - if ((error = copyin(SCARG(uap, lsp), &ls, sizeof ls))) - return error; - SCARG(&bsa, name) = ls.name; - SCARG(&bsa, namelen) = ls.namelen; - SCARG(&bsa, old) = ls.old; - SCARG(&bsa, oldlenp) = ls.oldlenp; - SCARG(&bsa, new) = ls.new; - SCARG(&bsa, newlen) = ls.newlen; - - return sys_sysctl(p, &bsa, retval); -} - -/* - * We have nonexistent fsuid equal to uid. - * If modification is requested, refuse. - */ -int -linux_sys_setfsuid(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_setfsuid_args /* { - syscallarg(uid_t) uid; - } */ *uap = v; - uid_t uid; - - uid = SCARG(uap, uid); - if (p->p_ucred->cr_ruid != uid) - return sys_nosys(p, v, retval); - else - return (0); -} - -int -linux_sys_getfsuid(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - return sys_getuid(p, v, retval); -} - - -int -linux_sys_nice(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_nice_args /* { - syscallarg(int) incr; - } */ *uap = v; - struct sys_setpriority_args bsa; - - SCARG(&bsa, which) = PRIO_PROCESS; - SCARG(&bsa, who) = 0; - SCARG(&bsa, prio) = SCARG(uap, incr); - return sys_setpriority(p, &bsa, retval); -} - -int -linux_sys_getpid(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - - *retval = p->p_p->ps_pid; - return (0); -} - -linux_pid_t -linux_sys_gettid(struct proc *p, void *v, register_t *retval) -{ - *retval = p->p_pid + THREAD_PID_OFFSET; - return (0); -} - -int -linux_sys_getuid(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - - *retval = p->p_ucred->cr_ruid; - return (0); -} - -int -linux_sys_getgid(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - - *retval = p->p_ucred->cr_rgid; - return (0); -} - - -/* - * sysinfo() - */ -/* ARGSUSED */ -int -linux_sys_sysinfo(p, v, retval) - struct proc *p; - void *v; - register_t *retval; -{ - struct linux_sys_sysinfo_args /* { - syscallarg(struct linux_sysinfo *) sysinfo; - } */ *uap = v; - struct linux_sysinfo si; - struct loadavg *la; - extern long bufpages; - struct timeval tv; - - getmicrouptime(&tv); - if (tv.tv_sec > LINUX_TIME_MAX) - return EOVERFLOW; - si.uptime = (linux_time_t)tv.tv_sec; - la = &averunnable; - si.loads[0] = la->ldavg[0] * LINUX_SYSINFO_LOADS_SCALE / la->fscale; - si.loads[1] = la->ldavg[1] * LINUX_SYSINFO_LOADS_SCALE / la->fscale; - si.loads[2] = la->ldavg[2] * LINUX_SYSINFO_LOADS_SCALE / la->fscale; - si.totalram = ptoa(physmem); - si.freeram = uvmexp.free * uvmexp.pagesize; - si.sharedram = 0;/* XXX */ - si.bufferram = bufpages * PAGE_SIZE; - si.totalswap = uvmexp.swpages * PAGE_SIZE; - si.freeswap = (uvmexp.swpages - uvmexp.swpginuse) * PAGE_SIZE; - si.procs = nthreads; - /* The following are only present in newer Linux kernels. */ - si.totalbig = 0; - si.freebig = 0; - si.mem_unit = 1; - - return (copyout(&si, SCARG(uap, sysinfo), sizeof(si))); -} - -int -linux_sys_mprotect(struct proc *p, void *v, register_t *retval) -{ - struct sys_mprotect_args *uap = v; - - if (SCARG(uap, prot) & (PROT_WRITE | PROT_EXEC)) - SCARG(uap, prot) |= PROT_READ; - return (sys_mprotect(p, uap, retval)); -} - -int -linux_sys_setdomainname(struct proc *p, void *v, register_t *retval) -{ - struct linux_sys_setdomainname_args *uap = v; - int error, mib[1]; - - if ((error = suser(p, 0))) - return (error); - mib[0] = KERN_DOMAINNAME; - return (kern_sysctl(mib, 1, NULL, NULL, SCARG(uap, name), - SCARG(uap, len), p)); -} - -int -linux_sys_swapon(struct proc *p, void *v, register_t *retval) -{ - struct sys_swapctl_args ua; - struct linux_sys_swapon_args /* { - syscallarg(const char *) name; - } */ *uap = v; - - SCARG(&ua, cmd) = SWAP_ON; - SCARG(&ua, arg) = (void *)SCARG(uap, name); - SCARG(&ua, misc) = 0; /* priority */ - return (sys_swapctl(p, &ua, retval)); -} - -int -linux_sys_prctl(struct proc *p, void *v, register_t *retval) -{ - int error = 0, max_size, pdeath_signal; - char comm[LINUX_MAX_COMM_LEN]; - struct linux_emuldata *ed = (struct linux_emuldata*)p->p_emuldata; - - struct linux_sys_prctl_args /* { - int option; - unsigned long arg2; - unsigned long arg3; - unsigned long arg4; - unsigned long arg5; - } */ *uap = v; - - switch (SCARG(uap, option)) { - case LINUX_PR_SET_PDEATHSIG: - if (SCARG(uap, arg2) >= LINUX__NSIG) - return (EINVAL); - ed->pdeath_signal = SCARG(uap, arg2); - break; - case LINUX_PR_GET_PDEATHSIG: - pdeath_signal = ed->pdeath_signal; - error = copyout(&pdeath_signal, (void *)SCARG(uap, arg2), - sizeof(pdeath_signal)); - break; - case LINUX_PR_GET_KEEPCAPS: - /* - * Indicate that we always clear the effective and - * permitted capability sets when the user id becomes - * non-zero (actually the capability sets are simply - * always zero in the current implementation). - */ - *retval = 0; - break; - case LINUX_PR_SET_KEEPCAPS: - /* - * Ignore requests to keep the effective and permitted - * capability sets when the user id becomes non-zero. - */ - break; - case LINUX_PR_SET_NAME: - /* - * To be on the safe side we need to make sure not to - * overflow the size a linux program expects. We already - * do this here in the copyin, so that we don't need to - * check on copyout. - */ - max_size = MIN(sizeof(comm), sizeof(p->p_comm)); - error = copyinstr((void *)SCARG(uap, arg2), comm, - max_size, NULL); - - /* Linux silently truncates the name if it is too long. */ - if (error == ENAMETOOLONG) { - /* - * XXX: copyinstr() isn't documented to populate the - * array completely, so do a copyin() to be on the - * safe side. This should be changed in case copyinstr() - * is changed to guarantee this. - */ - error = copyin((void *)SCARG(uap, arg2), comm, - max_size - 1); - comm[max_size - 1] = '\0'; - } - if (error) - return (error); - strlcpy(p->p_comm, comm, sizeof(p->p_comm)); - break; - case LINUX_PR_GET_NAME: - strlcpy(comm, p->p_comm, sizeof(comm)); - error = copyout(comm, (void *)SCARG(uap, arg2), - strlen(comm) + 1); - break; - default: - printf("linux_sys_prctl: unsupported option %d\n", - SCARG(uap, option)); - error = EINVAL; - break; - } - - return (error); -} |
