File indexing completed on 2025-05-11 08:24:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #define MSDOS_TRACE 1
0016
0017 #ifdef HAVE_CONFIG_H
0018 #include "config.h"
0019 #endif
0020
0021 #include <sys/types.h>
0022 #include <sys/stat.h>
0023 #include <fcntl.h>
0024 #include <unistd.h>
0025 #include <stdarg.h>
0026 #include <errno.h>
0027 #include <stdlib.h>
0028 #include <assert.h>
0029 #include <time.h>
0030
0031 #include <rtems/libio_.h>
0032
0033 #include "fat.h"
0034 #include "fat_fat_operations.h"
0035 #include "fat_file.h"
0036
0037 static inline void
0038 _hash_insert(rtems_chain_control *hash, uint32_t key1, uint32_t key2,
0039 fat_file_fd_t *el);
0040
0041 static inline void
0042 _hash_delete(rtems_chain_control *hash, uint32_t key1, uint32_t key2,
0043 fat_file_fd_t *el);
0044
0045 static inline int
0046 _hash_search(
0047 const fat_fs_info_t *fs_info,
0048 rtems_chain_control *hash,
0049 uint32_t key1,
0050 uint32_t key2,
0051 fat_file_fd_t **ret
0052 );
0053
0054 static off_t
0055 fat_file_lseek(
0056 fat_fs_info_t *fs_info,
0057 fat_file_fd_t *fat_fd,
0058 uint32_t file_cln,
0059 uint32_t *disk_cln
0060 );
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 int
0088 fat_file_open(
0089 fat_fs_info_t *fs_info,
0090 fat_dir_pos_t *dir_pos,
0091 fat_file_fd_t **fat_fd
0092 )
0093 {
0094 int rc = RC_OK;
0095 fat_file_fd_t *lfat_fd = NULL;
0096 uint32_t key = 0;
0097
0098
0099 key = fat_construct_key(fs_info, &dir_pos->sname);
0100
0101
0102 rc = _hash_search(fs_info, fs_info->vhash, key, 0, &lfat_fd);
0103 if ( rc == RC_OK )
0104 {
0105
0106 (*fat_fd) = lfat_fd;
0107 lfat_fd->links_num++;
0108 return rc;
0109 }
0110
0111
0112 rc = _hash_search(fs_info, fs_info->rhash, key, key, &lfat_fd);
0113
0114 lfat_fd = (*fat_fd) = (fat_file_fd_t*)calloc(1, sizeof(fat_file_fd_t));
0115 if ( lfat_fd == NULL )
0116 rtems_set_errno_and_return_minus_one( ENOMEM );
0117
0118 lfat_fd->links_num = 1;
0119 lfat_fd->flags &= ~FAT_FILE_REMOVED;
0120 lfat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
0121
0122 lfat_fd->dir_pos = *dir_pos;
0123
0124 if ( rc != RC_OK )
0125 lfat_fd->ino = key;
0126 else
0127 {
0128 lfat_fd->ino = fat_get_unique_ino(fs_info);
0129
0130 if ( lfat_fd->ino == 0 )
0131 {
0132 free((*fat_fd));
0133
0134
0135
0136
0137 rtems_set_errno_and_return_minus_one( ENOMEM );
0138 }
0139 }
0140 _hash_insert(fs_info->vhash, key, lfat_fd->ino, lfat_fd);
0141
0142
0143
0144
0145
0146
0147 return RC_OK;
0148 }
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168 int
0169 fat_file_get_new_inode_for(
0170 fat_fs_info_t *fs_info,
0171 fat_dir_pos_t *new_dir_pos,
0172 fat_file_fd_t *fat_fd
0173 )
0174 {
0175 fat_file_fd_t *lfat_fd = NULL;
0176 uint32_t old_key = 0;
0177 uint32_t new_key = 0;
0178 uint32_t old_inode = 0;
0179 uint32_t new_inode = 0;
0180 int rc = RC_OK;
0181
0182
0183 old_key = fat_construct_key(fs_info, &fat_fd->dir_pos.sname);
0184
0185
0186 new_key = fat_construct_key(fs_info, &new_dir_pos->sname);
0187
0188
0189
0190
0191
0192
0193
0194 rc = _hash_search(fs_info, fs_info->vhash, new_key, 0, &lfat_fd);
0195 assert(rc != RC_OK);
0196
0197
0198
0199
0200
0201 old_inode = fat_fd->ino;
0202 _hash_delete(fs_info->vhash, old_key, old_inode, fat_fd);
0203
0204
0205 fat_fd->dir_pos = *new_dir_pos;
0206
0207
0208
0209
0210
0211 if (fat_ino_is_unique(fs_info, old_inode))
0212 fat_free_unique_ino(fs_info, old_inode);
0213
0214
0215
0216
0217
0218
0219 rc = _hash_search(fs_info, fs_info->rhash, new_key, new_key, &lfat_fd);
0220 if (rc != RC_OK) new_inode = new_key;
0221 else new_inode = fat_get_unique_ino(fs_info);
0222
0223
0224
0225
0226
0227 _hash_insert(fs_info->vhash, new_key, new_inode, fat_fd);
0228 fat_fd->ino = new_inode;
0229 return RC_OK;
0230 }
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242 int
0243 fat_file_reopen(fat_file_fd_t *fat_fd)
0244 {
0245 fat_fd->links_num++;
0246 return RC_OK;
0247 }
0248
0249 int
0250 fat_file_update(fat_fs_info_t *fs_info, fat_file_fd_t *fat_fd)
0251 {
0252 int ret_rc = RC_OK;
0253
0254 if (!FAT_FILE_IS_REMOVED(fat_fd) &&
0255 FAT_FILE_HAS_META_DATA_CHANGED(fat_fd) &&
0256 !FAT_FD_OF_ROOT_DIR(fat_fd))
0257 {
0258 int rc;
0259
0260 rc = fat_file_write_first_cluster_num(fs_info, fat_fd);
0261 if (rc != RC_OK)
0262 ret_rc = rc;
0263
0264 rc = fat_file_write_file_size(fs_info, fat_fd);
0265 if (rc != RC_OK)
0266 ret_rc = rc;
0267
0268 rc = fat_file_write_time_and_date(fs_info, fat_fd);
0269 if (rc != RC_OK)
0270 ret_rc = rc;
0271 }
0272
0273 return ret_rc;
0274 }
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295 int
0296 fat_file_close(
0297 fat_fs_info_t *fs_info,
0298 fat_file_fd_t *fat_fd
0299 )
0300 {
0301 int rc = RC_OK;
0302
0303
0304
0305
0306
0307 if (fat_fd->links_num > 1)
0308 {
0309 fat_fd->links_num--;
0310 }
0311 else
0312 {
0313 uint32_t key = fat_construct_key(fs_info, &fat_fd->dir_pos.sname);
0314
0315 fat_file_update(fs_info, fat_fd);
0316
0317 if (fat_fd->flags & FAT_FILE_REMOVED)
0318 {
0319 rc = fat_file_truncate(fs_info, fat_fd, 0);
0320 if (rc == RC_OK)
0321 {
0322 _hash_delete(fs_info->rhash, key, fat_fd->ino, fat_fd);
0323
0324 if (fat_ino_is_unique(fs_info, fat_fd->ino))
0325 fat_free_unique_ino(fs_info, fat_fd->ino);
0326
0327 free(fat_fd);
0328 }
0329 }
0330 else
0331 {
0332 if (fat_ino_is_unique(fs_info, fat_fd->ino))
0333 {
0334 fat_fd->links_num = 0;
0335 }
0336 else
0337 {
0338 _hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
0339 free(fat_fd);
0340 }
0341 }
0342 }
0343
0344
0345
0346
0347 rc = fat_buf_release(fs_info);
0348
0349 return rc;
0350 }
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368 ssize_t
0369 fat_file_read(
0370 fat_fs_info_t *fs_info,
0371 fat_file_fd_t *fat_fd,
0372 uint32_t start,
0373 uint32_t count,
0374 uint8_t *buf
0375 )
0376 {
0377 int rc = RC_OK;
0378 ssize_t ret = 0;
0379 uint32_t cmpltd = 0;
0380 uint32_t cur_cln = 0;
0381 uint32_t cl_start = 0;
0382 uint32_t save_cln = 0;
0383 uint32_t ofs = 0;
0384 uint32_t save_ofs;
0385 uint32_t sec = 0;
0386 uint32_t sec_peek = 0;
0387 uint32_t byte = 0;
0388 uint32_t c = 0;
0389 uint32_t blk = 0;
0390 uint32_t blk_cnt = 0;
0391
0392
0393 if (count == 0)
0394 return cmpltd;
0395
0396
0397
0398
0399
0400 if ( start >= fat_fd->fat_file_size )
0401 return FAT_EOF;
0402
0403 if ((count > fat_fd->fat_file_size) ||
0404 (start > fat_fd->fat_file_size - count))
0405 count = fat_fd->fat_file_size - start;
0406
0407 if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
0408 (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
0409 {
0410 sec = fat_cluster_num_to_sector_num(fs_info, fat_fd->cln);
0411 sec += (start >> fs_info->vol.sec_log2);
0412 byte = start & (fs_info->vol.bps - 1);
0413
0414 ret = _fat_block_read(fs_info, sec, byte, count, buf);
0415 if ( ret < 0 )
0416 return -1;
0417
0418 return ret;
0419 }
0420
0421 cl_start = start >> fs_info->vol.bpc_log2;
0422 save_ofs = ofs = start & (fs_info->vol.bpc - 1);
0423
0424 rc = fat_file_lseek(fs_info, fat_fd, cl_start, &cur_cln);
0425 if (rc != RC_OK)
0426 return rc;
0427
0428 while (count > 0)
0429 {
0430 c = MIN(count, (fs_info->vol.bpc - ofs));
0431
0432 sec = fat_cluster_num_to_sector_num(fs_info, cur_cln);
0433
0434 save_cln = cur_cln;
0435 rc = fat_get_fat_cluster(fs_info, cur_cln, &cur_cln);
0436 if ( rc != RC_OK )
0437 return rc;
0438
0439 sec_peek = fat_cluster_num_to_sector_num(fs_info, cur_cln);
0440 blk = fat_sector_num_to_block_num (fs_info, sec_peek);
0441 blk_cnt = fs_info->vol.bpc >> fs_info->vol.bytes_per_block_log2;
0442 if (blk_cnt == 0)
0443 blk_cnt = 1;
0444 fat_block_peek(fs_info, blk, blk_cnt);
0445
0446 sec += (ofs >> fs_info->vol.sec_log2);
0447 byte = ofs & (fs_info->vol.bps - 1);
0448 ret = _fat_block_read(fs_info, sec, byte, c, buf + cmpltd);
0449 if ( ret < 0 )
0450 return -1;
0451
0452 count -= c;
0453 cmpltd += c;
0454
0455 ofs = 0;
0456 }
0457
0458
0459
0460 fat_fd->map.file_cln = cl_start +
0461 ((save_ofs + cmpltd - 1) >> fs_info->vol.bpc_log2);
0462 fat_fd->map.disk_cln = save_cln;
0463
0464 return cmpltd;
0465 }
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479 static bool
0480 fat_is_fat12_or_fat16_root_dir (const fat_file_fd_t *fat_fd,
0481 const uint8_t volume_type)
0482 {
0483 return (FAT_FD_OF_ROOT_DIR(fat_fd)) && (volume_type & (FAT_FAT12 | FAT_FAT16));
0484 }
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501 static ssize_t
0502 fat_file_write_fat32_or_non_root_dir(
0503 fat_fs_info_t *fs_info,
0504 fat_file_fd_t *fat_fd,
0505 const uint32_t start,
0506 const uint32_t count,
0507 const uint8_t *buf)
0508 {
0509 int rc = RC_OK;
0510 uint32_t cmpltd = 0;
0511 uint32_t cur_cln = 0;
0512 uint32_t save_cln = 0;
0513 uint32_t start_cln = start >> fs_info->vol.bpc_log2;
0514 uint32_t ofs_cln = start - (start_cln << fs_info->vol.bpc_log2);
0515 uint32_t ofs_cln_save = ofs_cln;
0516 uint32_t bytes_to_write = count;
0517 ssize_t ret;
0518 uint32_t c;
0519
0520 rc = fat_file_lseek(fs_info, fat_fd, start_cln, &cur_cln);
0521 if (RC_OK == rc)
0522 {
0523 while ( (RC_OK == rc)
0524 && (bytes_to_write > 0))
0525 {
0526 c = MIN(bytes_to_write, (fs_info->vol.bpc - ofs_cln));
0527
0528 ret = fat_cluster_write(fs_info,
0529 cur_cln,
0530 ofs_cln,
0531 c,
0532 &buf[cmpltd]);
0533 if (0 > ret)
0534 rc = -1;
0535
0536 if (RC_OK == rc)
0537 {
0538 bytes_to_write -= ret;
0539 cmpltd += ret;
0540 save_cln = cur_cln;
0541 if (0 < bytes_to_write)
0542 rc = fat_get_fat_cluster(fs_info, cur_cln, &cur_cln);
0543
0544 ofs_cln = 0;
0545 }
0546 }
0547
0548
0549
0550 fat_fd->map.file_cln = start_cln +
0551 ((ofs_cln_save + cmpltd - 1) >> fs_info->vol.bpc_log2);
0552 fat_fd->map.disk_cln = save_cln;
0553 }
0554
0555 if (RC_OK != rc)
0556 return rc;
0557 else
0558 return cmpltd;
0559 }
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577 ssize_t
0578 fat_file_write(
0579 fat_fs_info_t *fs_info,
0580 fat_file_fd_t *fat_fd,
0581 uint32_t start,
0582 uint32_t count,
0583 const uint8_t *buf
0584 )
0585 {
0586 int rc = RC_OK;
0587 ssize_t ret;
0588 uint32_t cmpltd = 0;
0589 uint32_t byte;
0590 uint32_t c = 0;
0591 bool zero_fill = start > fat_fd->fat_file_size;
0592 uint32_t cln;
0593
0594
0595 if ( count == 0 )
0596 return cmpltd;
0597
0598 if (start >= fat_fd->size_limit)
0599 rtems_set_errno_and_return_minus_one(EFBIG);
0600
0601 if (count > fat_fd->size_limit - start)
0602 count = fat_fd->size_limit - start;
0603
0604 rc = fat_file_extend(fs_info, fat_fd, zero_fill, start + count, &c);
0605 if (RC_OK == rc)
0606 {
0607
0608
0609
0610
0611 if (c != (start + count))
0612 count = c - start;
0613
0614
0615 if (fat_is_fat12_or_fat16_root_dir(fat_fd, fs_info->vol.type))
0616 {
0617 cln = fat_fd->cln;
0618 cln += (start >> fs_info->vol.bpc_log2);
0619 byte = start & (fs_info->vol.bpc -1);
0620
0621 ret = fat_cluster_write(fs_info,
0622 cln,
0623 byte,
0624 count,
0625 buf);
0626 if (0 > ret)
0627 rc = -1;
0628 else
0629 cmpltd = ret;
0630 }
0631 else
0632 {
0633 ret = fat_file_write_fat32_or_non_root_dir(fs_info,
0634 fat_fd,
0635 start,
0636 count,
0637 buf);
0638 if (0 > ret)
0639 rc = -1;
0640 else
0641 cmpltd = ret;
0642 }
0643 }
0644 if (RC_OK != rc)
0645 return rc;
0646 else
0647 return cmpltd;
0648 }
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666 int
0667 fat_file_extend(
0668 fat_fs_info_t *fs_info,
0669 fat_file_fd_t *fat_fd,
0670 bool zero_fill,
0671 uint32_t new_length,
0672 uint32_t *a_length
0673 )
0674 {
0675 int rc = RC_OK;
0676 uint32_t chain = 0;
0677 uint32_t bytes2add = 0;
0678 uint32_t cls2add = 0;
0679 uint32_t old_last_cl;
0680 uint32_t last_cl = 0;
0681 uint32_t bytes_remain = 0;
0682 uint32_t cls_added;
0683 ssize_t bytes_written;
0684
0685 *a_length = new_length;
0686
0687 if (new_length <= fat_fd->fat_file_size)
0688 return RC_OK;
0689
0690 if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
0691 (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
0692 rtems_set_errno_and_return_minus_one( ENOSPC );
0693
0694 bytes_remain = (fs_info->vol.bpc -
0695 (fat_fd->fat_file_size & (fs_info->vol.bpc - 1))) &
0696 (fs_info->vol.bpc - 1);
0697
0698 bytes2add = new_length - fat_fd->fat_file_size;
0699
0700 if (bytes2add > bytes_remain)
0701 bytes2add -= bytes_remain;
0702 else
0703 bytes2add = 0;
0704
0705 if (zero_fill && bytes_remain > 0) {
0706 uint32_t start = fat_fd->fat_file_size;
0707 uint32_t cl_start = start >> fs_info->vol.bpc_log2;
0708 uint32_t ofs = start & (fs_info->vol.bpc - 1);
0709 uint32_t cur_cln;
0710
0711 rc = fat_file_lseek(fs_info, fat_fd, cl_start, &cur_cln);
0712 if (rc != RC_OK)
0713 return rc;
0714
0715 bytes_written = fat_cluster_set (fs_info, cur_cln, ofs, bytes_remain, 0);
0716 if (bytes_remain != bytes_written)
0717 return -1;
0718 }
0719
0720
0721
0722
0723
0724
0725 if (bytes2add == 0)
0726 return RC_OK;
0727
0728 cls2add = ((bytes2add - 1) >> fs_info->vol.bpc_log2) + 1;
0729
0730 rc = fat_scan_fat_for_free_clusters(fs_info, &chain, cls2add,
0731 &cls_added, &last_cl, zero_fill);
0732
0733
0734 if (rc != RC_OK)
0735 return rc;
0736
0737
0738 if ((cls_added == 0) && (bytes_remain == 0))
0739 rtems_set_errno_and_return_minus_one(ENOSPC);
0740
0741
0742 if (cls2add != cls_added)
0743 {
0744 uint32_t missing = (cls2add - cls_added) << fs_info->vol.bpc_log2;
0745
0746 new_length -= bytes2add < missing ? bytes2add : missing;
0747 }
0748
0749 if (cls_added > 0)
0750 {
0751
0752 if ( fat_fd->fat_file_size == 0 )
0753 {
0754 fat_fd->map.disk_cln = chain;
0755 fat_fd->map.file_cln = 0;
0756 fat_file_set_first_cluster_num(fat_fd, chain);
0757 }
0758 else
0759 {
0760 if (fat_fd->map.last_cln != FAT_UNDEFINED_VALUE)
0761 {
0762 old_last_cl = fat_fd->map.last_cln;
0763 }
0764 else
0765 {
0766 rc = fat_file_ioctl(fs_info, fat_fd, F_CLU_NUM,
0767 (fat_fd->fat_file_size - 1), &old_last_cl);
0768 if ( rc != RC_OK )
0769 {
0770 fat_free_fat_clusters_chain(fs_info, chain);
0771 return rc;
0772 }
0773 }
0774
0775 rc = fat_set_fat_cluster(fs_info, old_last_cl, chain);
0776 if ( rc != RC_OK )
0777 {
0778 fat_free_fat_clusters_chain(fs_info, chain);
0779 return rc;
0780 }
0781 fat_buf_release(fs_info);
0782 }
0783
0784
0785 fat_fd->map.last_cln = last_cl;
0786
0787 if (fat_fd->fat_file_type == FAT_DIRECTORY)
0788 {
0789 rc = fat_init_clusters_chain(fs_info, chain);
0790 if ( rc != RC_OK )
0791 {
0792 fat_free_fat_clusters_chain(fs_info, chain);
0793 return rc;
0794 }
0795 }
0796 }
0797
0798 *a_length = new_length;
0799 fat_file_set_file_size(fat_fd, new_length);
0800
0801 return RC_OK;
0802 }
0803
0804
0805
0806
0807
0808
0809
0810
0811
0812
0813
0814
0815
0816
0817 int
0818 fat_file_truncate(
0819 fat_fs_info_t *fs_info,
0820 fat_file_fd_t *fat_fd,
0821 uint32_t new_length
0822 )
0823 {
0824 int rc = RC_OK;
0825 uint32_t cur_cln = 0;
0826 uint32_t cl_start = 0;
0827 uint32_t new_last_cln = FAT_UNDEFINED_VALUE;
0828
0829
0830 if ( new_length >= fat_fd->fat_file_size )
0831 return rc;
0832
0833 assert(fat_fd->fat_file_size);
0834
0835 cl_start = (new_length + fs_info->vol.bpc - 1) >> fs_info->vol.bpc_log2;
0836
0837 if ((cl_start << fs_info->vol.bpc_log2) >= fat_fd->fat_file_size)
0838 return RC_OK;
0839
0840 if (cl_start != 0)
0841 {
0842 rc = fat_file_lseek(fs_info, fat_fd, cl_start - 1, &new_last_cln);
0843 if (rc != RC_OK)
0844 return rc;
0845
0846 }
0847
0848 rc = fat_file_lseek(fs_info, fat_fd, cl_start, &cur_cln);
0849 if (rc != RC_OK)
0850 return rc;
0851
0852 rc = fat_free_fat_clusters_chain(fs_info, cur_cln);
0853 if (rc != RC_OK)
0854 return rc;
0855
0856 if (cl_start != 0)
0857 {
0858 rc = fat_set_fat_cluster(fs_info, new_last_cln, FAT_GENFAT_EOC);
0859 if ( rc != RC_OK )
0860 return rc;
0861 fat_fd->map.file_cln = cl_start - 1;
0862 fat_fd->map.disk_cln = new_last_cln;
0863 fat_fd->map.last_cln = new_last_cln;
0864 }
0865 else
0866 {
0867 fat_file_set_first_cluster_num(fat_fd, FAT_GENFAT_FREE);
0868 fat_fd->map.file_cln = FAT_UNDEFINED_VALUE;
0869 fat_fd->map.disk_cln = FAT_UNDEFINED_VALUE;
0870 fat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
0871 }
0872 return RC_OK;
0873 }
0874
0875
0876
0877
0878
0879
0880
0881
0882
0883
0884
0885
0886
0887
0888
0889 int
0890 fat_file_ioctl(
0891 fat_fs_info_t *fs_info,
0892 fat_file_fd_t *fat_fd,
0893 int cmd,
0894 ...)
0895 {
0896 int rc = RC_OK;
0897 uint32_t cur_cln = 0;
0898 uint32_t cl_start = 0;
0899 uint32_t pos = 0;
0900 uint32_t *ret;
0901 va_list ap;
0902
0903 va_start(ap, cmd);
0904
0905 switch (cmd)
0906 {
0907 case F_CLU_NUM:
0908 pos = va_arg(ap, uint32_t);
0909 ret = va_arg(ap, uint32_t *);
0910
0911
0912 if ( pos >= fat_fd->fat_file_size ) {
0913 va_end(ap);
0914 rtems_set_errno_and_return_minus_one( EIO );
0915 }
0916
0917 if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
0918 (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
0919 {
0920
0921 *ret = 0;
0922 rc = RC_OK;
0923 break;
0924 }
0925
0926 cl_start = pos >> fs_info->vol.bpc_log2;
0927
0928 rc = fat_file_lseek(fs_info, fat_fd, cl_start, &cur_cln);
0929 if ( rc != RC_OK )
0930 break;
0931
0932 *ret = cur_cln;
0933 break;
0934
0935 default:
0936 errno = EINVAL;
0937 rc = -1;
0938 break;
0939 }
0940 va_end(ap);
0941 return rc;
0942 }
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955 void
0956 fat_file_mark_removed(
0957 fat_fs_info_t *fs_info,
0958 fat_file_fd_t *fat_fd
0959 )
0960 {
0961 uint32_t key = 0;
0962
0963 key = fat_construct_key(fs_info, &fat_fd->dir_pos.sname);
0964
0965 _hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
0966
0967 _hash_insert(fs_info->rhash, key, fat_fd->ino, fat_fd);
0968
0969 fat_fd->flags |= FAT_FILE_REMOVED;
0970 }
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988 int
0989 fat_file_size(
0990 fat_fs_info_t *fs_info,
0991 fat_file_fd_t *fat_fd
0992 )
0993 {
0994 int rc = RC_OK;
0995 uint32_t cur_cln = fat_fd->cln;
0996 uint32_t save_cln = 0;
0997
0998
0999 if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
1000 (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
1001 {
1002 fat_fd->fat_file_size = fs_info->vol.rdir_size;
1003 return rc;
1004 }
1005
1006 fat_fd->fat_file_size = 0;
1007
1008 while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
1009 {
1010 save_cln = cur_cln;
1011 rc = fat_get_fat_cluster(fs_info, cur_cln, &cur_cln);
1012 if ( rc != RC_OK )
1013 return rc;
1014
1015 fat_fd->fat_file_size += fs_info->vol.bpc;
1016 }
1017 fat_fd->map.last_cln = save_cln;
1018 return rc;
1019 }
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035 static inline void
1036 _hash_insert(rtems_chain_control *hash, uint32_t key1, uint32_t key2,
1037 fat_file_fd_t *el)
1038 {
1039 rtems_chain_append_unprotected((hash) + ((key1) % FAT_HASH_MODULE), &(el)->link);
1040 }
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055 static inline void
1056 _hash_delete(rtems_chain_control *hash, uint32_t key1, uint32_t key2,
1057 fat_file_fd_t *el)
1058 {
1059 rtems_chain_extract_unprotected(&(el)->link);
1060 }
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076 static inline int
1077 _hash_search(
1078 const fat_fs_info_t *fs_info,
1079 rtems_chain_control *hash,
1080 uint32_t key1,
1081 uint32_t key2,
1082 fat_file_fd_t **ret
1083 )
1084 {
1085 uint32_t mod = (key1) % FAT_HASH_MODULE;
1086 rtems_chain_node *the_node = rtems_chain_first(hash + mod);
1087
1088 for ( ; !rtems_chain_is_tail((hash) + mod, the_node) ; )
1089 {
1090 fat_file_fd_t *ffd = (fat_file_fd_t *)the_node;
1091 uint32_t ck = fat_construct_key(fs_info, &ffd->dir_pos.sname);
1092
1093 if ( (key1) == ck)
1094 {
1095 if ( ((key2) == 0) || ((key2) == ffd->ino) )
1096 {
1097 *ret = (void *)the_node;
1098 return 0;
1099 }
1100 }
1101 the_node = the_node->next;
1102 }
1103 return -1;
1104 }
1105
1106 static off_t
1107 fat_file_lseek(
1108 fat_fs_info_t *fs_info,
1109 fat_file_fd_t *fat_fd,
1110 uint32_t file_cln,
1111 uint32_t *disk_cln
1112 )
1113 {
1114 int rc = RC_OK;
1115
1116 if (file_cln == fat_fd->map.file_cln)
1117 *disk_cln = fat_fd->map.disk_cln;
1118 else
1119 {
1120 uint32_t cur_cln;
1121 uint32_t count;
1122 uint32_t i;
1123
1124 if (file_cln > fat_fd->map.file_cln)
1125 {
1126 cur_cln = fat_fd->map.disk_cln;
1127 count = file_cln - fat_fd->map.file_cln;
1128 }
1129 else
1130 {
1131 cur_cln = fat_fd->cln;
1132 count = file_cln;
1133 }
1134
1135
1136 for (i = 0; i < count; i++)
1137 {
1138 rc = fat_get_fat_cluster(fs_info, cur_cln, &cur_cln);
1139 if ( rc != RC_OK )
1140 return rc;
1141 }
1142
1143
1144 fat_fd->map.file_cln = file_cln;
1145 fat_fd->map.disk_cln = cur_cln;
1146
1147 *disk_cln = cur_cln;
1148 }
1149 return RC_OK;
1150 }