File indexing completed on 2025-05-11 08:24:21
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
0033
0034 #ifdef HAVE_CONFIG_H
0035 #include "config.h"
0036 #endif
0037
0038 #include <rtems.h>
0039 #include <errno.h>
0040 #include <stdlib.h>
0041 #include <string.h>
0042 #include <sys/mman.h>
0043 #include <sys/stat.h>
0044 #include <unistd.h>
0045
0046 #include "rtems/libio_.h"
0047
0048 #include <rtems/posix/mmanimpl.h>
0049 #include <rtems/posix/shmimpl.h>
0050
0051
0052
0053
0054
0055 CHAIN_DEFINE_EMPTY( mmap_mappings );
0056
0057 void *mmap(
0058 void *addr, size_t len, int prot, int flags, int fildes, off_t off
0059 )
0060 {
0061 struct stat sb;
0062 mmap_mapping *mapping;
0063 mmap_mapping *current_mapping;
0064 ssize_t r;
0065 rtems_libio_t *iop;
0066 bool map_fixed;
0067 bool map_anonymous;
0068 bool map_shared;
0069 bool map_private;
0070 bool is_shared_shm;
0071 int err;
0072
0073 map_fixed = (flags & MAP_FIXED) == MAP_FIXED;
0074 map_anonymous = (flags & MAP_ANON) == MAP_ANON;
0075 map_shared = (flags & MAP_SHARED) == MAP_SHARED;
0076 map_private = (flags & MAP_PRIVATE) == MAP_PRIVATE;
0077
0078
0079 errno = 0;
0080 iop = NULL;
0081
0082 if ( len == 0 ) {
0083 errno = EINVAL;
0084 return MAP_FAILED;
0085 }
0086
0087
0088
0089
0090
0091 if ( prot == PROT_NONE ) {
0092 errno = ENOTSUP;
0093 return MAP_FAILED;
0094 }
0095
0096
0097
0098
0099
0100
0101 if ( PROT_WRITE != (prot & PROT_WRITE) ) {
0102 errno = ENOTSUP;
0103 return MAP_FAILED;
0104 }
0105
0106
0107
0108
0109
0110
0111 if ( map_anonymous && (fildes != -1 || off != 0 || map_shared) ) {
0112 errno = EINVAL;
0113 return MAP_FAILED;
0114 }
0115
0116
0117
0118
0119
0120 if ( map_anonymous && !map_private && !map_shared ) {
0121 flags |= MAP_PRIVATE;
0122 map_private = true;
0123 }
0124
0125
0126 if ((flags & ~(MAP_SHARED | MAP_PRIVATE | MAP_FIXED | MAP_ANON)) != 0) {
0127 errno = EINVAL;
0128 return MAP_FAILED;
0129 }
0130
0131
0132 if ( map_shared ) {
0133 if ( map_private ) {
0134 errno = EINVAL;
0135 return MAP_FAILED;
0136 }
0137 } else if ( !map_private ) {
0138 errno = EINVAL;
0139 return MAP_FAILED;
0140 }
0141
0142
0143 if ( map_fixed ) {
0144 if ((uintptr_t)addr & PAGE_MASK) {
0145 errno = EINVAL;
0146 return MAP_FAILED;
0147 }
0148 if ( addr == NULL ) {
0149 errno = EINVAL;
0150 return MAP_FAILED;
0151 }
0152 if (addr + len < addr) {
0153 errno = EINVAL;
0154 return MAP_FAILED;
0155 }
0156 }
0157
0158 if ( !map_anonymous ) {
0159
0160
0161
0162
0163
0164
0165 if ( fstat( fildes, &sb ) < 0 ) {
0166 errno = EBADF;
0167 return MAP_FAILED;
0168 }
0169
0170
0171 iop = rtems_libio_iop( fildes );
0172
0173
0174 if ( S_ISDIR( sb.st_mode ) || S_ISLNK( sb.st_mode )) {
0175 errno = ENODEV;
0176 return MAP_FAILED;
0177 }
0178
0179
0180 if ( S_ISREG( sb.st_mode )
0181
0182
0183 && (( off >= sb.st_size ) || (( off + len ) >= sb.st_size ))) {
0184 errno = EOVERFLOW;
0185 return MAP_FAILED;
0186 }
0187
0188
0189 if ( !S_ISCHR( sb.st_mode ) && sb.st_size < off + len ) {
0190 errno = ENXIO;
0191 return MAP_FAILED;
0192 }
0193
0194
0195 if ( S_ISREG( sb.st_mode ) || S_ISBLK( sb.st_mode ) ) {
0196 if ( lseek( fildes, off, SEEK_SET ) < 0 ) {
0197 return MAP_FAILED;
0198 }
0199 }
0200
0201
0202 if ( S_ISCHR( sb.st_mode ) && map_private ) {
0203 errno = EINVAL;
0204 return MAP_FAILED;
0205 }
0206 }
0207
0208
0209 mapping = malloc( sizeof( mmap_mapping ));
0210 if ( !mapping ) {
0211 errno = ENOMEM;
0212 return MAP_FAILED;
0213 }
0214 memset( mapping, 0, sizeof( mmap_mapping ));
0215 mapping->len = len;
0216 mapping->flags = flags;
0217
0218 if ( !map_anonymous ) {
0219
0220
0221
0222
0223
0224
0225 if ( S_ISREG( sb.st_mode ) || S_ISBLK( sb.st_mode ) ||
0226 S_ISCHR( sb.st_mode ) || S_ISFIFO( sb.st_mode ) ||
0227 S_ISSOCK( sb.st_mode ) ) {
0228 is_shared_shm = false;
0229 } else {
0230 is_shared_shm = true;
0231 }
0232 } else {
0233 is_shared_shm = false;
0234 }
0235
0236 if ( map_fixed ) {
0237 mapping->addr = addr;
0238 } else if ( map_private ) {
0239
0240 is_shared_shm = false;
0241 err = posix_memalign( &mapping->addr, PAGE_SIZE, len );
0242 if ( err != 0 ) {
0243 free( mapping );
0244 errno = ENOMEM;
0245 return MAP_FAILED;
0246 }
0247 }
0248
0249
0250 if ( map_fixed && is_shared_shm ) {
0251 free( mapping );
0252 errno = ENOTSUP;
0253 return MAP_FAILED;
0254 }
0255
0256 mmap_mappings_lock_obtain();
0257
0258 if ( map_fixed ) {
0259 rtems_chain_node* node = rtems_chain_first (&mmap_mappings);
0260 while ( !rtems_chain_is_tail( &mmap_mappings, node )) {
0261
0262
0263
0264
0265
0266
0267 current_mapping = (mmap_mapping*) node;
0268 if ( ( addr >= current_mapping->addr ) &&
0269 ( addr < ( current_mapping->addr + current_mapping->len )) ) {
0270 free( mapping );
0271 mmap_mappings_lock_release( );
0272 errno = ENXIO;
0273 return MAP_FAILED;
0274 }
0275 node = rtems_chain_next( node );
0276 }
0277 }
0278
0279
0280 if ( map_private ) {
0281 if ( !map_anonymous ) {
0282
0283
0284
0285
0286
0287 r = read( fildes, mapping->addr, len );
0288
0289 if ( r != len ) {
0290 mmap_mappings_lock_release( );
0291 if ( !map_fixed ) {
0292 free( mapping->addr );
0293 }
0294 free( mapping );
0295 errno = ENXIO;
0296 return MAP_FAILED;
0297 }
0298 } else if ( !map_fixed ) {
0299 memset( mapping->addr, 0, len );
0300 }
0301 } else if ( map_shared ) {
0302 if ( is_shared_shm ) {
0303
0304 mapping->shm = iop_to_shm( iop );
0305 }
0306
0307 err = (*iop->pathinfo.handlers->mmap_h)(
0308 iop, &mapping->addr, len, prot, off );
0309 if ( err != 0 ) {
0310 mmap_mappings_lock_release( );
0311 free( mapping );
0312 return MAP_FAILED;
0313 }
0314 }
0315
0316 rtems_chain_append_unprotected( &mmap_mappings, &mapping->node );
0317
0318 mmap_mappings_lock_release( );
0319
0320 return mapping->addr;
0321 }