1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** POSIX wrapper for THREADX */
16 /** */
17 /** */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 /* Include necessary system files. */
23
24 #include "tx_api.h" /* Threadx API */
25 #include "pthread.h" /* Posix API */
26 #include "px_int.h" /* Posix helper functions */
27
28
29 /**************************************************************************/
30 /* */
31 /* FUNCTION RELEASE */
32 /* */
33 /* mq_open PORTABLE C */
34 /* 6.2.0 */
35 /* AUTHOR */
36 /* */
37 /* William E. Lamie, Microsoft Corporation */
38 /* */
39 /* DESCRIPTION */
40 /* */
41 /* This routine establishes connection between a named message queue */
42 /* and the calling a thread */
43 /* */
44 /* INPUT */
45 /* */
46 /* mqName name of the queue to open. */
47 /* oflags O_RDONLY, O_WRONLY, O_RDWR, or O_CREAT, */
48 /* O_EXCEL,O_NONBLOCK. */
49 /* extra optional parameters. */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* queue_des If successful */
54 /* ERROR If fails */
55 /* */
56 /* CALLS */
57 /* */
58 /* posix_find_queue find queue of given name */
59 /* posix_mq_create create a queue */
60 /* posix_get_queue_des gets a queue-descriptor for Queue */
61 /* */
62 /* CALLED BY */
63 /* */
64 /* Application Code */
65 /* */
66 /* RELEASE HISTORY */
67 /* */
68 /* DATE NAME DESCRIPTION */
69 /* */
70 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
71 /* 10-31-2022 Scott Larson Update comparison with NULL, */
72 /* resulting in version 6.2.0 */
73 /* */
74 /**************************************************************************/
mq_open(const CHAR * mqName,ULONG oflags,...)75 mqd_t mq_open(const CHAR * mqName, ULONG oflags,...)
76 {
77
78 POSIX_MSG_QUEUE *posix_queue;
79 struct mq_des *queue_des;
80 struct mq_attr *q_attr;
81 mode_t mode;
82 va_list create_queue;
83 ULONG len;
84 ULONG temp1;
85
86 len = strlen(mqName);
87 if(len > PATH_MAX)
88 {
89 /* Return error. */
90 posix_errno = ENAMETOOLONG;
91 posix_set_pthread_errno(ENAMETOOLONG);
92
93 /*. Return error. */
94 return((struct mq_des *)ERROR);
95 }
96 switch(oflags & 0xFF00)
97 {
98 case O_CREAT:
99
100 case (O_EXCL | O_CREAT):
101
102 va_start(create_queue, oflags);
103 mode = va_arg(create_queue, mode_t);
104 mode = mode; /* just to keep the complier happy */
105 q_attr = va_arg(create_queue, struct mq_attr *);
106 va_end(create_queue);
107
108 /* Check for valid messages and its size. */
109 if(!q_attr || q_attr->mq_maxmsg > MQ_MAXMSG || q_attr->mq_msgsize > MQ_MSGSIZE)
110 {
111 /* return POSIX error.for invalid oflag. */
112 posix_errno = EINVAL;
113 posix_set_pthread_errno(EINVAL);
114 /* return error. */
115 return ((struct mq_des *)ERROR);
116 }
117
118 /* Check if name is exist. NULL if successful. */
119 if((posix_queue = posix_find_queue(mqName)) != NULL)
120 {
121 if(posix_queue->unlink_flag == TX_TRUE)
122 {
123 /* return POSIX error. */
124 posix_errno = ENOENT;
125 posix_set_pthread_errno(ENOENT);
126 /* return error. */
127 return ((struct mq_des *)ERROR);
128 }
129
130 /* Set Posix error if name exist. */
131 posix_errno = EEXIST;
132 posix_set_pthread_errno(EEXIST);
133 /* return error */
134 return((struct mq_des *)ERROR);
135 }
136
137 /* If q_attr is NULL then the default attributes of the struct
138 mq_attr are used */
139 if(q_attr == NULL)
140 {
141 q_attr = &(posix_qattr_default);
142 temp1 = q_attr->mq_maxmsg;
143 temp1= temp1 ; /* Just to keep complier happy */
144 }
145
146 /* Create a queue which returns posix queue if successful and
147 NULL if fails. */
148 if(!(posix_queue = posix_mq_create(mqName, q_attr)))
149 {
150
151 /* posix_errno is filled up in mq_create. */
152 return((struct mq_des *)ERROR);
153 }
154 /* open count incremented by one. */
155 posix_queue->open_count += 1;
156 break;
157
158 case O_EXCL:
159 /* Check if name is exist. NULL if successful. */
160 if(!(posix_queue = posix_find_queue(mqName)))
161 {
162 /* return POSIX error. */
163 posix_errno = EBADF;
164 posix_set_pthread_errno(EBADF);
165 /* return error. */
166 return ((struct mq_des *)ERROR);
167 }
168
169 return(OK);
170
171 case O_RDONLY:
172 case O_WRONLY:
173 case O_RDWR:
174 case O_NONBLOCK:
175 /* Check if name is exist. NULL if successful. */
176 if((posix_queue = posix_find_queue(mqName)) != NULL)
177 {
178 if(posix_queue->unlink_flag == TX_TRUE)
179 {
180 /* return POSIX error. */
181 posix_errno = ENOENT;
182 posix_set_pthread_errno(ENOENT);
183 /* return error. */
184 return ((struct mq_des *)ERROR);
185 }
186 /* open count incremented by one. */
187 posix_queue->open_count += 1;
188 }
189 break;
190
191 default:
192 /* return POSIX error.for invalid oflag. */
193 posix_errno = EINVAL;
194 posix_set_pthread_errno(EINVAL);
195 /* return error. */
196 return ((struct mq_des *)ERROR);
197 }
198
199 queue_des = posix_get_queue_des(posix_queue);
200 /* Store the flags. */
201 queue_des->f_flag = oflags;
202 return(queue_des);
203 }
204