File indexing completed on 2025-05-11 08:24:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #ifdef HAVE_CONFIG_H
0033 #include "config.h"
0034 #endif
0035
0036 #include <sys/mman.h>
0037 #include <errno.h>
0038 #include <unistd.h>
0039 #include <fcntl.h>
0040 #include <sys/stat.h>
0041
0042 #include <rtems/libio_.h>
0043 #include <rtems/seterr.h>
0044
0045 #include <rtems/posix/shmimpl.h>
0046 #include <rtems/score/wkspace.h>
0047 #include <rtems/sysinit.h>
0048
0049 static const rtems_filesystem_file_handlers_r shm_handlers;
0050
0051 static int shm_fstat(
0052 const rtems_filesystem_location_info_t *loc,
0053 struct stat *buf
0054 )
0055 {
0056 POSIX_Shm_Control *shm = loc_to_shm( loc );
0057
0058 if ( shm == NULL )
0059 rtems_set_errno_and_return_minus_one( EIO );
0060
0061
0062 buf->st_uid = shm->uid;
0063 buf->st_gid = shm->gid;
0064 buf->st_size = shm->shm_object.size;
0065 buf->st_mode = shm->mode;
0066
0067
0068 buf->st_atime = shm->atime;
0069 buf->st_mtime = shm->mtime;
0070 buf->st_ctime = shm->ctime;
0071
0072 return 0;
0073 }
0074
0075
0076 static ssize_t shm_read( rtems_libio_t *iop, void *buffer, size_t count )
0077 {
0078 ssize_t bytes_read;
0079 POSIX_Shm_Control *shm = iop_to_shm( iop );
0080
0081 _Objects_Allocator_lock();
0082 bytes_read = (*shm->shm_object.ops->object_read)(
0083 &shm->shm_object,
0084 buffer,
0085 count
0086 );
0087 _POSIX_Shm_Update_atime( shm );
0088
0089 _Objects_Allocator_unlock();
0090 return bytes_read;
0091 }
0092
0093 static int shm_ftruncate( rtems_libio_t *iop, off_t length )
0094 {
0095 int err;
0096 POSIX_Shm_Control *shm = iop_to_shm( iop );
0097
0098 _Objects_Allocator_lock();
0099
0100 err = (*shm->shm_object.ops->object_resize)( &shm->shm_object, length );
0101
0102 if ( err != 0 ) {
0103 _Objects_Allocator_unlock();
0104 rtems_set_errno_and_return_minus_one( err );
0105 }
0106
0107 _POSIX_Shm_Update_mtime_ctime( shm );
0108
0109 _Objects_Allocator_unlock();
0110 return 0;
0111 }
0112
0113 static int shm_close( rtems_libio_t *iop )
0114 {
0115 POSIX_Shm_Control *shm = iop_to_shm( iop );
0116 int err;
0117
0118 err = 0;
0119
0120 POSIX_Shm_Attempt_delete(shm);
0121 iop->pathinfo.node_access = NULL;
0122
0123 if ( err != 0 ) {
0124 rtems_set_errno_and_return_minus_one( err );
0125 }
0126 return 0;
0127 }
0128
0129 static int shm_mmap(
0130 rtems_libio_t *iop,
0131 void** addr,
0132 size_t len,
0133 int prot,
0134 off_t off
0135 )
0136 {
0137 POSIX_Shm_Control *shm = iop_to_shm( iop );
0138
0139 _Objects_Allocator_lock();
0140
0141 *addr = (*shm->shm_object.ops->object_mmap)( &shm->shm_object, len, prot, off);
0142 if ( *addr != NULL ) {
0143
0144 ++shm->reference_count;
0145
0146
0147 _POSIX_Shm_Update_atime(shm);
0148 } else {
0149 _Objects_Allocator_unlock();
0150 rtems_set_errno_and_return_minus_one( ENOMEM );
0151 }
0152
0153 _Objects_Allocator_unlock();
0154
0155 return 0;
0156 }
0157
0158 static inline POSIX_Shm_Control *shm_allocate(
0159 const char *name_arg,
0160 size_t name_len,
0161 int oflag,
0162 mode_t mode,
0163 int *error
0164 )
0165 {
0166 POSIX_Shm_Control *shm;
0167 char *name;
0168 struct timeval tv;
0169
0170
0171 if ( name_arg[0] != '/' ) {
0172 *error = EINVAL;
0173 return NULL;
0174 }
0175
0176
0177 if ( ( oflag & O_CREAT ) != O_CREAT ) {
0178 *error = ENOENT;
0179 return NULL;
0180 }
0181
0182 name = _Workspace_String_duplicate( name_arg, name_len );
0183 if ( name == NULL ) {
0184 *error = ENOSPC;
0185 return NULL;
0186 }
0187
0188 shm = _POSIX_Shm_Allocate_unprotected();
0189 if ( shm == NULL ) {
0190 _Workspace_Free( name );
0191 *error = ENFILE;
0192 return NULL;
0193 }
0194
0195 gettimeofday( &tv, 0 );
0196
0197 shm->reference_count = 1;
0198 shm->shm_object.handle = NULL;
0199 shm->shm_object.size = 0;
0200 shm->shm_object.ops = &_POSIX_Shm_Object_operations;
0201 shm->mode = mode & ~rtems_filesystem_umask;
0202 shm->oflag = oflag;
0203 shm->uid = geteuid();
0204 shm->gid = getegid();
0205 shm->atime = (time_t) tv.tv_sec;
0206 shm->mtime = (time_t) tv.tv_sec;
0207 shm->ctime = (time_t) tv.tv_sec;
0208
0209 _Objects_Open_string( &_POSIX_Shm_Information, &shm->Object, name );
0210
0211 return shm;
0212 }
0213
0214 static inline bool shm_access_ok( POSIX_Shm_Control *shm, int oflag )
0215 {
0216 int flags;
0217
0218 if ( (oflag & O_ACCMODE) == O_RDONLY ) {
0219 flags = RTEMS_FS_PERMS_READ;
0220 } else {
0221 flags = RTEMS_FS_PERMS_WRITE;
0222 }
0223 return rtems_filesystem_check_access( flags, shm->mode, shm->uid, shm->gid );
0224 }
0225
0226 static inline int shm_check_oflag( int oflag )
0227 {
0228 if ( ( oflag & O_ACCMODE ) != O_RDONLY && ( oflag & O_ACCMODE ) != O_RDWR ) {
0229 rtems_set_errno_and_return_minus_one( EACCES );
0230 }
0231
0232 if ( ( oflag & ~( O_RDONLY | O_RDWR | O_CREAT | O_EXCL | O_TRUNC ) ) != 0 ) {
0233 rtems_set_errno_and_return_minus_one( EACCES );
0234 }
0235
0236 if ( ( oflag & O_TRUNC ) != 0 && ( oflag & O_ACCMODE ) != O_RDWR ) {
0237 rtems_set_errno_and_return_minus_one( EACCES );
0238 }
0239 return 0;
0240 }
0241
0242 int shm_open( const char *name, int oflag, mode_t mode )
0243 {
0244 int err = 0;
0245 int fd;
0246 rtems_libio_t *iop;
0247 POSIX_Shm_Control *shm;
0248 size_t len;
0249 Objects_Get_by_name_error obj_err;
0250 unsigned int flags;
0251
0252 if ( shm_check_oflag( oflag ) != 0 ) {
0253 return -1;
0254 }
0255
0256 iop = rtems_libio_allocate();
0257 if ( iop == NULL ) {
0258 rtems_set_errno_and_return_minus_one( EMFILE );
0259 }
0260
0261 _Objects_Allocator_lock();
0262 shm = _POSIX_Shm_Get_by_name( name, &len, &obj_err );
0263
0264 if ( shm == NULL ) {
0265 switch ( obj_err ) {
0266 case OBJECTS_GET_BY_NAME_INVALID_NAME:
0267 err = EINVAL;
0268 break;
0269
0270 case OBJECTS_GET_BY_NAME_NAME_TOO_LONG:
0271 err = ENAMETOOLONG;
0272 break;
0273
0274 case OBJECTS_GET_BY_NAME_NO_OBJECT:
0275 default:
0276 shm = shm_allocate(name, len, oflag, mode, &err);
0277 break;
0278 }
0279 } else {
0280 if ( ( oflag & ( O_EXCL | O_CREAT ) ) == ( O_EXCL | O_CREAT ) ) {
0281
0282 err = EEXIST;
0283 } else if ( !shm_access_ok( shm, oflag ) ) {
0284 err = EACCES;
0285 } else {
0286 ++shm->reference_count;
0287 }
0288 }
0289 _Objects_Allocator_unlock();
0290 if ( err != 0 ) {
0291 rtems_libio_free( iop );
0292 rtems_set_errno_and_return_minus_one( err );
0293 }
0294
0295 if ( oflag & O_TRUNC ) {
0296 err = shm_ftruncate( iop, 0 );
0297 (void) err;
0298 }
0299
0300 fd = rtems_libio_iop_to_descriptor( iop );
0301 iop->data0 = fd;
0302 iop->data1 = shm;
0303 iop->pathinfo.node_access = shm;
0304 iop->pathinfo.handlers = &shm_handlers;
0305 iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry;
0306 rtems_filesystem_location_add_to_mt_entry( &iop->pathinfo );
0307
0308 flags = LIBIO_FLAGS_OPEN | LIBIO_FLAGS_CLOSE_ON_EXEC;
0309 if ( (oflag & O_ACCMODE) == O_RDONLY ) {
0310 flags |= LIBIO_FLAGS_READ;
0311 } else {
0312 flags |= LIBIO_FLAGS_READ_WRITE;
0313 }
0314
0315 rtems_libio_iop_flags_set( iop, flags );
0316
0317 return fd;
0318 }
0319
0320 static const rtems_filesystem_file_handlers_r shm_handlers = {
0321 .open_h = rtems_filesystem_default_open,
0322 .close_h = shm_close,
0323 .read_h = shm_read,
0324 .write_h = rtems_filesystem_default_write,
0325 .ioctl_h = rtems_filesystem_default_ioctl,
0326 .lseek_h = rtems_filesystem_default_lseek,
0327 .fstat_h = shm_fstat,
0328 .ftruncate_h = shm_ftruncate,
0329 .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
0330 .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
0331 .fcntl_h = rtems_filesystem_default_fcntl,
0332 .kqfilter_h = rtems_filesystem_default_kqfilter,
0333 .mmap_h = shm_mmap,
0334 .poll_h = rtems_filesystem_default_poll,
0335 .readv_h = rtems_filesystem_default_readv,
0336 .writev_h = rtems_filesystem_default_writev
0337 };
0338
0339 static void _POSIX_Shm_Manager_initialization( void )
0340 {
0341 _Objects_Initialize_information( &_POSIX_Shm_Information );
0342 }
0343
0344 RTEMS_SYSINIT_ITEM(
0345 _POSIX_Shm_Manager_initialization,
0346 RTEMS_SYSINIT_POSIX_SHM,
0347 RTEMS_SYSINIT_ORDER_MIDDLE
0348 );