File indexing completed on 2025-05-11 08:24:18
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
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041
0042 #include <inttypes.h>
0043 #include <stdlib.h>
0044 #include <string.h>
0045
0046 #include <rtems/rfs/rtems-rfs-block-pos.h>
0047 #include <rtems/rfs/rtems-rfs-file.h>
0048 #include <rtems/rfs/rtems-rfs-file-system.h>
0049 #include <rtems/rfs/rtems-rfs-trace.h>
0050
0051 int
0052 rtems_rfs_file_open (rtems_rfs_file_system* fs,
0053 rtems_rfs_ino ino,
0054 int oflag,
0055 rtems_rfs_file_handle** file)
0056 {
0057 rtems_rfs_file_handle* handle;
0058 rtems_rfs_file_shared* shared;
0059 int rc;
0060
0061 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
0062 printf ("rtems-rfs: file-open: ino=%" PRId32 "\n", ino);
0063
0064 *file = NULL;
0065
0066
0067
0068
0069
0070
0071 handle = malloc (sizeof (rtems_rfs_file_handle));
0072 if (!handle)
0073 return ENOMEM;
0074
0075 memset (handle, 0, sizeof (rtems_rfs_file_handle));
0076
0077 rc = rtems_rfs_buffer_handle_open (fs, &handle->buffer);
0078 if (rc > 0)
0079 {
0080 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
0081 printf ("rtems-rfs: file-open: buffer handle open failed: %d: %s\n",
0082 rc, strerror (rc));
0083 free (handle);
0084 return rc;
0085 }
0086
0087
0088
0089
0090
0091 shared = rtems_rfs_file_get_shared (fs, ino);
0092 if (shared)
0093 {
0094 shared->references++;
0095 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
0096 printf ("rtems-rfs: file-open: ino=%" PRId32 " shared\n", ino);
0097 }
0098 else
0099 {
0100
0101
0102
0103
0104 shared = malloc (sizeof (rtems_rfs_file_shared));
0105 if (!shared)
0106 {
0107 rtems_rfs_buffer_handle_close (fs, &handle->buffer);
0108 free (handle);
0109 return ENOMEM;
0110 }
0111
0112 memset (shared, 0, sizeof (rtems_rfs_file_shared));
0113
0114 rc = rtems_rfs_inode_open (fs, ino, &shared->inode, true);
0115 if (rc > 0)
0116 {
0117 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
0118 printf ("rtems-rfs: file-open: inode open failed: %d: %s\n",
0119 rc, strerror (rc));
0120 free (shared);
0121 rtems_rfs_buffer_handle_close (fs, &handle->buffer);
0122 free (handle);
0123 return rc;
0124 }
0125
0126 rc = rtems_rfs_block_map_open (fs, &shared->inode, &shared->map);
0127 if (rc > 0)
0128 {
0129 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
0130 printf ("rtems-rfs: file-open: block map open failed: %d: %s\n",
0131 rc, strerror (rc));
0132 rtems_rfs_inode_close (fs, &shared->inode);
0133 free (shared);
0134 rtems_rfs_buffer_handle_close (fs, &handle->buffer);
0135 free (handle);
0136 return rc;
0137 }
0138
0139 shared->references = 1;
0140 shared->size.count = rtems_rfs_inode_get_block_count (&shared->inode);
0141 shared->size.offset = rtems_rfs_inode_get_block_offset (&shared->inode);
0142 shared->atime = rtems_rfs_inode_get_atime (&shared->inode);
0143 shared->mtime = rtems_rfs_inode_get_mtime (&shared->inode);
0144 shared->ctime = rtems_rfs_inode_get_ctime (&shared->inode);
0145 shared->fs = fs;
0146
0147 rtems_chain_append_unprotected (&fs->file_shares, &shared->link);
0148
0149 rtems_rfs_inode_unload (fs, &shared->inode, false);
0150
0151 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
0152 printf ("rtems-rfs: file-open: ino=%" PRId32 " share created\n", ino);
0153 }
0154
0155 handle->flags = oflag;
0156 handle->shared = shared;
0157
0158 *file = handle;
0159
0160 return 0;
0161 }
0162
0163 int
0164 rtems_rfs_file_close (rtems_rfs_file_system* fs,
0165 rtems_rfs_file_handle* handle)
0166 {
0167 int rrc;
0168 int rc;
0169
0170 rrc = 0;
0171
0172 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
0173 printf ("rtems-rfs: file-close: entry: ino=%" PRId32 "\n",
0174 handle->shared->inode.ino);
0175
0176 if (handle->shared->references > 0)
0177 handle->shared->references--;
0178
0179 if (handle->shared->references == 0)
0180 {
0181 if (!rtems_rfs_inode_is_loaded (&handle->shared->inode))
0182 rrc = rtems_rfs_inode_load (fs, &handle->shared->inode);
0183
0184 if (rrc == 0)
0185 {
0186
0187
0188
0189 rtems_rfs_inode_set_atime (&handle->shared->inode,
0190 handle->shared->atime);
0191 rtems_rfs_inode_set_mtime (&handle->shared->inode,
0192 handle->shared->mtime);
0193 rtems_rfs_inode_set_ctime (&handle->shared->inode,
0194 handle->shared->ctime);
0195 if (!rtems_rfs_block_size_equal (&handle->shared->size,
0196 &handle->shared->map.size))
0197 rtems_rfs_block_map_set_size (&handle->shared->map,
0198 &handle->shared->size);
0199 }
0200
0201 rc = rtems_rfs_block_map_close (fs, &handle->shared->map);
0202 if (rc > 0)
0203 {
0204 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
0205 printf ("rtems-rfs: file-close: map close error: ino=%" PRId32 ": %d: %s\n",
0206 handle->shared->inode.ino, rc, strerror (rc));
0207 if (rrc == 0)
0208 rrc = rc;
0209 }
0210
0211 rc = rtems_rfs_inode_close (fs, &handle->shared->inode);
0212 if (rc > 0)
0213 {
0214 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
0215 printf ("rtems-rfs: file-close: inode close error: ino=%" PRId32 ": %d: %s\n",
0216 handle->shared->inode.ino, rc, strerror (rc));
0217 if (rrc == 0)
0218 rrc = rc;
0219 }
0220
0221 rtems_chain_extract_unprotected (&handle->shared->link);
0222 free (handle->shared);
0223 }
0224
0225 rc = rtems_rfs_buffer_handle_close (fs, &handle->buffer);
0226 if ((rrc == 0) && (rc > 0))
0227 rrc = rc;
0228
0229 if (rrc > 0)
0230 {
0231 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
0232 printf ("rtems-rfs: file-close: result: %d: %s\n", rrc, strerror (rrc));
0233 }
0234
0235 free (handle);
0236
0237 return rrc;
0238 }
0239
0240 int
0241 rtems_rfs_file_io_start (rtems_rfs_file_handle* handle,
0242 size_t* available,
0243 bool read)
0244 {
0245 size_t size;
0246
0247 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
0248 printf ("rtems-rfs: file-io: start: %s pos=%" PRIu32 ":%" PRIu32 "\n",
0249 read ? "read" : "write", handle->bpos.bno, handle->bpos.boff);
0250
0251 if (!rtems_rfs_buffer_handle_has_block (&handle->buffer))
0252 {
0253 rtems_rfs_buffer_block block;
0254 bool request_read;
0255 int rc;
0256
0257 request_read = read;
0258
0259 rc = rtems_rfs_block_map_find (rtems_rfs_file_fs (handle),
0260 rtems_rfs_file_map (handle),
0261 rtems_rfs_file_bpos (handle),
0262 &block);
0263 if (rc > 0)
0264 {
0265
0266
0267
0268 if (read && (rc == ENXIO))
0269 {
0270 *available = 0;
0271 return 0;
0272 }
0273
0274 if (rc != ENXIO)
0275 return rc;
0276
0277 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
0278 printf ("rtems-rfs: file-io: start: grow\n");
0279
0280 rc = rtems_rfs_block_map_grow (rtems_rfs_file_fs (handle),
0281 rtems_rfs_file_map (handle),
0282 1, &block);
0283 if (rc > 0)
0284 return rc;
0285
0286 request_read = false;
0287 }
0288 else
0289 {
0290
0291
0292
0293
0294
0295 if (!read &&
0296 (rtems_rfs_file_block_offset (handle) ||
0297 (*available < rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle)))))
0298 request_read = true;
0299 }
0300
0301 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
0302 printf ("rtems-rfs: file-io: start: block=%" PRIu32 " request-read=%s\n",
0303 block, request_read ? "yes" : "no");
0304
0305 rc = rtems_rfs_buffer_handle_request (rtems_rfs_file_fs (handle),
0306 rtems_rfs_file_buffer (handle),
0307 block, request_read);
0308 if (rc > 0)
0309 return rc;
0310 }
0311
0312 if (read
0313 && rtems_rfs_block_map_last (rtems_rfs_file_map (handle))
0314 && rtems_rfs_block_map_size_offset (rtems_rfs_file_map (handle)))
0315 size = rtems_rfs_block_map_size_offset (rtems_rfs_file_map (handle));
0316 else
0317 size = rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
0318
0319 *available = size - rtems_rfs_file_block_offset (handle);
0320
0321 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
0322 printf ("rtems-rfs: file-io: start: available=%zu (%zu)\n",
0323 *available, size);
0324
0325 return 0;
0326 }
0327
0328 int
0329 rtems_rfs_file_io_end (rtems_rfs_file_handle* handle,
0330 size_t size,
0331 bool read)
0332 {
0333 bool atime;
0334 bool mtime;
0335 bool length;
0336 int rc = 0;
0337
0338 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
0339 printf ("rtems-rfs: file-io: end: %s size=%zu\n",
0340 read ? "read" : "write", size);
0341
0342 if (rtems_rfs_buffer_handle_has_block (&handle->buffer))
0343 {
0344 if (!read)
0345 rtems_rfs_buffer_mark_dirty (rtems_rfs_file_buffer (handle));
0346 rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
0347 rtems_rfs_file_buffer (handle));
0348 if (rc > 0)
0349 {
0350 printf (
0351 "rtems-rfs: file-io: end: error on release: %s size=%zu: %d: %s\n",
0352 read ? "read" : "write", size, rc, strerror (rc));
0353
0354 return rc;
0355 }
0356 }
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366 handle->bpos.boff += size;
0367
0368 if (handle->bpos.boff >=
0369 rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle)))
0370 {
0371 handle->bpos.bno++;
0372 handle->bpos.boff -= rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
0373 }
0374
0375 length = false;
0376 mtime = !read;
0377
0378 if (!read &&
0379 rtems_rfs_block_map_past_end (rtems_rfs_file_map (handle),
0380 rtems_rfs_file_bpos (handle)))
0381 {
0382 rtems_rfs_block_map_set_size_offset (rtems_rfs_file_map (handle),
0383 handle->bpos.boff);
0384 length = true;
0385 }
0386
0387 atime = rtems_rfs_file_update_atime (handle);
0388 mtime = rtems_rfs_file_update_mtime (handle) && mtime;
0389 length = rtems_rfs_file_update_length (handle) && length;
0390
0391 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
0392 printf ("rtems-rfs: file-io: end: pos=%" PRIu32 ":%" PRIu32 " %c %c %c\n",
0393 handle->bpos.bno, handle->bpos.boff,
0394 atime ? 'A' : '-', mtime ? 'M' : '-', length ? 'L' : '-');
0395
0396 if (atime || mtime)
0397 {
0398 time_t now = time (NULL);
0399 if (read && atime)
0400 handle->shared->atime = now;
0401 if (!read && mtime)
0402 handle->shared->mtime = now;
0403 }
0404 if (length)
0405 {
0406 handle->shared->size.count =
0407 rtems_rfs_block_map_count (rtems_rfs_file_map (handle));
0408 handle->shared->size.offset =
0409 rtems_rfs_block_map_size_offset (rtems_rfs_file_map (handle));
0410 }
0411
0412 return rc;
0413 }
0414
0415 int
0416 rtems_rfs_file_io_release (rtems_rfs_file_handle* handle)
0417 {
0418 int rc = 0;
0419 if (rtems_rfs_buffer_handle_has_block (&handle->buffer))
0420 rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
0421 rtems_rfs_file_buffer (handle));
0422 return rc;
0423 }
0424
0425 int
0426 rtems_rfs_file_seek (rtems_rfs_file_handle* handle,
0427 rtems_rfs_pos pos,
0428 rtems_rfs_pos* new_pos)
0429 {
0430 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
0431 printf ("rtems-rfs: file-seek: new=%" PRIu64 "\n", pos);
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444 if (pos <= rtems_rfs_file_shared_get_size (rtems_rfs_file_fs (handle),
0445 handle->shared))
0446 {
0447 rtems_rfs_file_set_bpos (handle, pos);
0448
0449
0450
0451
0452
0453
0454 if (rtems_rfs_buffer_handle_has_block (&handle->buffer))
0455 {
0456 rtems_rfs_buffer_block block;
0457 int rc;
0458
0459 rc = rtems_rfs_block_map_find (rtems_rfs_file_fs (handle),
0460 rtems_rfs_file_map (handle),
0461 rtems_rfs_file_bpos (handle),
0462 &block);
0463 if (rc > 0)
0464 return rc;
0465 if (rtems_rfs_buffer_bnum (&handle->buffer) != block)
0466 {
0467 rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
0468 rtems_rfs_file_buffer (handle));
0469 if (rc > 0)
0470 return rc;
0471 }
0472 }
0473 }
0474 else
0475 {
0476
0477
0478
0479
0480 int rc = rtems_rfs_file_io_release (handle);
0481 if (rc > 0)
0482 return rc;
0483 }
0484
0485 *new_pos = pos;
0486 return 0;
0487 }
0488
0489 int
0490 rtems_rfs_file_set_size (rtems_rfs_file_handle* handle,
0491 rtems_rfs_pos new_size)
0492 {
0493 rtems_rfs_block_map* map = rtems_rfs_file_map (handle);
0494 rtems_rfs_pos size;
0495 int rc;
0496
0497 if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
0498 printf ("rtems-rfs: file-set-size: size=%" PRIu64 "\n", new_size);
0499
0500 size = rtems_rfs_file_size (handle);
0501
0502
0503
0504
0505
0506
0507 if (size != new_size)
0508 {
0509
0510
0511
0512 if (new_size == 0)
0513 {
0514 rc = rtems_rfs_block_map_free_all (rtems_rfs_file_fs (handle), map);
0515 if (rc > 0)
0516 return rc;
0517 }
0518 else
0519 {
0520 if (size < new_size)
0521 {
0522
0523
0524
0525 rtems_rfs_pos count;
0526 uint32_t length;
0527 bool read_block;
0528
0529 count = new_size - size;
0530 length = rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
0531 read_block = false;
0532
0533 while (count)
0534 {
0535 rtems_rfs_buffer_block block;
0536 rtems_rfs_block_pos bpos;
0537 uint8_t* dst;
0538
0539
0540
0541
0542
0543
0544 rtems_rfs_block_size_get_bpos (rtems_rfs_block_map_size (map), &bpos);
0545 rc = rtems_rfs_block_map_find (rtems_rfs_file_fs (handle),
0546 map, &bpos, &block);
0547 if (rc > 0)
0548 {
0549
0550
0551
0552 if (rc != ENXIO)
0553 return rc;
0554
0555 rc = rtems_rfs_block_map_grow (rtems_rfs_file_fs (handle),
0556 map, 1, &block);
0557 if (rc > 0)
0558 return rc;
0559 }
0560
0561 if (count < (length - bpos.boff))
0562 {
0563 length = count + bpos.boff;
0564 read_block = true;
0565 rtems_rfs_block_map_set_size_offset (map, length);
0566 }
0567 else
0568 {
0569 rtems_rfs_block_map_set_size_offset (map, 0);
0570 }
0571
0572
0573
0574
0575 rc = rtems_rfs_buffer_handle_request (rtems_rfs_file_fs (handle),
0576 rtems_rfs_file_buffer (handle),
0577 block, read_block);
0578 if (rc > 0)
0579 return rc;
0580
0581 dst = rtems_rfs_buffer_data (&handle->buffer);
0582 memset (dst + bpos.boff, 0, length - bpos.boff);
0583
0584 rtems_rfs_buffer_mark_dirty (rtems_rfs_file_buffer (handle));
0585
0586 rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
0587 rtems_rfs_file_buffer (handle));
0588 if (rc > 0)
0589 return rc;
0590
0591 count -= length - bpos.boff;
0592 }
0593 }
0594 else
0595 {
0596
0597
0598
0599 rtems_rfs_block_no blocks;
0600 uint32_t offset;
0601
0602 blocks =
0603 rtems_rfs_block_map_count (map) -
0604 (((new_size - 1) /
0605 rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle))) + 1);
0606
0607 offset =
0608 new_size % rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
0609
0610 if (blocks)
0611 {
0612 int rc;
0613 rc = rtems_rfs_block_map_shrink (rtems_rfs_file_fs (handle),
0614 rtems_rfs_file_map (handle),
0615 blocks);
0616 if (rc > 0)
0617 return rc;
0618 }
0619
0620 rtems_rfs_block_map_set_size_offset (map, offset);
0621
0622 if (rtems_rfs_block_pos_past_end (rtems_rfs_file_bpos (handle),
0623 rtems_rfs_block_map_size (map)))
0624 rtems_rfs_block_size_get_bpos (rtems_rfs_block_map_size (map),
0625 rtems_rfs_file_bpos (handle));
0626 }
0627 }
0628
0629 handle->shared->size.count = rtems_rfs_block_map_count (map);
0630 handle->shared->size.offset = rtems_rfs_block_map_size_offset (map);
0631 }
0632
0633 if (rtems_rfs_file_update_mtime (handle))
0634 handle->shared->mtime = time (NULL);
0635
0636 return 0;
0637 }
0638
0639 rtems_rfs_file_shared*
0640 rtems_rfs_file_get_shared (rtems_rfs_file_system* fs,
0641 rtems_rfs_ino ino)
0642 {
0643 rtems_chain_node* node;
0644 node = rtems_chain_first (&fs->file_shares);
0645 while (!rtems_chain_is_tail (&fs->file_shares, node))
0646 {
0647 rtems_rfs_file_shared* shared;
0648 shared = (rtems_rfs_file_shared*) node;
0649 if (shared->inode.ino == ino)
0650 return shared;
0651 node = rtems_chain_next (node);
0652 }
0653 return NULL;
0654 }