source: rtems/cpukit/posix/src/shmopen.c @ ea4488ae

Last change on this file since ea4488ae was ea4488ae, checked in by Joel Sherrill <joel@…>, on Aug 2, 2017 at 11:26:51 PM

posix shm: Add oflag to Shm_Control

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/**
2 * @file
3 */
4
5/*
6 * Copyright (c) 2016 Gedare Bloom.
7 *
8 * The license and distribution terms for this file may be
9 * found in the file LICENSE in this distribution or at
10 * http://www.rtems.org/license/LICENSE.
11 */
12
13#if HAVE_CONFIG_H
14#include "config.h"
15#endif
16
17#include <sys/mman.h>
18#include <errno.h>
19#include <unistd.h>
20#include <fcntl.h>
21#include <sys/stat.h>
22
23#include <rtems/libio_.h>
24#include <rtems/seterr.h>
25
26#include <rtems/posix/shmimpl.h>
27#include <rtems/score/wkspace.h>
28
29static const rtems_filesystem_file_handlers_r shm_handlers;
30
31static int shm_fstat(
32  const rtems_filesystem_location_info_t *loc,
33  struct stat *buf
34)
35{
36  POSIX_Shm_Control *shm = loc_to_shm( loc );
37
38  if ( shm == NULL )
39    rtems_set_errno_and_return_minus_one( EIO );
40
41  /* mandatory for shm objects */
42  buf->st_uid = shm->uid;
43  buf->st_gid = shm->gid;
44  buf->st_size = shm->shm_object.size;
45  buf->st_mode = shm->mode;
46
47  /* optional for shm objects */
48  buf->st_atime = shm->atime;
49  buf->st_mtime = shm->mtime;
50  buf->st_ctime = shm->ctime;
51
52  return 0;
53}
54
55/* read() is unspecified for shared memory objects */
56static ssize_t shm_read( rtems_libio_t *iop, void *buffer, size_t count )
57{
58  ssize_t bytes_read;
59  POSIX_Shm_Control *shm = iop_to_shm( iop );
60
61  _Objects_Allocator_lock();
62  bytes_read = (*shm->shm_object.ops->object_read)(
63      &shm->shm_object,
64      buffer,
65      count
66  );
67  _POSIX_Shm_Update_atime( shm );
68
69  _Objects_Allocator_unlock();
70  return bytes_read;
71}
72
73static int shm_ftruncate( rtems_libio_t *iop, off_t length )
74{
75  int err;
76  POSIX_Shm_Control *shm = iop_to_shm( iop );
77
78  _Objects_Allocator_lock();
79
80  err = (*shm->shm_object.ops->object_resize)( &shm->shm_object, length );
81
82  if ( err != 0 ) {
83    _Objects_Allocator_unlock();
84    rtems_set_errno_and_return_minus_one( err );
85  }
86
87  _POSIX_Shm_Update_mtime_ctime( shm );
88
89  _Objects_Allocator_unlock();
90  return 0;
91}
92
93static int shm_close( rtems_libio_t *iop )
94{
95  POSIX_Shm_Control *shm = iop_to_shm( iop );
96  int err;
97
98  err = 0;
99
100  POSIX_Shm_Attempt_delete(shm);
101  iop->pathinfo.node_access = NULL;
102
103  if ( err != 0 ) {
104    rtems_set_errno_and_return_minus_one( err );
105  }
106  return 0;
107}
108
109static int shm_mmap(
110  rtems_libio_t *iop,
111  void** addr,
112  size_t len,
113  int prot,
114  off_t off
115)
116{
117  POSIX_Shm_Control *shm = iop_to_shm( iop );
118
119  _Objects_Allocator_lock();
120
121  *addr = (*shm->shm_object.ops->object_mmap)( &shm->shm_object, len, prot, off);
122  if ( *addr != NULL ) {
123    /* Keep a reference in the shared memory to prevent its removal. */
124    ++shm->reference_count;
125
126    /* Update atime */
127    _POSIX_Shm_Update_atime(shm);
128  } else {
129    _Objects_Allocator_unlock();
130    rtems_set_errno_and_return_minus_one( ENOMEM );
131  }
132
133  _Objects_Allocator_unlock();
134
135  return 0;
136}
137
138static inline POSIX_Shm_Control *shm_allocate(
139  const char *name_arg,
140  size_t name_len,
141  int oflag,
142  mode_t mode,
143  int *error
144)
145{
146  POSIX_Shm_Control *shm;
147  char *name;
148  struct timeval tv;
149
150  /* Reject any name without a leading slash. */
151  if ( name_arg[0] != '/' ) {
152    *error = EINVAL;
153    return NULL;
154  }
155
156  /* Only create the object if requested. */
157  if ( ( oflag & O_CREAT ) != O_CREAT ) {
158    *error = ENOENT;
159    return NULL;
160  }
161
162  name = _Workspace_String_duplicate( name_arg, name_len );
163  if ( name == NULL ) {
164    *error = ENOSPC;
165    return NULL;
166  }
167
168  shm = _POSIX_Shm_Allocate_unprotected();
169  if ( shm == NULL ) {
170    _Workspace_Free( name );
171    *error = ENFILE;
172    return NULL;
173  }
174
175  gettimeofday( &tv, 0 );
176
177  shm->reference_count = 1;
178  shm->shm_object.handle = NULL;
179  shm->shm_object.size = 0;
180  shm->shm_object.ops = &_POSIX_Shm_Object_operations;
181  shm->mode = mode & ~rtems_filesystem_umask;
182  shm->oflag = oflag;
183  shm->uid = geteuid();
184  shm->gid = getegid();
185  shm->atime = (time_t) tv.tv_sec;
186  shm->mtime = (time_t) tv.tv_sec;
187  shm->ctime = (time_t) tv.tv_sec;
188
189  _Objects_Open_string( &_POSIX_Shm_Information, &shm->Object, name );
190
191  return shm;
192}
193
194static inline bool shm_access_ok( POSIX_Shm_Control *shm, int oflag )
195{
196  int flags;
197  if ( oflag & O_RDONLY ) {
198    flags = RTEMS_FS_PERMS_READ;
199  } else {
200    flags = RTEMS_FS_PERMS_WRITE;
201  }
202  return rtems_filesystem_check_access( flags, shm->mode, shm->uid, shm->gid );
203}
204
205static inline int shm_check_oflag( int oflag )
206{
207  if ( ( oflag & O_ACCMODE ) != O_RDONLY && ( oflag & O_ACCMODE ) != O_RDWR ) {
208    rtems_set_errno_and_return_minus_one( EACCES );
209  }
210
211  if ( ( oflag & ~( O_RDONLY | O_RDWR | O_CREAT | O_EXCL | O_TRUNC ) ) != 0 ) {
212    rtems_set_errno_and_return_minus_one( EACCES );
213  }
214
215  if ( ( oflag & O_TRUNC ) != 0 && ( oflag & O_ACCMODE ) != O_RDWR ) {
216    rtems_set_errno_and_return_minus_one( EACCES );
217  }
218  return 0;
219}
220
221int shm_open( const char *name, int oflag, mode_t mode )
222{
223  int err = 0;
224  int fd;
225  rtems_libio_t *iop;
226  POSIX_Shm_Control *shm;
227  size_t len;
228  Objects_Get_by_name_error obj_err;
229  unsigned int flags;
230
231  if ( shm_check_oflag( oflag ) != 0 ) {
232    return -1;
233  }
234
235  iop = rtems_libio_allocate();
236  if ( iop == NULL ) {
237    rtems_set_errno_and_return_minus_one( EMFILE );
238  }
239
240  _Objects_Allocator_lock();
241  shm = _POSIX_Shm_Get_by_name( name, &len, &obj_err );
242
243  if ( shm == NULL ) {
244    switch ( obj_err ) {
245      case OBJECTS_GET_BY_NAME_INVALID_NAME:
246        err = EINVAL;
247        break;
248
249      case OBJECTS_GET_BY_NAME_NAME_TOO_LONG:
250        err = ENAMETOOLONG;
251        break;
252
253      case OBJECTS_GET_BY_NAME_NO_OBJECT:
254      default:
255        shm = shm_allocate(name, len, oflag, mode, &err);
256        break;
257    }
258  } else { /* shm exists */
259    if ( ( oflag & ( O_EXCL | O_CREAT ) ) == ( O_EXCL | O_CREAT ) ) {
260      /* Request to create failed. */
261      err = EEXIST;
262    } else if ( !shm_access_ok( shm, oflag ) ) {
263      err = EACCES;
264    } else {
265      ++shm->reference_count;
266    }
267  }
268  _Objects_Allocator_unlock();
269  if ( err != 0 ) {
270    rtems_libio_free( iop );
271    rtems_set_errno_and_return_minus_one( err );
272  }
273
274  if ( oflag & O_TRUNC ) {
275    err = shm_ftruncate( iop, 0 );
276    (void) err; /* ignore truncate error */
277  }
278
279  fd = rtems_libio_iop_to_descriptor( iop );
280  iop->data0 = fd;
281  iop->data1 = shm;
282  iop->pathinfo.node_access = shm;
283  iop->pathinfo.handlers = &shm_handlers;
284  iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry;
285  rtems_filesystem_location_add_to_mt_entry( &iop->pathinfo );
286
287  flags = LIBIO_FLAGS_CLOSE_ON_EXEC;
288  if ( oflag & O_RDONLY ) {
289    flags |= LIBIO_FLAGS_READ;
290  } else {
291    flags |= LIBIO_FLAGS_READ_WRITE;
292  }
293
294  rtems_libio_iop_flags_initialize( iop, flags );
295
296  return fd;
297}
298
299static const rtems_filesystem_file_handlers_r shm_handlers = {
300  .open_h = rtems_filesystem_default_open,
301  .close_h = shm_close,
302  .read_h = shm_read,
303  .write_h = rtems_filesystem_default_write,
304  .ioctl_h = rtems_filesystem_default_ioctl,
305  .lseek_h = rtems_filesystem_default_lseek,
306  .fstat_h = shm_fstat,
307  .ftruncate_h = shm_ftruncate,
308  .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
309  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
310  .fcntl_h = rtems_filesystem_default_fcntl,
311  .kqfilter_h = rtems_filesystem_default_kqfilter,
312  .mmap_h = shm_mmap,
313  .poll_h = rtems_filesystem_default_poll,
314  .readv_h = rtems_filesystem_default_readv,
315  .writev_h = rtems_filesystem_default_writev
316};
Note: See TracBrowser for help on using the repository browser.