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