mirror of
https://github.com/qemu/qemu.git
synced 2026-04-05 22:00:58 +00:00
Add host_to_target_msqid_ds() to convert host struct msqid_ds to target format for msgctl(2) IPC_STAT operations. Signed-off-by: Stacey Son <sson@FreeBSD.org> Signed-off-by: Brooks Davis <brooks@one-eyed-alien.net> Signed-off-by: Sean Bruno <sbruno@FreeBSD.org> Signed-off-by: Mikael Urankar <mikael.urankar@gmail.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Warner Losh <imp@bsdimp.com>
193 lines
6.0 KiB
C
193 lines
6.0 KiB
C
/*
|
|
* BSD misc system call conversions routines
|
|
*
|
|
* Copyright (c) 2013 Stacey D. Son
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
#include "qemu/osdep.h"
|
|
|
|
#define _WANT_SEMUN
|
|
#include <sys/types.h>
|
|
#include <sys/ipc.h>
|
|
#include <sys/msg.h>
|
|
#include <sys/sem.h>
|
|
#include <sys/uuid.h>
|
|
|
|
#include "qemu.h"
|
|
#include "qemu-bsd.h"
|
|
|
|
/*
|
|
* BSD uuidgen(2) struct uuid conversion
|
|
*/
|
|
abi_long host_to_target_uuid(abi_ulong target_addr, struct uuid *host_uuid)
|
|
{
|
|
struct target_uuid *target_uuid;
|
|
|
|
if (!lock_user_struct(VERIFY_WRITE, target_uuid, target_addr, 0)) {
|
|
return -TARGET_EFAULT;
|
|
}
|
|
__put_user(host_uuid->time_low, &target_uuid->time_low);
|
|
__put_user(host_uuid->time_mid, &target_uuid->time_mid);
|
|
__put_user(host_uuid->time_hi_and_version,
|
|
&target_uuid->time_hi_and_version);
|
|
host_uuid->clock_seq_hi_and_reserved =
|
|
target_uuid->clock_seq_hi_and_reserved;
|
|
host_uuid->clock_seq_low = target_uuid->clock_seq_low;
|
|
memcpy(host_uuid->node, target_uuid->node, TARGET_UUID_NODE_LEN);
|
|
unlock_user_struct(target_uuid, target_addr, 1);
|
|
return 0;
|
|
}
|
|
|
|
abi_long target_to_host_semarray(int semid, unsigned short **host_array,
|
|
abi_ulong target_addr)
|
|
{
|
|
abi_long ret;
|
|
int nsems, i;
|
|
unsigned short *array;
|
|
union semun semun;
|
|
struct semid_ds semid_ds;
|
|
|
|
semun.buf = &semid_ds;
|
|
ret = semctl(semid, 0, IPC_STAT, semun);
|
|
if (ret == -1) {
|
|
return get_errno(ret);
|
|
}
|
|
nsems = semid_ds.sem_nsems;
|
|
*host_array = g_new(unsigned short, nsems);
|
|
array = lock_user(VERIFY_READ, target_addr,
|
|
nsems * sizeof(unsigned short), 1);
|
|
if (array == NULL) {
|
|
free(*host_array);
|
|
return -TARGET_EFAULT;
|
|
}
|
|
for (i = 0; i < nsems; i++) {
|
|
__get_user((*host_array)[i], array + i);
|
|
}
|
|
unlock_user(array, target_addr, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
|
|
unsigned short **host_arrayp)
|
|
{
|
|
g_autofree unsigned short *host_array = *host_arrayp;
|
|
abi_long ret;
|
|
int nsems, i;
|
|
unsigned short *array;
|
|
union semun semun;
|
|
struct semid_ds semid_ds;
|
|
|
|
semun.buf = &semid_ds;
|
|
|
|
ret = semctl(semid, 0, IPC_STAT, semun);
|
|
if (ret == -1) {
|
|
return get_errno(ret);
|
|
}
|
|
|
|
nsems = semid_ds.sem_nsems;
|
|
array = (unsigned short *)lock_user(VERIFY_WRITE, target_addr,
|
|
nsems * sizeof(unsigned short), 0);
|
|
if (array == NULL) {
|
|
return -TARGET_EFAULT;
|
|
}
|
|
for (i = 0; i < nsems; i++) {
|
|
__put_user(array[i], host_array + i);
|
|
}
|
|
unlock_user(array, target_addr, 1);
|
|
return 0;
|
|
}
|
|
|
|
abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
|
|
abi_ulong target_addr)
|
|
{
|
|
struct target_semid_ds *target_sd;
|
|
|
|
if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) {
|
|
return -TARGET_EFAULT;
|
|
}
|
|
target_to_host_ipc_perm__locked(&host_sd->sem_perm, &target_sd->sem_perm);
|
|
/* sem_base is not used by kernel for IPC_STAT/IPC_SET */
|
|
/* host_sd->sem_base = g2h_untagged(target_sd->sem_base); */
|
|
__get_user(host_sd->sem_nsems, &target_sd->sem_nsems);
|
|
__get_user(host_sd->sem_otime, &target_sd->sem_otime);
|
|
__get_user(host_sd->sem_ctime, &target_sd->sem_ctime);
|
|
unlock_user_struct(target_sd, target_addr, 0);
|
|
return 0;
|
|
}
|
|
|
|
abi_long host_to_target_semid_ds(abi_ulong target_addr,
|
|
struct semid_ds *host_sd)
|
|
{
|
|
struct target_semid_ds *target_sd;
|
|
|
|
if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) {
|
|
return -TARGET_EFAULT;
|
|
}
|
|
host_to_target_ipc_perm__locked(&target_sd->sem_perm,
|
|
&host_sd->sem_perm);
|
|
/* sem_base is not used by kernel for IPC_STAT/IPC_SET */
|
|
/* target_sd->sem_base = h2g((void *)host_sd->sem_base); */
|
|
__put_user(target_sd->sem_nsems, &host_sd->sem_nsems);
|
|
__put_user(target_sd->sem_otime, &host_sd->sem_otime);
|
|
__put_user(target_sd->sem_ctime, &host_sd->sem_ctime);
|
|
unlock_user_struct(target_sd, target_addr, 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
|
|
abi_ulong target_addr)
|
|
{
|
|
struct target_msqid_ds *target_md;
|
|
|
|
if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1)) {
|
|
return -TARGET_EFAULT;
|
|
}
|
|
|
|
memset(host_md, 0, sizeof(struct msqid_ds));
|
|
target_to_host_ipc_perm__locked(&host_md->msg_perm,
|
|
&target_md->msg_perm);
|
|
|
|
/* msg_first and msg_last are not used by IPC_SET/IPC_STAT in kernel. */
|
|
__get_user(host_md->msg_cbytes, &target_md->msg_cbytes);
|
|
__get_user(host_md->msg_qnum, &target_md->msg_qnum);
|
|
__get_user(host_md->msg_qbytes, &target_md->msg_qbytes);
|
|
__get_user(host_md->msg_lspid, &target_md->msg_lspid);
|
|
__get_user(host_md->msg_lrpid, &target_md->msg_lrpid);
|
|
__get_user(host_md->msg_stime, &target_md->msg_stime);
|
|
__get_user(host_md->msg_rtime, &target_md->msg_rtime);
|
|
__get_user(host_md->msg_ctime, &target_md->msg_ctime);
|
|
unlock_user_struct(target_md, target_addr, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
abi_long host_to_target_msqid_ds(abi_ulong target_addr,
|
|
struct msqid_ds *host_md)
|
|
{
|
|
struct target_msqid_ds *target_md;
|
|
|
|
if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) {
|
|
return -TARGET_EFAULT;
|
|
}
|
|
|
|
memset(target_md, 0, sizeof(struct target_msqid_ds));
|
|
host_to_target_ipc_perm__locked(&target_md->msg_perm,
|
|
&host_md->msg_perm);
|
|
|
|
/* msg_first and msg_last are not used by IPC_SET/IPC_STAT in kernel. */
|
|
__put_user(target_md->msg_cbytes, &host_md->msg_cbytes);
|
|
__put_user(target_md->msg_qnum, &host_md->msg_qnum);
|
|
__put_user(target_md->msg_qbytes, &host_md->msg_qbytes);
|
|
__put_user(target_md->msg_lspid, &host_md->msg_lspid);
|
|
__put_user(target_md->msg_lrpid, &host_md->msg_lrpid);
|
|
__put_user(target_md->msg_stime, &host_md->msg_stime);
|
|
__put_user(target_md->msg_rtime, &host_md->msg_rtime);
|
|
__put_user(target_md->msg_ctime, &host_md->msg_ctime);
|
|
unlock_user_struct(target_md, target_addr, 1);
|
|
|
|
return 0;
|
|
}
|