/*-
* Copyright (c) 1995, 1998 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.
*
* 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.
*/
/*
* Note: Not all linux architectures have explicit versions
* of the SYSV* syscalls. On the ones that don't
* we pretend that they are defined anyway. *_args and
* prototypes are defined in individual headers;
* syscalls.master lists those syscalls as NOARGS.
*
* The functions in multiarch are the ones that just need
* the arguments shuffled around and then use the
* normal NetBSD syscall.
*
* Function in multiarch:
* linux_sys_ipc : linux_ipccall.c
* linux_semop : linux_ipccall.c
* linux_semget : linux_ipccall.c
* linux_msgsnd : linux_ipccall.c
* linux_msgrcv : linux_ipccall.c
* linux_msgget : linux_ipccall.c
* linux_shmdt : linux_ipccall.c
* linux_shmget : linux_ipccall.c
*/
#if defined (SYSVSEM) || defined(SYSVSHM) || defined(SYSVMSG)
/*
* Convert between Linux and NetBSD ipc_perm structures. Only the
* order of the fields is different.
*/
void
linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp)
{
/*
* Most of this can be handled by directly passing the arguments on; we
* just need to frob the `cmd' and convert the semid_ds and semun.
*/
int
linux_sys_semctl(struct lwp *l, const struct linux_sys_semctl_args *uap, register_t *retval)
{
/* {
syscallarg(int) semid;
syscallarg(int) semnum;
syscallarg(int) cmd;
syscallarg(union linux_semun) arg;
} */
struct semid_ds sembuf;
struct linux_semid_ds lsembuf;
struct linux_semid64_ds lsembuf64;
union __semun semun;
int cmd, lcmd, error;
void *pass_arg = NULL;
#ifdef SYSVSHM
/*
* shmget(2). Just make sure the Linux-compatible shmat() semantics
* is enabled for the segment, so that shmat() succeeds even when
* the segment would be removed.
*/
int
linux_sys_shmget(struct lwp *l, const struct linux_sys_shmget_args *uap, register_t *retval)
{
/* {
syscallarg(key_t) key;
syscallarg(size_t) size;
syscallarg(int) shmflg;
} */
struct sys_shmget_args bsd_ua;
/*
* shmat(2). Very straightforward, except that Linux passes a pointer
* in which the return value is to be passed. This is subsequently
* handled by libc, apparently.
*/
#ifndef __amd64__
int
linux_sys_shmat(struct lwp *l, const struct linux_sys_shmat_args *uap, register_t *retval)
{
/* {
syscallarg(int) shmid;
syscallarg(void *) shmaddr;
syscallarg(int) shmflg;
syscallarg(u_long *) raddr;
} */
int error;
if ((error = sys_shmat(l, (const void *)uap, retval)))
return error;
if ((error = copyout(&retval[0], SCARG(uap, raddr), sizeof retval[0])))
return error;
retval[0] = 0;
return 0;
}
#endif /* __amd64__ */
/*
* Convert between Linux and NetBSD shmid_ds structures.
* The order of the fields is once again the difference, and
* we also need a place to store the internal data pointer
* in, which is unfortunately stored in this structure.
*
* We abuse a Linux internal field for that.
*/
void
linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp)
{