10d163575Sopenharmony_ci/* 20d163575Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 30d163575Sopenharmony_ci * Copyright (c) 2020-2023 Huawei Device Co., Ltd. All rights reserved. 40d163575Sopenharmony_ci * 50d163575Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 60d163575Sopenharmony_ci * are permitted provided that the following conditions are met: 70d163575Sopenharmony_ci * 80d163575Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of 90d163575Sopenharmony_ci * conditions and the following disclaimer. 100d163575Sopenharmony_ci * 110d163575Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list 120d163575Sopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials 130d163575Sopenharmony_ci * provided with the distribution. 140d163575Sopenharmony_ci * 150d163575Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used 160d163575Sopenharmony_ci * to endorse or promote products derived from this software without specific prior written 170d163575Sopenharmony_ci * permission. 180d163575Sopenharmony_ci * 190d163575Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 200d163575Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 210d163575Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 220d163575Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 230d163575Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 240d163575Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 250d163575Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 260d163575Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 270d163575Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 280d163575Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 290d163575Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 300d163575Sopenharmony_ci */ 310d163575Sopenharmony_ci 320d163575Sopenharmony_ci#include "mqueue.h" 330d163575Sopenharmony_ci#ifdef LOSCFG_FS_VFS 340d163575Sopenharmony_ci#include "fcntl.h" 350d163575Sopenharmony_ci#include "pthread.h" 360d163575Sopenharmony_ci#include "map_error.h" 370d163575Sopenharmony_ci#include "time_posix.h" 380d163575Sopenharmony_ci#include "los_memory.h" 390d163575Sopenharmony_ci#include "los_vm_map.h" 400d163575Sopenharmony_ci#include "los_process_pri.h" 410d163575Sopenharmony_ci#include "fs/file.h" 420d163575Sopenharmony_ci#include "user_copy.h" 430d163575Sopenharmony_ci 440d163575Sopenharmony_ci 450d163575Sopenharmony_ci#define FNONBLOCK O_NONBLOCK 460d163575Sopenharmony_ci 470d163575Sopenharmony_ci#ifndef LOSCFG_IPC_CONTAINER 480d163575Sopenharmony_ci/* GLOBALS */ 490d163575Sopenharmony_ciSTATIC fd_set g_queueFdSet; 500d163575Sopenharmony_ciSTATIC struct mqarray g_queueTable[LOSCFG_BASE_IPC_QUEUE_LIMIT]; 510d163575Sopenharmony_ciSTATIC pthread_mutex_t g_mqueueMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; 520d163575Sopenharmony_ciSTATIC struct mqpersonal *g_mqPrivBuf[MAX_MQ_FD]; 530d163575Sopenharmony_ci 540d163575Sopenharmony_ci#define IPC_QUEUE_FD_SET g_queueFdSet 550d163575Sopenharmony_ci#define IPC_QUEUE_TABLE g_queueTable 560d163575Sopenharmony_ci#define IPC_QUEUE_MUTEX g_mqueueMutex 570d163575Sopenharmony_ci#define IPC_QUEUE_MQ_PRIV_BUF g_mqPrivBuf 580d163575Sopenharmony_ci#endif 590d163575Sopenharmony_ci 600d163575Sopenharmony_ci/* LOCAL FUNCTIONS */ 610d163575Sopenharmony_ciSTATIC INLINE INT32 MqNameCheck(const CHAR *mqName) 620d163575Sopenharmony_ci{ 630d163575Sopenharmony_ci if (mqName == NULL) { 640d163575Sopenharmony_ci errno = EINVAL; 650d163575Sopenharmony_ci return -1; 660d163575Sopenharmony_ci } 670d163575Sopenharmony_ci 680d163575Sopenharmony_ci if (strlen(mqName) == 0) { 690d163575Sopenharmony_ci errno = EINVAL; 700d163575Sopenharmony_ci return -1; 710d163575Sopenharmony_ci } 720d163575Sopenharmony_ci 730d163575Sopenharmony_ci if (strlen(mqName) > (PATH_MAX - 1)) { 740d163575Sopenharmony_ci errno = ENAMETOOLONG; 750d163575Sopenharmony_ci return -1; 760d163575Sopenharmony_ci } 770d163575Sopenharmony_ci return 0; 780d163575Sopenharmony_ci} 790d163575Sopenharmony_ci 800d163575Sopenharmony_ciSTATIC INLINE UINT32 GetMqueueCBByID(UINT32 queueID, LosQueueCB **queueCB) 810d163575Sopenharmony_ci{ 820d163575Sopenharmony_ci LosQueueCB *tmpQueueCB = NULL; 830d163575Sopenharmony_ci if (queueCB == NULL) { 840d163575Sopenharmony_ci errno = EINVAL; 850d163575Sopenharmony_ci return LOS_ERRNO_QUEUE_READ_PTR_NULL; 860d163575Sopenharmony_ci } 870d163575Sopenharmony_ci tmpQueueCB = GET_QUEUE_HANDLE(queueID); 880d163575Sopenharmony_ci if ((GET_QUEUE_INDEX(queueID) >= LOSCFG_BASE_IPC_QUEUE_LIMIT) || (tmpQueueCB->queueID != queueID)) { 890d163575Sopenharmony_ci return LOS_ERRNO_QUEUE_INVALID; 900d163575Sopenharmony_ci } 910d163575Sopenharmony_ci *queueCB = tmpQueueCB; 920d163575Sopenharmony_ci 930d163575Sopenharmony_ci return LOS_OK; 940d163575Sopenharmony_ci} 950d163575Sopenharmony_ci 960d163575Sopenharmony_ciSTATIC INLINE struct mqarray *GetMqueueCBByName(const CHAR *name) 970d163575Sopenharmony_ci{ 980d163575Sopenharmony_ci UINT32 index; 990d163575Sopenharmony_ci UINT32 mylen = strlen(name); 1000d163575Sopenharmony_ci 1010d163575Sopenharmony_ci for (index = 0; index < LOSCFG_BASE_IPC_QUEUE_LIMIT; index++) { 1020d163575Sopenharmony_ci if ((IPC_QUEUE_TABLE[index].mq_name == NULL) || (strlen(IPC_QUEUE_TABLE[index].mq_name) != mylen)) { 1030d163575Sopenharmony_ci continue; 1040d163575Sopenharmony_ci } 1050d163575Sopenharmony_ci 1060d163575Sopenharmony_ci if (strncmp(name, (const CHAR *)(IPC_QUEUE_TABLE[index].mq_name), mylen) == 0) { 1070d163575Sopenharmony_ci return &(IPC_QUEUE_TABLE[index]); 1080d163575Sopenharmony_ci } 1090d163575Sopenharmony_ci } 1100d163575Sopenharmony_ci return NULL; 1110d163575Sopenharmony_ci} 1120d163575Sopenharmony_ci 1130d163575Sopenharmony_ciSTATIC INT32 DoMqueueDelete(struct mqarray *mqueueCB) 1140d163575Sopenharmony_ci{ 1150d163575Sopenharmony_ci UINT32 ret; 1160d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_IPC_PLIMIT 1170d163575Sopenharmony_ci OsIPCLimitMqFree(); 1180d163575Sopenharmony_ci#endif 1190d163575Sopenharmony_ci if (mqueueCB->mq_name != NULL) { 1200d163575Sopenharmony_ci LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name); 1210d163575Sopenharmony_ci mqueueCB->mq_name = NULL; 1220d163575Sopenharmony_ci } 1230d163575Sopenharmony_ci 1240d163575Sopenharmony_ci mqueueCB->mqcb = NULL; 1250d163575Sopenharmony_ci /* When mqueue-list head node needed free ,reset the mode_data */ 1260d163575Sopenharmony_ci mqueueCB->mode_data.data = 0; 1270d163575Sopenharmony_ci mqueueCB->euid = -1; 1280d163575Sopenharmony_ci mqueueCB->egid = -1; 1290d163575Sopenharmony_ci mqueueCB->mq_notify.pid = 0; 1300d163575Sopenharmony_ci 1310d163575Sopenharmony_ci ret = LOS_QueueDelete(mqueueCB->mq_id); 1320d163575Sopenharmony_ci switch (ret) { 1330d163575Sopenharmony_ci case LOS_OK: 1340d163575Sopenharmony_ci return 0; 1350d163575Sopenharmony_ci case LOS_ERRNO_QUEUE_NOT_FOUND: 1360d163575Sopenharmony_ci case LOS_ERRNO_QUEUE_NOT_CREATE: 1370d163575Sopenharmony_ci case LOS_ERRNO_QUEUE_IN_TSKUSE: 1380d163575Sopenharmony_ci case LOS_ERRNO_QUEUE_IN_TSKWRITE: 1390d163575Sopenharmony_ci errno = EAGAIN; 1400d163575Sopenharmony_ci return -1; 1410d163575Sopenharmony_ci default: 1420d163575Sopenharmony_ci errno = EINVAL; 1430d163575Sopenharmony_ci return -1; 1440d163575Sopenharmony_ci } 1450d163575Sopenharmony_ci} 1460d163575Sopenharmony_ci 1470d163575Sopenharmony_ciSTATIC int SaveMqueueName(const CHAR *mqName, struct mqarray *mqueueCB) 1480d163575Sopenharmony_ci{ 1490d163575Sopenharmony_ci size_t nameLen; 1500d163575Sopenharmony_ci 1510d163575Sopenharmony_ci nameLen = strlen(mqName); /* sys_mq_open has checked name and name length */ 1520d163575Sopenharmony_ci mqueueCB->mq_name = (char *)LOS_MemAlloc(OS_SYS_MEM_ADDR, nameLen + 1); 1530d163575Sopenharmony_ci if (mqueueCB->mq_name == NULL) { 1540d163575Sopenharmony_ci errno = ENOMEM; 1550d163575Sopenharmony_ci return LOS_NOK; 1560d163575Sopenharmony_ci } 1570d163575Sopenharmony_ci 1580d163575Sopenharmony_ci if (strncpy_s(mqueueCB->mq_name, (nameLen + 1), mqName, nameLen) != EOK) { 1590d163575Sopenharmony_ci LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name); 1600d163575Sopenharmony_ci mqueueCB->mq_name = NULL; 1610d163575Sopenharmony_ci errno = EINVAL; 1620d163575Sopenharmony_ci return LOS_NOK; 1630d163575Sopenharmony_ci } 1640d163575Sopenharmony_ci mqueueCB->mq_name[nameLen] = '\0'; 1650d163575Sopenharmony_ci return LOS_OK; 1660d163575Sopenharmony_ci} 1670d163575Sopenharmony_ci 1680d163575Sopenharmony_ciSTATIC VOID MqueueCBInit(struct mqarray *mqueueCB, const struct mq_attr *attr, INT32 openFlag, UINT32 mode) 1690d163575Sopenharmony_ci{ 1700d163575Sopenharmony_ci mqueueCB->unlinkflag = FALSE; 1710d163575Sopenharmony_ci mqueueCB->unlink_ref = 0; 1720d163575Sopenharmony_ci mqueueCB->mq_personal->mq_status = MQ_USE_MAGIC; 1730d163575Sopenharmony_ci mqueueCB->mq_personal->mq_next = NULL; 1740d163575Sopenharmony_ci mqueueCB->mq_personal->mq_posixdes = mqueueCB; 1750d163575Sopenharmony_ci mqueueCB->mq_personal->mq_flags = (INT32)((UINT32)openFlag | ((UINT32)attr->mq_flags & (UINT32)FNONBLOCK)); 1760d163575Sopenharmony_ci mqueueCB->mq_personal->mq_mode = mode; 1770d163575Sopenharmony_ci mqueueCB->mq_personal->mq_refcount = 0; 1780d163575Sopenharmony_ci mqueueCB->mq_notify.pid = 0; 1790d163575Sopenharmony_ci} 1800d163575Sopenharmony_ci 1810d163575Sopenharmony_ciSTATIC struct mqpersonal *DoMqueueCreate(const struct mq_attr *attr, const CHAR *mqName, INT32 openFlag, UINT32 mode) 1820d163575Sopenharmony_ci{ 1830d163575Sopenharmony_ci struct mqarray *mqueueCB = NULL; 1840d163575Sopenharmony_ci UINT32 mqueueID; 1850d163575Sopenharmony_ci 1860d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_IPC_PLIMIT 1870d163575Sopenharmony_ci if (OsIPCLimitMqAlloc() != LOS_OK) { 1880d163575Sopenharmony_ci return (struct mqpersonal *)-1; 1890d163575Sopenharmony_ci } 1900d163575Sopenharmony_ci#endif 1910d163575Sopenharmony_ci UINT32 err = LOS_QueueCreate(NULL, attr->mq_maxmsg, &mqueueID, 0, attr->mq_msgsize); 1920d163575Sopenharmony_ci if (map_errno(err) != ENOERR) { 1930d163575Sopenharmony_ci goto ERROUT; 1940d163575Sopenharmony_ci } 1950d163575Sopenharmony_ci 1960d163575Sopenharmony_ci if (IPC_QUEUE_TABLE[GET_QUEUE_INDEX(mqueueID)].mqcb == NULL) { 1970d163575Sopenharmony_ci mqueueCB = &(IPC_QUEUE_TABLE[GET_QUEUE_INDEX(mqueueID)]); 1980d163575Sopenharmony_ci mqueueCB->mq_id = mqueueID; 1990d163575Sopenharmony_ci } 2000d163575Sopenharmony_ci 2010d163575Sopenharmony_ci if (mqueueCB == NULL) { 2020d163575Sopenharmony_ci errno = EINVAL; 2030d163575Sopenharmony_ci goto ERROUT; 2040d163575Sopenharmony_ci } 2050d163575Sopenharmony_ci 2060d163575Sopenharmony_ci if (SaveMqueueName(mqName, mqueueCB) != LOS_OK) { 2070d163575Sopenharmony_ci goto ERROUT; 2080d163575Sopenharmony_ci } 2090d163575Sopenharmony_ci 2100d163575Sopenharmony_ci if (GetMqueueCBByID(mqueueCB->mq_id, &(mqueueCB->mqcb)) != LOS_OK) { 2110d163575Sopenharmony_ci errno = ENOSPC; 2120d163575Sopenharmony_ci goto ERROUT; 2130d163575Sopenharmony_ci } 2140d163575Sopenharmony_ci 2150d163575Sopenharmony_ci mqueueCB->mq_personal = (struct mqpersonal *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct mqpersonal)); 2160d163575Sopenharmony_ci if (mqueueCB->mq_personal == NULL) { 2170d163575Sopenharmony_ci (VOID)LOS_QueueDelete(mqueueCB->mq_id); 2180d163575Sopenharmony_ci mqueueCB->mqcb->queueHandle = NULL; 2190d163575Sopenharmony_ci mqueueCB->mqcb = NULL; 2200d163575Sopenharmony_ci errno = ENOSPC; 2210d163575Sopenharmony_ci goto ERROUT; 2220d163575Sopenharmony_ci } 2230d163575Sopenharmony_ci 2240d163575Sopenharmony_ci MqueueCBInit(mqueueCB, attr, openFlag, mode); 2250d163575Sopenharmony_ci 2260d163575Sopenharmony_ci return mqueueCB->mq_personal; 2270d163575Sopenharmony_ciERROUT: 2280d163575Sopenharmony_ci 2290d163575Sopenharmony_ci if ((mqueueCB != NULL) && (mqueueCB->mq_name != NULL)) { 2300d163575Sopenharmony_ci LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name); 2310d163575Sopenharmony_ci mqueueCB->mq_name = NULL; 2320d163575Sopenharmony_ci } 2330d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_IPC_PLIMIT 2340d163575Sopenharmony_ci OsIPCLimitMqFree(); 2350d163575Sopenharmony_ci#endif 2360d163575Sopenharmony_ci return (struct mqpersonal *)-1; 2370d163575Sopenharmony_ci} 2380d163575Sopenharmony_ci 2390d163575Sopenharmony_ciSTATIC struct mqpersonal *DoMqueueOpen(struct mqarray *mqueueCB, INT32 openFlag) 2400d163575Sopenharmony_ci{ 2410d163575Sopenharmony_ci struct mqpersonal *privateMqPersonal = NULL; 2420d163575Sopenharmony_ci 2430d163575Sopenharmony_ci /* already have the same name of g_squeuetable */ 2440d163575Sopenharmony_ci if (mqueueCB->unlinkflag == TRUE) { 2450d163575Sopenharmony_ci errno = EINVAL; 2460d163575Sopenharmony_ci goto ERROUT; 2470d163575Sopenharmony_ci } 2480d163575Sopenharmony_ci /* alloc mqprivate and add to mqarray */ 2490d163575Sopenharmony_ci privateMqPersonal = (struct mqpersonal *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct mqpersonal)); 2500d163575Sopenharmony_ci if (privateMqPersonal == NULL) { 2510d163575Sopenharmony_ci errno = ENOSPC; 2520d163575Sopenharmony_ci goto ERROUT; 2530d163575Sopenharmony_ci } 2540d163575Sopenharmony_ci 2550d163575Sopenharmony_ci privateMqPersonal->mq_next = mqueueCB->mq_personal; 2560d163575Sopenharmony_ci mqueueCB->mq_personal = privateMqPersonal; 2570d163575Sopenharmony_ci 2580d163575Sopenharmony_ci privateMqPersonal->mq_posixdes = mqueueCB; 2590d163575Sopenharmony_ci privateMqPersonal->mq_flags = openFlag; 2600d163575Sopenharmony_ci privateMqPersonal->mq_status = MQ_USE_MAGIC; 2610d163575Sopenharmony_ci privateMqPersonal->mq_refcount = 0; 2620d163575Sopenharmony_ci 2630d163575Sopenharmony_ci return privateMqPersonal; 2640d163575Sopenharmony_ci 2650d163575Sopenharmony_ciERROUT: 2660d163575Sopenharmony_ci return (struct mqpersonal *)-1; 2670d163575Sopenharmony_ci} 2680d163575Sopenharmony_ci 2690d163575Sopenharmony_ciSTATIC INT32 DoMqueueClose(struct mqpersonal *privateMqPersonal) 2700d163575Sopenharmony_ci{ 2710d163575Sopenharmony_ci struct mqarray *mqueueCB = NULL; 2720d163575Sopenharmony_ci struct mqpersonal *tmp = NULL; 2730d163575Sopenharmony_ci INT32 ret; 2740d163575Sopenharmony_ci 2750d163575Sopenharmony_ci mqueueCB = privateMqPersonal->mq_posixdes; 2760d163575Sopenharmony_ci if (mqueueCB == NULL || mqueueCB->mq_personal == NULL) { 2770d163575Sopenharmony_ci errno = EBADF; 2780d163575Sopenharmony_ci return LOS_NOK; 2790d163575Sopenharmony_ci } 2800d163575Sopenharmony_ci 2810d163575Sopenharmony_ci if ((mqueueCB->unlinkflag == TRUE) && (privateMqPersonal->mq_next == NULL)) { 2820d163575Sopenharmony_ci ret = DoMqueueDelete(mqueueCB); 2830d163575Sopenharmony_ci if (ret < 0) { 2840d163575Sopenharmony_ci return ret; 2850d163575Sopenharmony_ci } 2860d163575Sopenharmony_ci } 2870d163575Sopenharmony_ci /* find the personal and remove */ 2880d163575Sopenharmony_ci if (mqueueCB->mq_personal == privateMqPersonal) { 2890d163575Sopenharmony_ci mqueueCB->mq_personal = privateMqPersonal->mq_next; 2900d163575Sopenharmony_ci } else { 2910d163575Sopenharmony_ci for (tmp = mqueueCB->mq_personal; tmp->mq_next != NULL; tmp = tmp->mq_next) { 2920d163575Sopenharmony_ci if (tmp->mq_next == privateMqPersonal) { 2930d163575Sopenharmony_ci break; 2940d163575Sopenharmony_ci } 2950d163575Sopenharmony_ci } 2960d163575Sopenharmony_ci if (tmp->mq_next == NULL) { 2970d163575Sopenharmony_ci errno = EBADF; 2980d163575Sopenharmony_ci return LOS_NOK; 2990d163575Sopenharmony_ci } 3000d163575Sopenharmony_ci tmp->mq_next = privateMqPersonal->mq_next; 3010d163575Sopenharmony_ci } 3020d163575Sopenharmony_ci /* flag no use */ 3030d163575Sopenharmony_ci privateMqPersonal->mq_status = 0; 3040d163575Sopenharmony_ci 3050d163575Sopenharmony_ci /* free the personal */ 3060d163575Sopenharmony_ci (VOID)LOS_MemFree(OS_SYS_MEM_ADDR, privateMqPersonal); 3070d163575Sopenharmony_ci 3080d163575Sopenharmony_ci return LOS_OK; 3090d163575Sopenharmony_ci} 3100d163575Sopenharmony_ci 3110d163575Sopenharmony_ci/* Translate a sysFd into privateMqPersonal */ 3120d163575Sopenharmony_ciSTATIC struct mqpersonal *MqGetPrivDataBuff(mqd_t personal) 3130d163575Sopenharmony_ci{ 3140d163575Sopenharmony_ci INT32 sysFd = (INT32)personal; 3150d163575Sopenharmony_ci INT32 id = sysFd - MQUEUE_FD_OFFSET; 3160d163575Sopenharmony_ci 3170d163575Sopenharmony_ci /* Filter illegal id */ 3180d163575Sopenharmony_ci if ((id < 0) || (id >= MAX_MQ_FD)) { 3190d163575Sopenharmony_ci errno = EBADF; 3200d163575Sopenharmony_ci return NULL; 3210d163575Sopenharmony_ci } 3220d163575Sopenharmony_ci return IPC_QUEUE_MQ_PRIV_BUF[id]; 3230d163575Sopenharmony_ci} 3240d163575Sopenharmony_ci 3250d163575Sopenharmony_ci/** 3260d163575Sopenharmony_ci * Alloc sysFd, storage mq private data, set using bit. 3270d163575Sopenharmony_ci * 3280d163575Sopenharmony_ci * @param maxfdp: Maximum allowed application of mqueue sysFd. 3290d163575Sopenharmony_ci * @param fdset: Mqueue sysFd bit map. 3300d163575Sopenharmony_ci * @param privateMqPersonal: Private data. 3310d163575Sopenharmony_ci * @return the index of the new fd; -1 on error 3320d163575Sopenharmony_ci */ 3330d163575Sopenharmony_ciSTATIC INT32 MqAllocSysFd(int maxfdp, struct mqpersonal *privateMqPersonal) 3340d163575Sopenharmony_ci{ 3350d163575Sopenharmony_ci INT32 i; 3360d163575Sopenharmony_ci fd_set *fdset = &IPC_QUEUE_FD_SET; 3370d163575Sopenharmony_ci for (i = 0; i < maxfdp; i++) { 3380d163575Sopenharmony_ci /* sysFd: used bit setting, and get the index of swtmrID buffer */ 3390d163575Sopenharmony_ci if (fdset && !(FD_ISSET(i + MQUEUE_FD_OFFSET, fdset))) { 3400d163575Sopenharmony_ci FD_SET(i + MQUEUE_FD_OFFSET, fdset); 3410d163575Sopenharmony_ci if (!IPC_QUEUE_MQ_PRIV_BUF[i]) { 3420d163575Sopenharmony_ci IPC_QUEUE_MQ_PRIV_BUF[i] = privateMqPersonal; 3430d163575Sopenharmony_ci return i + MQUEUE_FD_OFFSET; 3440d163575Sopenharmony_ci } 3450d163575Sopenharmony_ci } 3460d163575Sopenharmony_ci } 3470d163575Sopenharmony_ci return -1; 3480d163575Sopenharmony_ci} 3490d163575Sopenharmony_ci 3500d163575Sopenharmony_ciSTATIC VOID MqFreeSysFd(mqd_t personal) 3510d163575Sopenharmony_ci{ 3520d163575Sopenharmony_ci INT32 sysFd = (INT32)personal; 3530d163575Sopenharmony_ci fd_set *fdset = &IPC_QUEUE_FD_SET; 3540d163575Sopenharmony_ci if (fdset && FD_ISSET(sysFd, fdset)) { 3550d163575Sopenharmony_ci FD_CLR(sysFd, fdset); 3560d163575Sopenharmony_ci IPC_QUEUE_MQ_PRIV_BUF[sysFd - MQUEUE_FD_OFFSET] = NULL; 3570d163575Sopenharmony_ci } 3580d163575Sopenharmony_ci} 3590d163575Sopenharmony_ci 3600d163575Sopenharmony_ci/* Mqueue fd reference count */ 3610d163575Sopenharmony_civoid MqueueRefer(int sysFd) 3620d163575Sopenharmony_ci{ 3630d163575Sopenharmony_ci struct mqarray *mqueueCB = NULL; 3640d163575Sopenharmony_ci struct mqpersonal *privateMqPersonal = NULL; 3650d163575Sopenharmony_ci 3660d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&IPC_QUEUE_MUTEX); 3670d163575Sopenharmony_ci /* Get the personal sysFd and reset personal fd -1 */ 3680d163575Sopenharmony_ci privateMqPersonal = MqGetPrivDataBuff((mqd_t)sysFd); 3690d163575Sopenharmony_ci if (privateMqPersonal == NULL) { 3700d163575Sopenharmony_ci goto OUT_UNLOCK; 3710d163575Sopenharmony_ci } 3720d163575Sopenharmony_ci mqueueCB = privateMqPersonal->mq_posixdes; 3730d163575Sopenharmony_ci if (mqueueCB == NULL) { 3740d163575Sopenharmony_ci goto OUT_UNLOCK; 3750d163575Sopenharmony_ci } 3760d163575Sopenharmony_ci 3770d163575Sopenharmony_ci privateMqPersonal->mq_refcount++; 3780d163575Sopenharmony_ciOUT_UNLOCK: 3790d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 3800d163575Sopenharmony_ci return; 3810d163575Sopenharmony_ci} 3820d163575Sopenharmony_ci 3830d163575Sopenharmony_ciSTATIC INT32 MqTryClose(struct mqpersonal *privateMqPersonal) 3840d163575Sopenharmony_ci{ 3850d163575Sopenharmony_ci struct mqarray *mqueueCB = NULL; 3860d163575Sopenharmony_ci mqueueCB = privateMqPersonal->mq_posixdes; 3870d163575Sopenharmony_ci if (mqueueCB == NULL) { 3880d163575Sopenharmony_ci errno = ENFILE; 3890d163575Sopenharmony_ci return false; 3900d163575Sopenharmony_ci } 3910d163575Sopenharmony_ci 3920d163575Sopenharmony_ci if (privateMqPersonal->mq_refcount == 0) { 3930d163575Sopenharmony_ci return TRUE; 3940d163575Sopenharmony_ci } 3950d163575Sopenharmony_ci privateMqPersonal->mq_refcount--; 3960d163575Sopenharmony_ci return FALSE; 3970d163575Sopenharmony_ci} 3980d163575Sopenharmony_ci 3990d163575Sopenharmony_ci/* Set the mode data bit,for consumer's mode comparing. */ 4000d163575Sopenharmony_ciSTATIC INT32 MqueueModeAnalysisSet(struct mqpersonal *privateMqPersonal) 4010d163575Sopenharmony_ci{ 4020d163575Sopenharmony_ci UINT32 mode; 4030d163575Sopenharmony_ci UINT32 intSave; 4040d163575Sopenharmony_ci User *user = NULL; 4050d163575Sopenharmony_ci struct mqarray *mqueueCB = NULL; 4060d163575Sopenharmony_ci 4070d163575Sopenharmony_ci if ((INT32)(UINTPTR)privateMqPersonal < 0) { 4080d163575Sopenharmony_ci return -1; 4090d163575Sopenharmony_ci } 4100d163575Sopenharmony_ci /* Get mqueueCB of first time creating mqueue */ 4110d163575Sopenharmony_ci mqueueCB = privateMqPersonal->mq_posixdes; 4120d163575Sopenharmony_ci if (mqueueCB == NULL) { 4130d163575Sopenharmony_ci errno = ENFILE; 4140d163575Sopenharmony_ci return -1; 4150d163575Sopenharmony_ci } 4160d163575Sopenharmony_ci 4170d163575Sopenharmony_ci mode = mqueueCB->mq_personal->mq_mode; 4180d163575Sopenharmony_ci /* Set mqueue gid uid */ 4190d163575Sopenharmony_ci SCHEDULER_LOCK(intSave); 4200d163575Sopenharmony_ci user = OsCurrUserGet(); 4210d163575Sopenharmony_ci mqueueCB->euid = user->effUserID; 4220d163575Sopenharmony_ci mqueueCB->egid = user->effGid; 4230d163575Sopenharmony_ci SCHEDULER_UNLOCK(intSave); 4240d163575Sopenharmony_ci 4250d163575Sopenharmony_ci /* Set mode data bit */ 4260d163575Sopenharmony_ci if (mode & S_IRUSR) { 4270d163575Sopenharmony_ci mqueueCB->mode_data.usr |= S_IRUSR; 4280d163575Sopenharmony_ci } 4290d163575Sopenharmony_ci if (mode & S_IWUSR) { 4300d163575Sopenharmony_ci mqueueCB->mode_data.usr |= S_IWUSR; 4310d163575Sopenharmony_ci } 4320d163575Sopenharmony_ci if (mode & S_IRGRP) { 4330d163575Sopenharmony_ci mqueueCB->mode_data.grp |= S_IRGRP; 4340d163575Sopenharmony_ci } 4350d163575Sopenharmony_ci if (mode & S_IWGRP) { 4360d163575Sopenharmony_ci mqueueCB->mode_data.grp |= S_IWGRP; 4370d163575Sopenharmony_ci } 4380d163575Sopenharmony_ci if (mode & S_IROTH) { 4390d163575Sopenharmony_ci mqueueCB->mode_data.oth |= S_IROTH; 4400d163575Sopenharmony_ci } 4410d163575Sopenharmony_ci if (mode & S_IWOTH) { 4420d163575Sopenharmony_ci mqueueCB->mode_data.oth |= S_IWOTH; 4430d163575Sopenharmony_ci } 4440d163575Sopenharmony_ci return 0; 4450d163575Sopenharmony_ci} 4460d163575Sopenharmony_ci 4470d163575Sopenharmony_ciSTATIC INT32 GetPermissionOfVisitor(struct mqarray *mqueueCB) 4480d163575Sopenharmony_ci{ 4490d163575Sopenharmony_ci uid_t euid; 4500d163575Sopenharmony_ci gid_t egid; 4510d163575Sopenharmony_ci UINT32 intSave; 4520d163575Sopenharmony_ci User *user = NULL; 4530d163575Sopenharmony_ci 4540d163575Sopenharmony_ci if (mqueueCB == NULL) { 4550d163575Sopenharmony_ci errno = ENOENT; 4560d163575Sopenharmony_ci return -EPERM; 4570d163575Sopenharmony_ci } 4580d163575Sopenharmony_ci 4590d163575Sopenharmony_ci /* Get the visitor process euid and egid */ 4600d163575Sopenharmony_ci SCHEDULER_LOCK(intSave); 4610d163575Sopenharmony_ci user = OsCurrUserGet(); 4620d163575Sopenharmony_ci euid = user->effUserID; 4630d163575Sopenharmony_ci egid = user->effGid; 4640d163575Sopenharmony_ci SCHEDULER_UNLOCK(intSave); 4650d163575Sopenharmony_ci 4660d163575Sopenharmony_ci /* root */ 4670d163575Sopenharmony_ci if (euid == 0) { 4680d163575Sopenharmony_ci return ENOERR; 4690d163575Sopenharmony_ci } 4700d163575Sopenharmony_ci if (euid == mqueueCB->euid) { /* usr */ 4710d163575Sopenharmony_ci if (!((mqueueCB->mode_data.usr & S_IRUSR) || (mqueueCB->mode_data.usr & S_IWUSR))) { 4720d163575Sopenharmony_ci errno = EACCES; 4730d163575Sopenharmony_ci goto ERR_OUT; 4740d163575Sopenharmony_ci } 4750d163575Sopenharmony_ci } else if (egid == mqueueCB->egid) { /* grp */ 4760d163575Sopenharmony_ci if (!((mqueueCB->mode_data.grp & S_IRGRP) || (mqueueCB->mode_data.grp & S_IWGRP))) { 4770d163575Sopenharmony_ci errno = EACCES; 4780d163575Sopenharmony_ci goto ERR_OUT; 4790d163575Sopenharmony_ci } 4800d163575Sopenharmony_ci } else { /* oth */ 4810d163575Sopenharmony_ci if (!((mqueueCB->mode_data.oth & S_IROTH) || (mqueueCB->mode_data.oth & S_IWOTH))) { 4820d163575Sopenharmony_ci errno = EACCES; 4830d163575Sopenharmony_ci goto ERR_OUT; 4840d163575Sopenharmony_ci } 4850d163575Sopenharmony_ci } 4860d163575Sopenharmony_ci return ENOERR; 4870d163575Sopenharmony_ci 4880d163575Sopenharmony_ciERR_OUT: 4890d163575Sopenharmony_ci return -EPERM; 4900d163575Sopenharmony_ci} 4910d163575Sopenharmony_ci 4920d163575Sopenharmony_ciSTATIC INT32 GetMqueueAttr(struct mq_attr *defaultAttr, struct mq_attr *attr) 4930d163575Sopenharmony_ci{ 4940d163575Sopenharmony_ci if (attr != NULL) { 4950d163575Sopenharmony_ci if (LOS_ArchCopyFromUser(defaultAttr, attr, sizeof(struct mq_attr))) { 4960d163575Sopenharmony_ci errno = EFAULT; 4970d163575Sopenharmony_ci return -1; 4980d163575Sopenharmony_ci } 4990d163575Sopenharmony_ci if ((defaultAttr->mq_maxmsg < 0) || (defaultAttr->mq_maxmsg > (long int)USHRT_MAX) || 5000d163575Sopenharmony_ci (defaultAttr->mq_msgsize < 0) || (defaultAttr->mq_msgsize > (long int)(USHRT_MAX - sizeof(UINT32)))) { 5010d163575Sopenharmony_ci errno = EINVAL; 5020d163575Sopenharmony_ci return -1; 5030d163575Sopenharmony_ci } 5040d163575Sopenharmony_ci } 5050d163575Sopenharmony_ci return 0; 5060d163575Sopenharmony_ci} 5070d163575Sopenharmony_ci 5080d163575Sopenharmony_cimqd_t mq_open(const char *mqName, int openFlag, ...) 5090d163575Sopenharmony_ci{ 5100d163575Sopenharmony_ci struct mqarray *mqueueCB = NULL; 5110d163575Sopenharmony_ci struct mqpersonal *privateMqPersonal = (struct mqpersonal *)-1; 5120d163575Sopenharmony_ci struct mq_attr *attr = NULL; 5130d163575Sopenharmony_ci struct mq_attr defaultAttr = { 0, MQ_MAX_MSG_NUM, MQ_MAX_MSG_LEN, 0 }; 5140d163575Sopenharmony_ci va_list ap; 5150d163575Sopenharmony_ci int sysFd; 5160d163575Sopenharmony_ci mqd_t mqFd = -1; 5170d163575Sopenharmony_ci unsigned int mode = 0; 5180d163575Sopenharmony_ci 5190d163575Sopenharmony_ci if (MqNameCheck(mqName) == -1) { 5200d163575Sopenharmony_ci return (mqd_t)-1; 5210d163575Sopenharmony_ci } 5220d163575Sopenharmony_ci 5230d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&IPC_QUEUE_MUTEX); 5240d163575Sopenharmony_ci mqueueCB = GetMqueueCBByName(mqName); 5250d163575Sopenharmony_ci if ((UINT32)openFlag & (UINT32)O_CREAT) { 5260d163575Sopenharmony_ci if (mqueueCB != NULL) { 5270d163575Sopenharmony_ci if (((UINT32)openFlag & (UINT32)O_EXCL)) { 5280d163575Sopenharmony_ci errno = EEXIST; 5290d163575Sopenharmony_ci goto OUT; 5300d163575Sopenharmony_ci } 5310d163575Sopenharmony_ci privateMqPersonal = DoMqueueOpen(mqueueCB, openFlag); 5320d163575Sopenharmony_ci } else { 5330d163575Sopenharmony_ci va_start(ap, openFlag); 5340d163575Sopenharmony_ci mode = va_arg(ap, unsigned int); 5350d163575Sopenharmony_ci attr = va_arg(ap, struct mq_attr *); 5360d163575Sopenharmony_ci va_end(ap); 5370d163575Sopenharmony_ci 5380d163575Sopenharmony_ci if (GetMqueueAttr(&defaultAttr, attr)) { 5390d163575Sopenharmony_ci goto OUT; 5400d163575Sopenharmony_ci } 5410d163575Sopenharmony_ci privateMqPersonal = DoMqueueCreate(&defaultAttr, mqName, openFlag, mode); 5420d163575Sopenharmony_ci } 5430d163575Sopenharmony_ci /* Set mode data bit ,just for the first node */ 5440d163575Sopenharmony_ci if (MqueueModeAnalysisSet(privateMqPersonal)) { 5450d163575Sopenharmony_ci if ((INT32)(UINTPTR)privateMqPersonal > 0) { 5460d163575Sopenharmony_ci (VOID)DoMqueueClose(privateMqPersonal); 5470d163575Sopenharmony_ci } 5480d163575Sopenharmony_ci goto OUT; 5490d163575Sopenharmony_ci } 5500d163575Sopenharmony_ci } else { 5510d163575Sopenharmony_ci if (GetPermissionOfVisitor(mqueueCB)) { 5520d163575Sopenharmony_ci goto OUT; 5530d163575Sopenharmony_ci } 5540d163575Sopenharmony_ci privateMqPersonal = DoMqueueOpen(mqueueCB, openFlag); 5550d163575Sopenharmony_ci } 5560d163575Sopenharmony_ci 5570d163575Sopenharmony_ci if ((INT32)(UINTPTR)privateMqPersonal > 0) { 5580d163575Sopenharmony_ci /* alloc sysFd */ 5590d163575Sopenharmony_ci sysFd = MqAllocSysFd(MAX_MQ_FD, privateMqPersonal); 5600d163575Sopenharmony_ci if (sysFd == -1) { 5610d163575Sopenharmony_ci /* there are no more mq sysFd to use, close the personal */ 5620d163575Sopenharmony_ci (VOID)DoMqueueClose(privateMqPersonal); 5630d163575Sopenharmony_ci errno = ENFILE; 5640d163575Sopenharmony_ci } 5650d163575Sopenharmony_ci mqFd = (mqd_t)sysFd; 5660d163575Sopenharmony_ci } 5670d163575Sopenharmony_ciOUT: 5680d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 5690d163575Sopenharmony_ci return mqFd; 5700d163575Sopenharmony_ci} 5710d163575Sopenharmony_ci 5720d163575Sopenharmony_ciint mq_close(mqd_t personal) 5730d163575Sopenharmony_ci{ 5740d163575Sopenharmony_ci INT32 ret = -1; 5750d163575Sopenharmony_ci struct mqpersonal *privateMqPersonal = NULL; 5760d163575Sopenharmony_ci 5770d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&IPC_QUEUE_MUTEX); 5780d163575Sopenharmony_ci 5790d163575Sopenharmony_ci /* Get the personal sysFd and reset personal fd -1 */ 5800d163575Sopenharmony_ci privateMqPersonal = MqGetPrivDataBuff(personal); 5810d163575Sopenharmony_ci if (privateMqPersonal == NULL) { 5820d163575Sopenharmony_ci goto OUT_UNLOCK; 5830d163575Sopenharmony_ci } 5840d163575Sopenharmony_ci 5850d163575Sopenharmony_ci if (privateMqPersonal->mq_status != MQ_USE_MAGIC) { 5860d163575Sopenharmony_ci errno = EBADF; 5870d163575Sopenharmony_ci goto OUT_UNLOCK; 5880d163575Sopenharmony_ci } 5890d163575Sopenharmony_ci 5900d163575Sopenharmony_ci if (!MqTryClose(privateMqPersonal)) { 5910d163575Sopenharmony_ci ret = 0; 5920d163575Sopenharmony_ci goto OUT_UNLOCK; 5930d163575Sopenharmony_ci } 5940d163575Sopenharmony_ci 5950d163575Sopenharmony_ci ret = DoMqueueClose(privateMqPersonal); 5960d163575Sopenharmony_ci if (ret < 0) { 5970d163575Sopenharmony_ci goto OUT_UNLOCK; 5980d163575Sopenharmony_ci } 5990d163575Sopenharmony_ci MqFreeSysFd(personal); 6000d163575Sopenharmony_ci 6010d163575Sopenharmony_ciOUT_UNLOCK: 6020d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 6030d163575Sopenharmony_ci return ret; 6040d163575Sopenharmony_ci} 6050d163575Sopenharmony_ci 6060d163575Sopenharmony_ciint OsMqGetAttr(mqd_t personal, struct mq_attr *mqAttr) 6070d163575Sopenharmony_ci{ 6080d163575Sopenharmony_ci struct mqarray *mqueueCB = NULL; 6090d163575Sopenharmony_ci struct mqpersonal *privateMqPersonal = NULL; 6100d163575Sopenharmony_ci 6110d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&IPC_QUEUE_MUTEX); 6120d163575Sopenharmony_ci privateMqPersonal = MqGetPrivDataBuff(personal); 6130d163575Sopenharmony_ci if (privateMqPersonal == NULL) { 6140d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 6150d163575Sopenharmony_ci return -1; 6160d163575Sopenharmony_ci } 6170d163575Sopenharmony_ci 6180d163575Sopenharmony_ci if (mqAttr == NULL) { 6190d163575Sopenharmony_ci errno = EINVAL; 6200d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 6210d163575Sopenharmony_ci return -1; 6220d163575Sopenharmony_ci } 6230d163575Sopenharmony_ci 6240d163575Sopenharmony_ci if (privateMqPersonal->mq_status != MQ_USE_MAGIC) { 6250d163575Sopenharmony_ci errno = EBADF; 6260d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 6270d163575Sopenharmony_ci return -1; 6280d163575Sopenharmony_ci } 6290d163575Sopenharmony_ci 6300d163575Sopenharmony_ci mqueueCB = privateMqPersonal->mq_posixdes; 6310d163575Sopenharmony_ci mqAttr->mq_maxmsg = mqueueCB->mqcb->queueLen; 6320d163575Sopenharmony_ci mqAttr->mq_msgsize = mqueueCB->mqcb->queueSize - sizeof(UINT32); 6330d163575Sopenharmony_ci mqAttr->mq_curmsgs = mqueueCB->mqcb->readWriteableCnt[OS_QUEUE_READ]; 6340d163575Sopenharmony_ci mqAttr->mq_flags = privateMqPersonal->mq_flags; 6350d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 6360d163575Sopenharmony_ci return 0; 6370d163575Sopenharmony_ci} 6380d163575Sopenharmony_ci 6390d163575Sopenharmony_ciint OsMqSetAttr(mqd_t personal, const struct mq_attr *mqSetAttr, struct mq_attr *mqOldAttr) 6400d163575Sopenharmony_ci{ 6410d163575Sopenharmony_ci struct mqpersonal *privateMqPersonal = NULL; 6420d163575Sopenharmony_ci 6430d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&IPC_QUEUE_MUTEX); 6440d163575Sopenharmony_ci privateMqPersonal = MqGetPrivDataBuff(personal); 6450d163575Sopenharmony_ci if (privateMqPersonal == NULL) { 6460d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 6470d163575Sopenharmony_ci return -1; 6480d163575Sopenharmony_ci } 6490d163575Sopenharmony_ci 6500d163575Sopenharmony_ci if (mqSetAttr == NULL) { 6510d163575Sopenharmony_ci errno = EINVAL; 6520d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 6530d163575Sopenharmony_ci return -1; 6540d163575Sopenharmony_ci } 6550d163575Sopenharmony_ci 6560d163575Sopenharmony_ci if (privateMqPersonal->mq_status != MQ_USE_MAGIC) { 6570d163575Sopenharmony_ci errno = EBADF; 6580d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 6590d163575Sopenharmony_ci return -1; 6600d163575Sopenharmony_ci } 6610d163575Sopenharmony_ci 6620d163575Sopenharmony_ci if (mqOldAttr != NULL) { 6630d163575Sopenharmony_ci (VOID)OsMqGetAttr(personal, mqOldAttr); 6640d163575Sopenharmony_ci } 6650d163575Sopenharmony_ci 6660d163575Sopenharmony_ci privateMqPersonal->mq_flags = (INT32)((UINT32)privateMqPersonal->mq_flags & (UINT32)(~FNONBLOCK)); /* clear */ 6670d163575Sopenharmony_ci if (((UINT32)mqSetAttr->mq_flags & (UINT32)FNONBLOCK) == (UINT32)FNONBLOCK) { 6680d163575Sopenharmony_ci privateMqPersonal->mq_flags = (INT32)((UINT32)privateMqPersonal->mq_flags | (UINT32)FNONBLOCK); 6690d163575Sopenharmony_ci } 6700d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 6710d163575Sopenharmony_ci return 0; 6720d163575Sopenharmony_ci} 6730d163575Sopenharmony_ci 6740d163575Sopenharmony_ciint mq_getsetattr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old) 6750d163575Sopenharmony_ci{ 6760d163575Sopenharmony_ci if (new == NULL) { 6770d163575Sopenharmony_ci return OsMqGetAttr(mqd, old); 6780d163575Sopenharmony_ci } 6790d163575Sopenharmony_ci return OsMqSetAttr(mqd, new, old); 6800d163575Sopenharmony_ci} 6810d163575Sopenharmony_ci 6820d163575Sopenharmony_ciint mq_unlink(const char *mqName) 6830d163575Sopenharmony_ci{ 6840d163575Sopenharmony_ci INT32 ret = 0; 6850d163575Sopenharmony_ci struct mqarray *mqueueCB = NULL; 6860d163575Sopenharmony_ci 6870d163575Sopenharmony_ci if (MqNameCheck(mqName) == -1) { 6880d163575Sopenharmony_ci return -1; 6890d163575Sopenharmony_ci } 6900d163575Sopenharmony_ci 6910d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&IPC_QUEUE_MUTEX); 6920d163575Sopenharmony_ci mqueueCB = GetMqueueCBByName(mqName); 6930d163575Sopenharmony_ci if (mqueueCB == NULL) { 6940d163575Sopenharmony_ci errno = ENOENT; 6950d163575Sopenharmony_ci goto ERROUT_UNLOCK; 6960d163575Sopenharmony_ci } 6970d163575Sopenharmony_ci 6980d163575Sopenharmony_ci if (mqueueCB->mq_personal != NULL) { 6990d163575Sopenharmony_ci mqueueCB->unlinkflag = TRUE; 7000d163575Sopenharmony_ci } else if (mqueueCB->unlink_ref == 0) { 7010d163575Sopenharmony_ci ret = DoMqueueDelete(mqueueCB); 7020d163575Sopenharmony_ci } 7030d163575Sopenharmony_ci 7040d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 7050d163575Sopenharmony_ci return ret; 7060d163575Sopenharmony_ci 7070d163575Sopenharmony_ciERROUT_UNLOCK: 7080d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 7090d163575Sopenharmony_ci return -1; 7100d163575Sopenharmony_ci} 7110d163575Sopenharmony_ci 7120d163575Sopenharmony_ciSTATIC INT32 ConvertTimeout(long flags, const struct timespec *absTimeout, UINT64 *ticks) 7130d163575Sopenharmony_ci{ 7140d163575Sopenharmony_ci if ((UINT32)flags & (UINT32)FNONBLOCK) { 7150d163575Sopenharmony_ci *ticks = LOS_NO_WAIT; 7160d163575Sopenharmony_ci return 0; 7170d163575Sopenharmony_ci } 7180d163575Sopenharmony_ci 7190d163575Sopenharmony_ci if (absTimeout == NULL) { 7200d163575Sopenharmony_ci *ticks = LOS_WAIT_FOREVER; 7210d163575Sopenharmony_ci return 0; 7220d163575Sopenharmony_ci } 7230d163575Sopenharmony_ci 7240d163575Sopenharmony_ci if (!ValidTimeSpec(absTimeout)) { 7250d163575Sopenharmony_ci errno = EINVAL; 7260d163575Sopenharmony_ci return -1; 7270d163575Sopenharmony_ci } 7280d163575Sopenharmony_ci 7290d163575Sopenharmony_ci *ticks = OsTimeSpec2Tick(absTimeout); 7300d163575Sopenharmony_ci return 0; 7310d163575Sopenharmony_ci} 7320d163575Sopenharmony_ci 7330d163575Sopenharmony_ciSTATIC INLINE BOOL MqParamCheck(mqd_t personal, const char *msg, size_t msgLen) 7340d163575Sopenharmony_ci{ 7350d163575Sopenharmony_ci if (personal < 0) { 7360d163575Sopenharmony_ci return FALSE; 7370d163575Sopenharmony_ci } 7380d163575Sopenharmony_ci 7390d163575Sopenharmony_ci if ((msg == NULL) || (msgLen == 0)) { 7400d163575Sopenharmony_ci errno = EINVAL; 7410d163575Sopenharmony_ci return FALSE; 7420d163575Sopenharmony_ci } 7430d163575Sopenharmony_ci return TRUE; 7440d163575Sopenharmony_ci} 7450d163575Sopenharmony_ci 7460d163575Sopenharmony_ci/* 7470d163575Sopenharmony_ci * Send realtime a signal to process which registered itself 7480d163575Sopenharmony_ci * successfully by mq_notify. 7490d163575Sopenharmony_ci */ 7500d163575Sopenharmony_cistatic void MqSendNotify(struct mqarray *mqueueCB) 7510d163575Sopenharmony_ci{ 7520d163575Sopenharmony_ci struct mqnotify *mqnotify = &mqueueCB->mq_notify; 7530d163575Sopenharmony_ci 7540d163575Sopenharmony_ci if ((mqnotify->pid) && (mqueueCB->mqcb->readWriteableCnt[OS_QUEUE_READ] == 0)) { 7550d163575Sopenharmony_ci siginfo_t info; 7560d163575Sopenharmony_ci 7570d163575Sopenharmony_ci switch (mqnotify->notify.sigev_notify) { 7580d163575Sopenharmony_ci case SIGEV_SIGNAL: 7590d163575Sopenharmony_ci /* sends signal */ 7600d163575Sopenharmony_ci /* Create the siginfo structure */ 7610d163575Sopenharmony_ci info.si_signo = mqnotify->notify.sigev_signo; 7620d163575Sopenharmony_ci info.si_code = SI_MESGQ; 7630d163575Sopenharmony_ci info.si_value = mqnotify->notify.sigev_value; 7640d163575Sopenharmony_ci OsDispatch(mqnotify->pid, &info, OS_USER_KILL_PERMISSION); 7650d163575Sopenharmony_ci break; 7660d163575Sopenharmony_ci case SIGEV_NONE: 7670d163575Sopenharmony_ci default: 7680d163575Sopenharmony_ci break; 7690d163575Sopenharmony_ci } 7700d163575Sopenharmony_ci /* after notification unregisters process */ 7710d163575Sopenharmony_ci mqnotify->pid = 0; 7720d163575Sopenharmony_ci } 7730d163575Sopenharmony_ci} 7740d163575Sopenharmony_ci 7750d163575Sopenharmony_ci#define OS_MQ_GOTO_ERROUT_UNLOCK_IF(expr, errcode) \ 7760d163575Sopenharmony_ci if (expr) { \ 7770d163575Sopenharmony_ci errno = errcode; \ 7780d163575Sopenharmony_ci goto ERROUT_UNLOCK; \ 7790d163575Sopenharmony_ci } 7800d163575Sopenharmony_ci#define OS_MQ_GOTO_ERROUT_IF(expr, errcode) \ 7810d163575Sopenharmony_ci if (expr) { \ 7820d163575Sopenharmony_ci errno = errcode; \ 7830d163575Sopenharmony_ci goto ERROUT; \ 7840d163575Sopenharmony_ci } 7850d163575Sopenharmony_ciint mq_timedsend(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio, 7860d163575Sopenharmony_ci const struct timespec *absTimeout) 7870d163575Sopenharmony_ci{ 7880d163575Sopenharmony_ci UINT32 mqueueID, err; 7890d163575Sopenharmony_ci UINT64 absTicks; 7900d163575Sopenharmony_ci struct mqarray *mqueueCB = NULL; 7910d163575Sopenharmony_ci struct mqpersonal *privateMqPersonal = NULL; 7920d163575Sopenharmony_ci 7930d163575Sopenharmony_ci OS_MQ_GOTO_ERROUT_IF(!MqParamCheck(personal, msg, msgLen), errno); 7940d163575Sopenharmony_ci OS_MQ_GOTO_ERROUT_IF(msgPrio > (MQ_PRIO_MAX - 1), EINVAL); 7950d163575Sopenharmony_ci 7960d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&IPC_QUEUE_MUTEX); 7970d163575Sopenharmony_ci privateMqPersonal = MqGetPrivDataBuff(personal); 7980d163575Sopenharmony_ci 7990d163575Sopenharmony_ci OS_MQ_GOTO_ERROUT_UNLOCK_IF(privateMqPersonal == NULL || privateMqPersonal->mq_status != MQ_USE_MAGIC, EBADF); 8000d163575Sopenharmony_ci 8010d163575Sopenharmony_ci mqueueCB = privateMqPersonal->mq_posixdes; 8020d163575Sopenharmony_ci OS_MQ_GOTO_ERROUT_UNLOCK_IF(msgLen > (size_t)(mqueueCB->mqcb->queueSize - sizeof(UINT32)), EMSGSIZE); 8030d163575Sopenharmony_ci 8040d163575Sopenharmony_ci OS_MQ_GOTO_ERROUT_UNLOCK_IF((((UINT32)privateMqPersonal->mq_flags & (UINT32)O_WRONLY) != (UINT32)O_WRONLY) && 8050d163575Sopenharmony_ci (((UINT32)privateMqPersonal->mq_flags & (UINT32)O_RDWR) != (UINT32)O_RDWR), 8060d163575Sopenharmony_ci EBADF); 8070d163575Sopenharmony_ci 8080d163575Sopenharmony_ci OS_MQ_GOTO_ERROUT_UNLOCK_IF(ConvertTimeout(privateMqPersonal->mq_flags, absTimeout, &absTicks) == -1, errno); 8090d163575Sopenharmony_ci mqueueID = mqueueCB->mq_id; 8100d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 8110d163575Sopenharmony_ci 8120d163575Sopenharmony_ci if (LOS_ListEmpty(&mqueueCB->mqcb->readWriteList[OS_QUEUE_READ])) { 8130d163575Sopenharmony_ci MqSendNotify(mqueueCB); 8140d163575Sopenharmony_ci } 8150d163575Sopenharmony_ci 8160d163575Sopenharmony_ci err = LOS_QueueWriteCopy(mqueueID, (VOID *)msg, (UINT32)msgLen, (UINT32)absTicks); 8170d163575Sopenharmony_ci if (map_errno(err) != ENOERR) { 8180d163575Sopenharmony_ci goto ERROUT; 8190d163575Sopenharmony_ci } 8200d163575Sopenharmony_ci return 0; 8210d163575Sopenharmony_ciERROUT_UNLOCK: 8220d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 8230d163575Sopenharmony_ciERROUT: 8240d163575Sopenharmony_ci return -1; 8250d163575Sopenharmony_ci} 8260d163575Sopenharmony_ci 8270d163575Sopenharmony_cissize_t mq_timedreceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio, 8280d163575Sopenharmony_ci const struct timespec *absTimeout) 8290d163575Sopenharmony_ci{ 8300d163575Sopenharmony_ci UINT32 mqueueID, err; 8310d163575Sopenharmony_ci UINT32 receiveLen; 8320d163575Sopenharmony_ci UINT64 absTicks; 8330d163575Sopenharmony_ci struct mqarray *mqueueCB = NULL; 8340d163575Sopenharmony_ci struct mqpersonal *privateMqPersonal = NULL; 8350d163575Sopenharmony_ci 8360d163575Sopenharmony_ci if (!MqParamCheck(personal, msg, msgLen)) { 8370d163575Sopenharmony_ci goto ERROUT; 8380d163575Sopenharmony_ci } 8390d163575Sopenharmony_ci 8400d163575Sopenharmony_ci if (msgPrio != NULL) { 8410d163575Sopenharmony_ci *msgPrio = 0; 8420d163575Sopenharmony_ci } 8430d163575Sopenharmony_ci 8440d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&IPC_QUEUE_MUTEX); 8450d163575Sopenharmony_ci privateMqPersonal = MqGetPrivDataBuff(personal); 8460d163575Sopenharmony_ci if (privateMqPersonal == NULL || privateMqPersonal->mq_status != MQ_USE_MAGIC) { 8470d163575Sopenharmony_ci errno = EBADF; 8480d163575Sopenharmony_ci goto ERROUT_UNLOCK; 8490d163575Sopenharmony_ci } 8500d163575Sopenharmony_ci 8510d163575Sopenharmony_ci mqueueCB = privateMqPersonal->mq_posixdes; 8520d163575Sopenharmony_ci if (msgLen < (size_t)(mqueueCB->mqcb->queueSize - sizeof(UINT32))) { 8530d163575Sopenharmony_ci errno = EMSGSIZE; 8540d163575Sopenharmony_ci goto ERROUT_UNLOCK; 8550d163575Sopenharmony_ci } 8560d163575Sopenharmony_ci 8570d163575Sopenharmony_ci if (((UINT32)privateMqPersonal->mq_flags & (UINT32)O_WRONLY) == (UINT32)O_WRONLY) { 8580d163575Sopenharmony_ci errno = EBADF; 8590d163575Sopenharmony_ci goto ERROUT_UNLOCK; 8600d163575Sopenharmony_ci } 8610d163575Sopenharmony_ci 8620d163575Sopenharmony_ci if (ConvertTimeout(privateMqPersonal->mq_flags, absTimeout, &absTicks) == -1) { 8630d163575Sopenharmony_ci goto ERROUT_UNLOCK; 8640d163575Sopenharmony_ci } 8650d163575Sopenharmony_ci 8660d163575Sopenharmony_ci receiveLen = msgLen; 8670d163575Sopenharmony_ci mqueueID = mqueueCB->mq_id; 8680d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 8690d163575Sopenharmony_ci 8700d163575Sopenharmony_ci err = LOS_QueueReadCopy(mqueueID, (VOID *)msg, &receiveLen, (UINT32)absTicks); 8710d163575Sopenharmony_ci if (map_errno(err) == ENOERR) { 8720d163575Sopenharmony_ci return (ssize_t)receiveLen; 8730d163575Sopenharmony_ci } else { 8740d163575Sopenharmony_ci goto ERROUT; 8750d163575Sopenharmony_ci } 8760d163575Sopenharmony_ci 8770d163575Sopenharmony_ciERROUT_UNLOCK: 8780d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 8790d163575Sopenharmony_ciERROUT: 8800d163575Sopenharmony_ci return -1; 8810d163575Sopenharmony_ci} 8820d163575Sopenharmony_ci 8830d163575Sopenharmony_ci/* not support the prio */ 8840d163575Sopenharmony_ciint mq_send(mqd_t personal, const char *msg_ptr, size_t msg_len, unsigned int msg_prio) 8850d163575Sopenharmony_ci{ 8860d163575Sopenharmony_ci return mq_timedsend(personal, msg_ptr, msg_len, msg_prio, NULL); 8870d163575Sopenharmony_ci} 8880d163575Sopenharmony_ci 8890d163575Sopenharmony_cissize_t mq_receive(mqd_t personal, char *msg_ptr, size_t msg_len, unsigned int *msg_prio) 8900d163575Sopenharmony_ci{ 8910d163575Sopenharmony_ci return mq_timedreceive(personal, msg_ptr, msg_len, msg_prio, NULL); 8920d163575Sopenharmony_ci} 8930d163575Sopenharmony_ci 8940d163575Sopenharmony_ciSTATIC INLINE BOOL MqNotifyParamCheck(mqd_t personal, const struct sigevent *sigev) 8950d163575Sopenharmony_ci{ 8960d163575Sopenharmony_ci if (personal < 0) { 8970d163575Sopenharmony_ci errno = EBADF; 8980d163575Sopenharmony_ci goto ERROUT; 8990d163575Sopenharmony_ci } 9000d163575Sopenharmony_ci 9010d163575Sopenharmony_ci if (sigev != NULL) { 9020d163575Sopenharmony_ci if (sigev->sigev_notify != SIGEV_NONE && sigev->sigev_notify != SIGEV_SIGNAL) { 9030d163575Sopenharmony_ci errno = EINVAL; 9040d163575Sopenharmony_ci goto ERROUT; 9050d163575Sopenharmony_ci } 9060d163575Sopenharmony_ci if (sigev->sigev_notify == SIGEV_SIGNAL && !GOOD_SIGNO(sigev->sigev_signo)) { 9070d163575Sopenharmony_ci errno = EINVAL; 9080d163575Sopenharmony_ci goto ERROUT; 9090d163575Sopenharmony_ci } 9100d163575Sopenharmony_ci } 9110d163575Sopenharmony_ci 9120d163575Sopenharmony_ci return TRUE; 9130d163575Sopenharmony_ciERROUT: 9140d163575Sopenharmony_ci return FALSE; 9150d163575Sopenharmony_ci} 9160d163575Sopenharmony_ci 9170d163575Sopenharmony_ciint OsMqNotify(mqd_t personal, const struct sigevent *sigev) 9180d163575Sopenharmony_ci{ 9190d163575Sopenharmony_ci struct mqarray *mqueueCB = NULL; 9200d163575Sopenharmony_ci struct mqnotify *mqnotify = NULL; 9210d163575Sopenharmony_ci struct mqpersonal *privateMqPersonal = NULL; 9220d163575Sopenharmony_ci 9230d163575Sopenharmony_ci if (!MqNotifyParamCheck(personal, sigev)) { 9240d163575Sopenharmony_ci goto ERROUT; 9250d163575Sopenharmony_ci } 9260d163575Sopenharmony_ci 9270d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&IPC_QUEUE_MUTEX); 9280d163575Sopenharmony_ci privateMqPersonal = MqGetPrivDataBuff(personal); 9290d163575Sopenharmony_ci if (privateMqPersonal == NULL) { 9300d163575Sopenharmony_ci goto OUT_UNLOCK; 9310d163575Sopenharmony_ci } 9320d163575Sopenharmony_ci 9330d163575Sopenharmony_ci if (privateMqPersonal->mq_status != MQ_USE_MAGIC) { 9340d163575Sopenharmony_ci errno = EBADF; 9350d163575Sopenharmony_ci goto OUT_UNLOCK; 9360d163575Sopenharmony_ci } 9370d163575Sopenharmony_ci 9380d163575Sopenharmony_ci mqueueCB = privateMqPersonal->mq_posixdes; 9390d163575Sopenharmony_ci mqnotify = &mqueueCB->mq_notify; 9400d163575Sopenharmony_ci 9410d163575Sopenharmony_ci if (sigev == NULL) { 9420d163575Sopenharmony_ci if (mqnotify->pid == LOS_GetCurrProcessID()) { 9430d163575Sopenharmony_ci mqnotify->pid = 0; 9440d163575Sopenharmony_ci } 9450d163575Sopenharmony_ci } else if (mqnotify->pid != 0) { 9460d163575Sopenharmony_ci errno = EBUSY; 9470d163575Sopenharmony_ci goto OUT_UNLOCK; 9480d163575Sopenharmony_ci } else { 9490d163575Sopenharmony_ci switch (sigev->sigev_notify) { 9500d163575Sopenharmony_ci case SIGEV_NONE: 9510d163575Sopenharmony_ci mqnotify->notify.sigev_notify = SIGEV_NONE; 9520d163575Sopenharmony_ci break; 9530d163575Sopenharmony_ci case SIGEV_SIGNAL: 9540d163575Sopenharmony_ci mqnotify->notify.sigev_signo = sigev->sigev_signo; 9550d163575Sopenharmony_ci mqnotify->notify.sigev_value = sigev->sigev_value; 9560d163575Sopenharmony_ci mqnotify->notify.sigev_notify = SIGEV_SIGNAL; 9570d163575Sopenharmony_ci break; 9580d163575Sopenharmony_ci default: 9590d163575Sopenharmony_ci break; 9600d163575Sopenharmony_ci } 9610d163575Sopenharmony_ci 9620d163575Sopenharmony_ci mqnotify->pid = LOS_GetCurrProcessID(); 9630d163575Sopenharmony_ci } 9640d163575Sopenharmony_ci 9650d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 9660d163575Sopenharmony_ci return 0; 9670d163575Sopenharmony_ciOUT_UNLOCK: 9680d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&IPC_QUEUE_MUTEX); 9690d163575Sopenharmony_ciERROUT: 9700d163575Sopenharmony_ci return -1; 9710d163575Sopenharmony_ci} 9720d163575Sopenharmony_ci 9730d163575Sopenharmony_ciVOID OsMqueueCBDestroy(struct mqarray *queueTable) 9740d163575Sopenharmony_ci{ 9750d163575Sopenharmony_ci if (queueTable == NULL) { 9760d163575Sopenharmony_ci return; 9770d163575Sopenharmony_ci } 9780d163575Sopenharmony_ci 9790d163575Sopenharmony_ci for (UINT32 index = 0; index < LOSCFG_BASE_IPC_QUEUE_LIMIT; index++) { 9800d163575Sopenharmony_ci struct mqarray *mqueueCB = &(queueTable[index]); 9810d163575Sopenharmony_ci if (mqueueCB->mq_name == NULL) { 9820d163575Sopenharmony_ci continue; 9830d163575Sopenharmony_ci } 9840d163575Sopenharmony_ci (VOID)DoMqueueClose(mqueueCB->mq_personal); 9850d163575Sopenharmony_ci } 9860d163575Sopenharmony_ci} 9870d163575Sopenharmony_ci#endif 988