source: rtems/cpukit/posix/src/mqueueopen.c @ c499856

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/**
2 * @file
3 *
4 * @brief Creates a new POSIX Message Queue or Opens an Existing Queue
5 * @ingroup POSIXAPI
6 */
7
8/*
9 *  NOTE:  The structure of the routines is identical to that of POSIX
10 *         Message_queues to leave the option of having unnamed message
11 *         queues at a future date.  They are currently not part of the
12 *         POSIX standard but unnamed message_queues are.  This is also
13 *         the reason for the apparently unnecessary tracking of
14 *         the process_shared attribute.  [In addition to the fact that
15 *         it would be trivial to add pshared to the mq_attr structure
16 *         and have process private message queues.]
17 *
18 *         This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
19 *         time.
20 *
21 *  COPYRIGHT (c) 1989-2009.
22 *  On-Line Applications Research Corporation (OAR).
23 *
24 *  The license and distribution terms for this file may be
25 *  found in the file LICENSE in this distribution or at
26 *  http://www.rtems.org/license/LICENSE.
27 */
28
29#if HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <stdarg.h>
34
35#include <pthread.h>
36#include <limits.h>
37#include <errno.h>
38#include <fcntl.h>
39#include <mqueue.h>
40
41#include <rtems/score/todimpl.h>
42#include <rtems/score/watchdog.h>
43#include <rtems/posix/mqueueimpl.h>
44#include <rtems/posix/time.h>
45#include <rtems/seterr.h>
46
47/*
48 *  15.2.2 Open a Message Queue, P1003.1b-1993, p. 272
49 */
50mqd_t mq_open(
51  const char *name,
52  int         oflag,
53  ...
54  /* mode_t mode, */
55  /* struct mq_attr  attr */
56)
57{
58  /*
59   * mode is set but never used. GCC gives a warning for this
60   * and we need to tell GCC not to complain. But we have to
61   * have it because we have to work through the variable
62   * arguments to get to attr.
63   */
64  mode_t                          mode RTEMS_COMPILER_UNUSED_ATTRIBUTE;
65
66  va_list                         arg;
67  struct mq_attr                 *attr = NULL;
68  int                             status;
69  Objects_Id                      the_mq_id;
70  POSIX_Message_queue_Control    *the_mq;
71  POSIX_Message_queue_Control_fd *the_mq_fd;
72  Objects_Locations               location;
73  size_t                          name_len;
74
75  _Thread_Disable_dispatch();
76
77  if ( oflag & O_CREAT ) {
78    va_start(arg, oflag);
79    mode = va_arg( arg, mode_t );
80    attr = va_arg( arg, struct mq_attr * );
81    va_end(arg);
82  }
83
84  the_mq_fd = _POSIX_Message_queue_Allocate_fd();
85  if ( !the_mq_fd ) {
86    _Thread_Enable_dispatch();
87    rtems_set_errno_and_return_minus_one( ENFILE );
88  }
89  the_mq_fd->oflag = oflag;
90
91  status = _POSIX_Message_queue_Name_to_id( name, &the_mq_id, &name_len );
92
93  /*
94   *  If the name to id translation worked, then the message queue exists
95   *  and we can just return a pointer to the id.  Otherwise we may
96   *  need to check to see if this is a "message queue does not exist"
97   *  or some other miscellaneous error on the name.
98   */
99  if ( status ) {
100    /*
101     * Unless provided a valid name that did not already exist
102     * and we are willing to create then it is an error.
103     */
104    if ( !( status == ENOENT && (oflag & O_CREAT) ) ) {
105      _POSIX_Message_queue_Free_fd( the_mq_fd );
106      _Thread_Enable_dispatch();
107      rtems_set_errno_and_return_minus_one_cast( status, mqd_t );
108    }
109
110  } else {                /* name -> ID translation succeeded */
111    /*
112     * Check for existence with creation.
113     */
114    if ( (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL) ) {
115      _POSIX_Message_queue_Free_fd( the_mq_fd );
116      _Thread_Enable_dispatch();
117      rtems_set_errno_and_return_minus_one_cast( EEXIST, mqd_t );
118    }
119
120    /*
121     * In this case we need to do an ID->pointer conversion to
122     * check the mode.
123     */
124    the_mq = _POSIX_Message_queue_Get( the_mq_id, &location );
125    the_mq->open_count += 1;
126    the_mq_fd->Queue = the_mq;
127    _Objects_Open_string(
128      &_POSIX_Message_queue_Information_fds,
129      &the_mq_fd->Object,
130      NULL
131    );
132    _Thread_Enable_dispatch();
133    _Thread_Enable_dispatch();
134    return (mqd_t)the_mq_fd->Object.id;
135
136  }
137
138  /*
139   *  At this point, the message queue does not exist and everything has been
140   *  checked. We should go ahead and create a message queue.
141   */
142  status = _POSIX_Message_queue_Create_support(
143    name,
144    name_len,
145    true,         /* shared across processes */
146    attr,
147    &the_mq
148  );
149
150  /*
151   * errno was set by Create_support, so don't set it again.
152   */
153  if ( status == -1 ) {
154    _POSIX_Message_queue_Free_fd( the_mq_fd );
155    _Thread_Enable_dispatch();
156    return (mqd_t) -1;
157  }
158
159  the_mq_fd->Queue = the_mq;
160  _Objects_Open_string(
161    &_POSIX_Message_queue_Information_fds,
162    &the_mq_fd->Object,
163    NULL
164  );
165
166  _Thread_Enable_dispatch();
167
168  return (mqd_t) the_mq_fd->Object.id;
169}
Note: See TracBrowser for help on using the repository browser.