File indexing completed on 2025-05-11 08:24:17
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
0035
0036
0037 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040
0041 #include <rtems/imfsimpl.h>
0042
0043 #include <stdlib.h>
0044 #include <string.h>
0045
0046
0047
0048
0049 static int IMFS_memfile_extend(
0050 IMFS_memfile_t *memfile,
0051 bool zero_fill,
0052 off_t new_length
0053 );
0054
0055 static int IMFS_memfile_addblock(
0056 IMFS_memfile_t *memfile,
0057 unsigned int block
0058 );
0059
0060 static void IMFS_memfile_remove_block(
0061 IMFS_memfile_t *memfile,
0062 unsigned int block
0063 );
0064
0065 static block_p *IMFS_memfile_get_block_pointer(
0066 IMFS_memfile_t *memfile,
0067 unsigned int block,
0068 int malloc_it
0069 );
0070
0071 static ssize_t IMFS_memfile_read(
0072 IMFS_file_t *file,
0073 off_t start,
0074 unsigned char *destination,
0075 unsigned int length
0076 );
0077
0078 static void *memfile_alloc_block(void);
0079
0080 static void memfile_free_block(
0081 void *memory
0082 );
0083
0084 static ssize_t memfile_read(
0085 rtems_libio_t *iop,
0086 void *buffer,
0087 size_t count
0088 )
0089 {
0090 IMFS_file_t *file = IMFS_iop_to_file( iop );
0091 ssize_t status;
0092
0093 status = IMFS_memfile_read( file, iop->offset, buffer, count );
0094
0095 if ( status > 0 )
0096 iop->offset += status;
0097
0098 return status;
0099 }
0100
0101 static ssize_t memfile_write(
0102 rtems_libio_t *iop,
0103 const void *buffer,
0104 size_t count
0105 )
0106 {
0107 IMFS_memfile_t *memfile = IMFS_iop_to_memfile( iop );
0108 ssize_t status;
0109
0110 if (rtems_libio_iop_is_append(iop))
0111 iop->offset = memfile->File.size;
0112
0113 status = IMFS_memfile_write( memfile, iop->offset, buffer, count );
0114
0115 if ( status > 0 )
0116 iop->offset += status;
0117
0118 return status;
0119 }
0120
0121
0122
0123
0124
0125
0126
0127 static int memfile_ftruncate(
0128 rtems_libio_t *iop,
0129 off_t length
0130 )
0131 {
0132 IMFS_memfile_t *memfile = IMFS_iop_to_memfile( iop );
0133
0134
0135
0136
0137
0138
0139
0140 if ( length > memfile->File.size )
0141 return IMFS_memfile_extend( memfile, true, length );
0142
0143
0144
0145
0146
0147
0148 memfile->File.size = length;
0149
0150 IMFS_mtime_ctime_update( &memfile->File.Node );
0151
0152 return 0;
0153 }
0154
0155
0156
0157
0158
0159
0160
0161
0162 static int IMFS_memfile_extend(
0163 IMFS_memfile_t *memfile,
0164 bool zero_fill,
0165 off_t new_length
0166 )
0167 {
0168 unsigned int block;
0169 unsigned int new_blocks;
0170 unsigned int old_blocks;
0171 unsigned int offset;
0172
0173
0174
0175
0176 IMFS_assert( memfile );
0177
0178
0179
0180
0181 if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
0182 rtems_set_errno_and_return_minus_one( EFBIG );
0183
0184
0185
0186
0187 if ( new_length <= memfile->File.size )
0188 return 0;
0189
0190
0191
0192
0193 new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
0194 old_blocks = memfile->File.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
0195 offset = memfile->File.size - old_blocks * IMFS_MEMFILE_BYTES_PER_BLOCK;
0196
0197
0198
0199
0200 for ( block=old_blocks ; block<=new_blocks ; block++ ) {
0201 if ( !IMFS_memfile_addblock( memfile, block ) ) {
0202 if ( zero_fill ) {
0203 size_t count = IMFS_MEMFILE_BYTES_PER_BLOCK - offset;
0204 block_p *block_ptr =
0205 IMFS_memfile_get_block_pointer( memfile, block, 0 );
0206
0207 memset( &(*block_ptr) [offset], 0, count);
0208 offset = 0;
0209 }
0210 } else {
0211 for ( ; block>old_blocks ; block-- ) {
0212 IMFS_memfile_remove_block( memfile, block );
0213 }
0214 IMFS_memfile_remove_block( memfile, old_blocks );
0215 rtems_set_errno_and_return_minus_one( ENOSPC );
0216 }
0217 }
0218
0219
0220
0221
0222 memfile->File.size = new_length;
0223
0224 IMFS_mtime_ctime_update( &memfile->File.Node );
0225
0226 return 0;
0227 }
0228
0229
0230
0231
0232
0233
0234 static int IMFS_memfile_addblock(
0235 IMFS_memfile_t *memfile,
0236 unsigned int block
0237 )
0238 {
0239 block_p memory;
0240 block_p *block_entry_ptr;
0241
0242 IMFS_assert( memfile );
0243
0244
0245
0246
0247 block_entry_ptr = IMFS_memfile_get_block_pointer( memfile, block, 1 );
0248 if ( !block_entry_ptr )
0249 return 1;
0250
0251 if ( *block_entry_ptr )
0252 return 0;
0253
0254
0255
0256
0257 memory = memfile_alloc_block();
0258 if ( !memory )
0259 return 1;
0260
0261 *block_entry_ptr = memory;
0262 return 0;
0263 }
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 static void IMFS_memfile_remove_block(
0276 IMFS_memfile_t *memfile,
0277 unsigned int block
0278 )
0279 {
0280 block_p *block_ptr;
0281 block_p ptr;
0282
0283 block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 );
0284 if ( block_ptr ) {
0285 ptr = *block_ptr;
0286 *block_ptr = 0;
0287 memfile_free_block( ptr );
0288 }
0289 }
0290
0291
0292
0293
0294
0295
0296
0297 static void memfile_free_blocks_in_table(
0298 block_p **block_table,
0299 int entries
0300 )
0301 {
0302 int i;
0303 block_p *b;
0304
0305
0306
0307
0308 IMFS_assert( block_table );
0309
0310
0311
0312
0313 b = *block_table;
0314
0315 for ( i=0 ; i<entries ; i++ ) {
0316 if ( b[i] ) {
0317 memfile_free_block( b[i] );
0318 b[i] = 0;
0319 }
0320 }
0321
0322
0323
0324
0325
0326 memfile_free_block( *block_table );
0327 *block_table = 0;
0328 }
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348 static void IMFS_memfile_destroy(
0349 IMFS_jnode_t *the_jnode
0350 )
0351 {
0352 IMFS_memfile_t *memfile;
0353 int i;
0354 int j;
0355 unsigned int to_free;
0356 block_p *p;
0357
0358 memfile = (IMFS_memfile_t *) the_jnode;
0359
0360
0361
0362
0363 IMFS_assert( memfile );
0364
0365
0366
0367
0368
0369 to_free = IMFS_MEMFILE_BLOCK_SLOTS;
0370
0371
0372
0373
0374
0375
0376
0377
0378 if ( memfile->indirect ) {
0379 memfile_free_blocks_in_table( &memfile->indirect, to_free );
0380 }
0381
0382 if ( memfile->doubly_indirect ) {
0383 for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
0384 if ( memfile->doubly_indirect[i] ) {
0385 memfile_free_blocks_in_table(
0386 (block_p **)&memfile->doubly_indirect[i], to_free );
0387 }
0388 }
0389 memfile_free_blocks_in_table( &memfile->doubly_indirect, to_free );
0390
0391 }
0392
0393 if ( memfile->triply_indirect ) {
0394 for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
0395 p = (block_p *) memfile->triply_indirect[i];
0396 if ( !p )
0397 break;
0398 for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
0399 if ( p[j] ) {
0400 memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
0401 }
0402 }
0403 memfile_free_blocks_in_table(
0404 (block_p **)&memfile->triply_indirect[i], to_free );
0405 }
0406 memfile_free_blocks_in_table(
0407 (block_p **)&memfile->triply_indirect, to_free );
0408 }
0409
0410 IMFS_node_destroy_default( the_jnode );
0411 }
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424 static ssize_t IMFS_memfile_read(
0425 IMFS_file_t *file,
0426 off_t start,
0427 unsigned char *destination,
0428 unsigned int length
0429 )
0430 {
0431 block_p *block_ptr;
0432 unsigned int block;
0433 unsigned int my_length;
0434 unsigned int to_copy = 0;
0435 unsigned int last_byte;
0436 unsigned int copied;
0437 unsigned int start_offset;
0438 unsigned char *dest;
0439
0440 dest = destination;
0441
0442
0443
0444
0445 IMFS_assert( file );
0446 IMFS_assert( dest );
0447
0448
0449
0450
0451
0452 my_length = length;
0453
0454
0455
0456
0457
0458 last_byte = start + length;
0459 if ( last_byte > file->Memfile.File.size )
0460 my_length = file->Memfile.File.size - start;
0461
0462 copied = 0;
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474 start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
0475 block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
0476 if ( start_offset ) {
0477 to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
0478 if ( to_copy > my_length )
0479 to_copy = my_length;
0480 block_ptr = IMFS_memfile_get_block_pointer( &file->Memfile, block, 0 );
0481 if ( !block_ptr )
0482 return copied;
0483 memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
0484 dest += to_copy;
0485 block++;
0486 my_length -= to_copy;
0487 copied += to_copy;
0488 }
0489
0490
0491
0492
0493 to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
0494 while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
0495 block_ptr = IMFS_memfile_get_block_pointer( &file->Memfile, block, 0 );
0496 if ( !block_ptr )
0497 return copied;
0498 memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
0499 dest += to_copy;
0500 block++;
0501 my_length -= to_copy;
0502 copied += to_copy;
0503 }
0504
0505
0506
0507
0508 IMFS_assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
0509
0510 if ( my_length ) {
0511 block_ptr = IMFS_memfile_get_block_pointer( &file->Memfile, block, 0 );
0512 if ( !block_ptr )
0513 return copied;
0514 memcpy( dest, &(*block_ptr)[ 0 ], my_length );
0515 copied += my_length;
0516 }
0517
0518 IMFS_update_atime( &file->Node );
0519
0520 return copied;
0521 }
0522
0523
0524
0525
0526
0527
0528
0529 ssize_t IMFS_memfile_write(
0530 IMFS_memfile_t *memfile,
0531 off_t start,
0532 const unsigned char *source,
0533 unsigned int length
0534 )
0535 {
0536 block_p *block_ptr;
0537 unsigned int block;
0538 int status;
0539 unsigned int my_length;
0540 unsigned int to_copy = 0;
0541 unsigned int last_byte;
0542 unsigned int start_offset;
0543 int copied;
0544 const unsigned char *src;
0545
0546 src = source;
0547
0548
0549
0550
0551 IMFS_assert( source );
0552 IMFS_assert( memfile );
0553
0554 my_length = length;
0555
0556
0557
0558
0559
0560 last_byte = start + my_length;
0561 if ( last_byte > memfile->File.size ) {
0562 bool zero_fill = start > memfile->File.size;
0563
0564 status = IMFS_memfile_extend( memfile, zero_fill, last_byte );
0565 if ( status )
0566 return status;
0567 }
0568
0569 copied = 0;
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581 start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
0582 block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
0583 if ( start_offset ) {
0584 to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
0585 if ( to_copy > my_length )
0586 to_copy = my_length;
0587 block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 );
0588 if ( !block_ptr )
0589 return copied;
0590 #if 0
0591 fprintf(
0592 stderr,
0593 "write %d at %d in %d: %*s\n",
0594 to_copy,
0595 start_offset,
0596 block,
0597 to_copy,
0598 src
0599 );
0600 #endif
0601 memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
0602 src += to_copy;
0603 block++;
0604 my_length -= to_copy;
0605 copied += to_copy;
0606 }
0607
0608
0609
0610
0611
0612 to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
0613 while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
0614 block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 );
0615 if ( !block_ptr )
0616 return copied;
0617 #if 0
0618 fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src );
0619 #endif
0620 memcpy( &(*block_ptr)[ 0 ], src, to_copy );
0621 src += to_copy;
0622 block++;
0623 my_length -= to_copy;
0624 copied += to_copy;
0625 }
0626
0627
0628
0629
0630 IMFS_assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
0631
0632 to_copy = my_length;
0633 if ( my_length ) {
0634 block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 );
0635 if ( !block_ptr )
0636 return copied;
0637 #if 0
0638 fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src );
0639 #endif
0640 memcpy( &(*block_ptr)[ 0 ], src, my_length );
0641 copied += to_copy;
0642 }
0643
0644 IMFS_mtime_ctime_update( &memfile->File.Node );
0645
0646 return copied;
0647 }
0648
0649
0650
0651
0652
0653
0654
0655
0656 #if 0
0657 block_p *IMFS_memfile_get_block_pointer_DEBUG(
0658 IMFS_jnode_t *the_jnode,
0659 unsigned int block,
0660 int malloc_it
0661 );
0662
0663 block_p *IMFS_memfile_get_block_pointer(
0664 IMFS_jnode_t *the_jnode,
0665 unsigned int block,
0666 int malloc_it
0667 )
0668 {
0669 block_p *p;
0670
0671 p = IMFS_memfile_get_block_pointer_DEBUG( the_jnode, block, malloc_it );
0672 fprintf(stdout, "(%d -> %p) ", block, p );
0673 return p;
0674 }
0675
0676 block_p *IMFS_memfile_get_block_pointer_DEBUG(
0677 #else
0678 block_p *IMFS_memfile_get_block_pointer(
0679 #endif
0680 IMFS_memfile_t *memfile,
0681 unsigned int block,
0682 int malloc_it
0683 )
0684 {
0685 unsigned int my_block;
0686 unsigned int singly;
0687 unsigned int doubly;
0688 unsigned int triply;
0689 block_p *p;
0690 block_p *p1;
0691 block_p *p2;
0692
0693
0694
0695
0696 IMFS_assert( memfile );
0697
0698 my_block = block;
0699
0700
0701
0702
0703 if ( my_block <= LAST_INDIRECT ) {
0704 p = memfile->indirect;
0705
0706 if ( malloc_it ) {
0707
0708 if ( !p ) {
0709 p = memfile_alloc_block();
0710 if ( !p )
0711 return 0;
0712 memfile->indirect = p;
0713 }
0714 return &memfile->indirect[ my_block ];
0715 }
0716
0717 if ( !p )
0718 return 0;
0719
0720 return &memfile->indirect[ my_block ];
0721 }
0722
0723
0724
0725
0726
0727 if ( my_block <= LAST_DOUBLY_INDIRECT ) {
0728 my_block -= FIRST_DOUBLY_INDIRECT;
0729
0730 singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
0731 doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
0732
0733 p = memfile->doubly_indirect;
0734 if ( malloc_it ) {
0735
0736 if ( !p ) {
0737 p = memfile_alloc_block();
0738 if ( !p )
0739 return 0;
0740 memfile->doubly_indirect = p;
0741 }
0742
0743 p1 = (block_p *)p[ doubly ];
0744 if ( !p1 ) {
0745 p1 = memfile_alloc_block();
0746 if ( !p1 )
0747 return 0;
0748 p[ doubly ] = (block_p) p1;
0749 }
0750
0751 return (block_p *)&p1[ singly ];
0752 }
0753
0754 if ( !p )
0755 return 0;
0756
0757 p = (block_p *)p[ doubly ];
0758 if ( !p )
0759 return 0;
0760
0761 return (block_p *)&p[ singly ];
0762 }
0763
0764
0765
0766
0767 if ( my_block <= LAST_TRIPLY_INDIRECT ) {
0768 my_block -= FIRST_TRIPLY_INDIRECT;
0769
0770 singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
0771 doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
0772 triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
0773 doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
0774
0775 p = memfile->triply_indirect;
0776
0777 if ( malloc_it ) {
0778 if ( !p ) {
0779 p = memfile_alloc_block();
0780 if ( !p )
0781 return 0;
0782 memfile->triply_indirect = p;
0783 }
0784
0785 p1 = (block_p *) p[ triply ];
0786 if ( !p1 ) {
0787 p1 = memfile_alloc_block();
0788 if ( !p1 )
0789 return 0;
0790 p[ triply ] = (block_p) p1;
0791 }
0792
0793 p2 = (block_p *)p1[ doubly ];
0794 if ( !p2 ) {
0795 p2 = memfile_alloc_block();
0796 if ( !p2 )
0797 return 0;
0798 p1[ doubly ] = (block_p) p2;
0799 }
0800 return (block_p *)&p2[ singly ];
0801 }
0802
0803 if ( !p )
0804 return 0;
0805
0806 p1 = (block_p *) p[ triply ];
0807 if ( !p1 )
0808 return 0;
0809
0810 p2 = (block_p *)p1[ doubly ];
0811 if ( !p2 )
0812 return 0;
0813
0814 return (block_p *)&p2[ singly ];
0815 }
0816
0817
0818
0819
0820 return 0;
0821 }
0822
0823
0824
0825
0826
0827
0828 int memfile_blocks_allocated = 0;
0829
0830 void *memfile_alloc_block(void)
0831 {
0832 void *memory;
0833
0834 memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
0835 if ( memory )
0836 memfile_blocks_allocated++;
0837
0838 return memory;
0839 }
0840
0841
0842
0843
0844
0845
0846 void memfile_free_block(
0847 void *memory
0848 )
0849 {
0850 free(memory);
0851 memfile_blocks_allocated--;
0852 }
0853
0854 static const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = {
0855 .open_h = rtems_filesystem_default_open,
0856 .close_h = rtems_filesystem_default_close,
0857 .read_h = memfile_read,
0858 .write_h = memfile_write,
0859 .ioctl_h = rtems_filesystem_default_ioctl,
0860 .lseek_h = rtems_filesystem_default_lseek_file,
0861 .fstat_h = IMFS_stat_file,
0862 .ftruncate_h = memfile_ftruncate,
0863 .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success,
0864 .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success,
0865 .fcntl_h = rtems_filesystem_default_fcntl,
0866 .kqfilter_h = rtems_filesystem_default_kqfilter,
0867 .mmap_h = rtems_filesystem_default_mmap,
0868 .poll_h = rtems_filesystem_default_poll,
0869 .readv_h = rtems_filesystem_default_readv,
0870 .writev_h = rtems_filesystem_default_writev
0871 };
0872
0873 const IMFS_mknod_control IMFS_mknod_control_memfile = {
0874 {
0875 .handlers = &IMFS_memfile_handlers,
0876 .node_initialize = IMFS_node_initialize_default,
0877 .node_remove = IMFS_node_remove_default,
0878 .node_destroy = IMFS_memfile_destroy
0879 },
0880 .node_size = sizeof( IMFS_file_t )
0881 };