File indexing completed on 2025-05-11 08:24:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifdef HAVE_CONFIG_H
0015 #include "config.h"
0016 #endif
0017
0018 #include <sys/types.h>
0019 #include <sys/stat.h>
0020 #include <fcntl.h>
0021 #include <unistd.h>
0022 #include <errno.h>
0023 #include <stdlib.h>
0024 #include <stdint.h>
0025
0026 #include <rtems/libio_.h>
0027
0028 #include "fat.h"
0029 #include "fat_fat_operations.h"
0030
0031 static int
0032 _fat_block_release(fat_fs_info_t *fs_info);
0033
0034 static inline uint32_t
0035 fat_cluster_num_to_block_num (const fat_fs_info_t *fs_info,
0036 uint32_t cln)
0037 {
0038 uint32_t blk;
0039
0040 if ( (cln == 0) && (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)) )
0041 blk = fat_sector_num_to_block_num(fs_info, fs_info->vol.rdir_loc);
0042 else
0043 {
0044 cln -= FAT_RSRVD_CLN;
0045 blk = cln << (fs_info->vol.bpc_log2 - fs_info->vol.bytes_per_block_log2);
0046 blk += fat_sector_num_to_block_num(fs_info, fs_info->vol.data_fsec);
0047 }
0048
0049 return blk;
0050 }
0051
0052 int
0053 fat_buf_access(fat_fs_info_t *fs_info,
0054 const uint32_t sec_num,
0055 const int op_type,
0056 uint8_t **sec_buf)
0057 {
0058 rtems_status_code sc = RTEMS_SUCCESSFUL;
0059 uint32_t blk = fat_sector_num_to_block_num (fs_info,
0060 sec_num);
0061 uint32_t blk_ofs = fat_sector_offset_to_block_offset (fs_info,
0062 sec_num,
0063 0);
0064
0065 if (fs_info->c.state == FAT_CACHE_EMPTY || fs_info->c.blk_num != sec_num)
0066 {
0067 fat_buf_release(fs_info);
0068
0069 if (op_type == FAT_OP_TYPE_READ)
0070 sc = rtems_bdbuf_read(fs_info->vol.dd, blk, &fs_info->c.buf);
0071 else
0072 sc = rtems_bdbuf_get(fs_info->vol.dd, blk, &fs_info->c.buf);
0073 if (sc != RTEMS_SUCCESSFUL)
0074 rtems_set_errno_and_return_minus_one(EIO);
0075 fs_info->c.blk_num = sec_num;
0076 fs_info->c.modified = 0;
0077 fs_info->c.state = FAT_CACHE_ACTUAL;
0078 }
0079 *sec_buf = &fs_info->c.buf->buffer[blk_ofs];
0080 return RC_OK;
0081 }
0082
0083 int
0084 fat_buf_release(fat_fs_info_t *fs_info)
0085 {
0086 rtems_status_code sc = RTEMS_SUCCESSFUL;
0087
0088 if (fs_info->c.state == FAT_CACHE_EMPTY)
0089 return RC_OK;
0090
0091 if (fs_info->c.modified)
0092 {
0093 uint32_t sec_num = fs_info->c.blk_num;
0094 bool sec_of_fat = ((sec_num >= fs_info->vol.fat_loc) &&
0095 (sec_num < fs_info->vol.rdir_loc));
0096 uint32_t blk_ofs = fat_sector_offset_to_block_offset(fs_info,
0097 sec_num,
0098 0);
0099
0100 if (sec_of_fat && !fs_info->vol.mirror)
0101 memcpy(fs_info->sec_buf,
0102 fs_info->c.buf->buffer + blk_ofs,
0103 fs_info->vol.bps);
0104
0105 sc = rtems_bdbuf_release_modified(fs_info->c.buf);
0106 if (sc != RTEMS_SUCCESSFUL)
0107 rtems_set_errno_and_return_minus_one(EIO);
0108 fs_info->c.modified = 0;
0109
0110 if (sec_of_fat && !fs_info->vol.mirror)
0111 {
0112 uint8_t i;
0113
0114 for (i = 1; i < fs_info->vol.fats; i++)
0115 {
0116 rtems_bdbuf_buffer *bd;
0117 uint32_t blk;
0118
0119 sec_num = fs_info->c.blk_num + fs_info->vol.fat_length * i,
0120 blk = fat_sector_num_to_block_num(fs_info, sec_num);
0121 blk_ofs = fat_sector_offset_to_block_offset(fs_info,
0122 sec_num,
0123 0);
0124
0125 if (blk_ofs == 0
0126 && fs_info->vol.bps == fs_info->vol.bytes_per_block)
0127 {
0128 sc = rtems_bdbuf_get(fs_info->vol.dd, blk, &bd);
0129 }
0130 else
0131 {
0132 sc = rtems_bdbuf_read(fs_info->vol.dd, blk, &bd);
0133 }
0134 if ( sc != RTEMS_SUCCESSFUL)
0135 rtems_set_errno_and_return_minus_one(ENOMEM);
0136 memcpy(bd->buffer + blk_ofs, fs_info->sec_buf, fs_info->vol.bps);
0137 sc = rtems_bdbuf_release_modified(bd);
0138 if ( sc != RTEMS_SUCCESSFUL)
0139 rtems_set_errno_and_return_minus_one(ENOMEM);
0140 }
0141 }
0142 }
0143 else
0144 {
0145 sc = rtems_bdbuf_release(fs_info->c.buf);
0146 if (sc != RTEMS_SUCCESSFUL)
0147 rtems_set_errno_and_return_minus_one(EIO);
0148 }
0149 fs_info->c.state = FAT_CACHE_EMPTY;
0150 return RC_OK;
0151 }
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170 ssize_t
0171 _fat_block_read(
0172 fat_fs_info_t *fs_info,
0173 uint32_t start,
0174 uint32_t offset,
0175 uint32_t count,
0176 void *buff
0177 )
0178 {
0179 int rc = RC_OK;
0180 ssize_t cmpltd = 0;
0181 uint32_t sec_num = start;
0182 uint32_t ofs = offset;
0183 uint8_t *sec_buf;
0184 uint32_t c = 0;
0185
0186 while (count > 0)
0187 {
0188 rc = fat_buf_access(fs_info, sec_num, FAT_OP_TYPE_READ, &sec_buf);
0189 if (rc != RC_OK)
0190 return -1;
0191
0192 c = MIN(count, (fs_info->vol.bps - ofs));
0193 memcpy((buff + cmpltd), (sec_buf + ofs), c);
0194
0195 count -= c;
0196 cmpltd += c;
0197 sec_num++;
0198 ofs = 0;
0199 }
0200 return cmpltd;
0201 }
0202
0203 void
0204 fat_block_peek(
0205 fat_fs_info_t *fs_info,
0206 const uint32_t blk,
0207 const uint32_t blk_cnt
0208 )
0209 {
0210 rtems_bdbuf_peek(fs_info->vol.dd, blk, blk_cnt);
0211 }
0212
0213 static ssize_t
0214 fat_block_write(
0215 fat_fs_info_t *fs_info,
0216 const uint32_t start_blk,
0217 const uint32_t offset,
0218 const uint32_t count,
0219 const void *buf)
0220 {
0221 int rc = RC_OK;
0222 uint32_t bytes_to_write = MIN(count, (fs_info->vol.bytes_per_block - offset));
0223 uint8_t *blk_buf;
0224 uint32_t sec_num = fat_block_num_to_sector_num(fs_info, start_blk);
0225
0226 if (0 < bytes_to_write)
0227 {
0228 if (bytes_to_write == fs_info->vol.bytes_per_block)
0229 {
0230 rc = fat_buf_access(fs_info, sec_num, FAT_OP_TYPE_GET, &blk_buf);
0231 }
0232 else
0233 rc = fat_buf_access(fs_info, sec_num, FAT_OP_TYPE_READ, &blk_buf);
0234
0235 if (RC_OK == rc)
0236 {
0237 memcpy(blk_buf + offset, buf, bytes_to_write);
0238
0239 fat_buf_mark_modified(fs_info);
0240 }
0241 }
0242 if (RC_OK != rc)
0243 return rc;
0244 else
0245 return bytes_to_write;
0246 }
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265 ssize_t
0266 fat_sector_write(
0267 fat_fs_info_t *fs_info,
0268 uint32_t start,
0269 uint32_t offset,
0270 uint32_t count,
0271 const void *buff)
0272 {
0273 int rc = RC_OK;
0274 ssize_t cmpltd = 0;
0275 uint32_t sec_num = start;
0276 uint32_t ofs = offset;
0277 uint8_t *sec_buf;
0278 uint32_t c = 0;
0279
0280 while(count > 0)
0281 {
0282 c = MIN(count, (fs_info->vol.bps - ofs));
0283
0284 if (c == fs_info->vol.bytes_per_block)
0285 rc = fat_buf_access(fs_info, sec_num, FAT_OP_TYPE_GET, &sec_buf);
0286 else
0287 rc = fat_buf_access(fs_info, sec_num, FAT_OP_TYPE_READ, &sec_buf);
0288 if (rc != RC_OK)
0289 return -1;
0290
0291 memcpy((sec_buf + ofs), (buff + cmpltd), c);
0292
0293 fat_buf_mark_modified(fs_info);
0294
0295 count -= c;
0296 cmpltd +=c;
0297 sec_num++;
0298 ofs = 0;
0299 }
0300 return cmpltd;
0301 }
0302
0303 static ssize_t
0304 fat_block_set (
0305 fat_fs_info_t *fs_info,
0306 const uint32_t start_blk,
0307 const uint32_t offset,
0308 const uint32_t count,
0309 const uint8_t pattern)
0310 {
0311 int rc = RC_OK;
0312 uint32_t bytes_to_write = MIN(count, (fs_info->vol.bytes_per_block - offset));
0313 uint8_t *blk_buf;
0314 uint32_t sec_num = fat_block_num_to_sector_num(fs_info, start_blk);
0315
0316 if (0 < bytes_to_write)
0317 {
0318 if (bytes_to_write == fs_info->vol.bytes_per_block)
0319 {
0320 rc = fat_buf_access(fs_info, sec_num, FAT_OP_TYPE_GET, &blk_buf);
0321 }
0322 else
0323 rc = fat_buf_access(fs_info, sec_num, FAT_OP_TYPE_READ, &blk_buf);
0324
0325 if (RC_OK == rc)
0326 {
0327 memset(blk_buf + offset, pattern, bytes_to_write);
0328
0329 fat_buf_mark_modified(fs_info);
0330 }
0331 }
0332 if (RC_OK != rc)
0333 return rc;
0334 else
0335 return bytes_to_write;
0336 }
0337
0338 ssize_t
0339 fat_cluster_set(
0340 fat_fs_info_t *fs_info,
0341 const uint32_t start_cln,
0342 const uint32_t offset,
0343 const uint32_t count,
0344 const uint8_t pattern)
0345 {
0346 ssize_t rc = RC_OK;
0347 uint32_t bytes_to_write = MIN(count, (fs_info->vol.bpc - offset));
0348 uint32_t cur_blk = fat_cluster_num_to_block_num(fs_info, start_cln);
0349 uint32_t blocks_in_offset = offset >> fs_info->vol.bytes_per_block_log2;
0350 uint32_t ofs_blk = offset - (blocks_in_offset << fs_info->vol.bytes_per_block_log2);
0351 ssize_t bytes_written = 0;
0352 ssize_t ret;
0353
0354 cur_blk += blocks_in_offset;
0355
0356 while ( (RC_OK == rc)
0357 && (0 < bytes_to_write))
0358 {
0359 uint32_t c = MIN(bytes_to_write, (fs_info->vol.bytes_per_block - ofs_blk));
0360
0361 ret = fat_block_set(
0362 fs_info,
0363 cur_blk,
0364 ofs_blk,
0365 c,
0366 pattern);
0367 if (c != ret)
0368 rc = -1;
0369 else
0370 {
0371 bytes_to_write -= ret;
0372 bytes_written += ret;
0373 ++cur_blk;
0374 }
0375 ofs_blk = 0;
0376 }
0377 if (RC_OK != rc)
0378 return rc;
0379 else
0380 return bytes_written;
0381 }
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393 int
0394 _fat_block_release(fat_fs_info_t *fs_info)
0395 {
0396 return fat_buf_release(fs_info);
0397 }
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416 ssize_t
0417 fat_cluster_write(
0418 fat_fs_info_t *fs_info,
0419 const uint32_t start_cln,
0420 const uint32_t offset,
0421 const uint32_t count,
0422 const void *buff)
0423 {
0424 ssize_t rc = RC_OK;
0425 uint32_t bytes_to_write = MIN(count, (fs_info->vol.bpc - offset));
0426 uint32_t cur_blk = fat_cluster_num_to_block_num(fs_info, start_cln);
0427 uint32_t blocks_in_offset = (offset >> fs_info->vol.bytes_per_block_log2);
0428 uint32_t ofs_blk = offset - (blocks_in_offset << fs_info->vol.bytes_per_block_log2);
0429 ssize_t bytes_written = 0;
0430 uint8_t *buffer = (uint8_t*)buff;
0431 ssize_t ret;
0432 uint32_t c;
0433
0434 cur_blk += blocks_in_offset;
0435
0436 while ( (RC_OK == rc)
0437 && (0 < bytes_to_write))
0438 {
0439 c = MIN(bytes_to_write, (fs_info->vol.bytes_per_block - ofs_blk));
0440
0441 ret = fat_block_write(
0442 fs_info,
0443 cur_blk,
0444 ofs_blk,
0445 c,
0446 &buffer[bytes_written]);
0447 if (c != ret)
0448 rc = -1;
0449 else
0450 {
0451 bytes_to_write -= ret;
0452 bytes_written += ret;
0453 ++cur_blk;
0454 }
0455 ofs_blk = 0;
0456 }
0457 if (RC_OK != rc)
0458 return rc;
0459 else
0460 return bytes_written;
0461 }
0462
0463 static bool is_cluster_aligned(const fat_vol_t *vol, uint32_t sec_num)
0464 {
0465 return (sec_num & (vol->spc - 1)) == 0;
0466 }
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478 int
0479 fat_init_volume_info(fat_fs_info_t *fs_info, const char *device)
0480 {
0481 rtems_status_code sc = RTEMS_SUCCESSFUL;
0482 int rc = RC_OK;
0483 fat_vol_t *vol = &fs_info->vol;
0484 uint32_t data_secs = 0;
0485 char boot_rec[FAT_MAX_BPB_SIZE];
0486 char fs_info_sector[FAT_USEFUL_INFO_SIZE];
0487 ssize_t ret = 0;
0488 struct stat stat_buf;
0489 int i = 0;
0490 rtems_bdbuf_buffer *block = NULL;
0491
0492 vol->fd = open(device, O_RDWR);
0493 if (vol->fd < 0)
0494 {
0495 rtems_set_errno_and_return_minus_one(ENXIO);
0496 }
0497
0498 rc = fstat(vol->fd, &stat_buf);
0499 if (rc != 0)
0500 {
0501 close(vol->fd);
0502 rtems_set_errno_and_return_minus_one(ENXIO);
0503 }
0504
0505
0506 if (!S_ISBLK(stat_buf.st_mode))
0507 {
0508 close(vol->fd);
0509 rtems_set_errno_and_return_minus_one(ENXIO);
0510 }
0511
0512
0513 rc = rtems_disk_fd_get_disk_device(vol->fd, &vol->dd);
0514 if (rc != 0) {
0515 close(vol->fd);
0516 rtems_set_errno_and_return_minus_one(ENXIO);
0517 }
0518
0519 vol->dev = stat_buf.st_rdev;
0520
0521
0522
0523 sc = rtems_bdbuf_read( vol->dd, 0, &block);
0524 if (sc != RTEMS_SUCCESSFUL)
0525 {
0526 close(vol->fd);
0527 rtems_set_errno_and_return_minus_one( EIO);
0528 }
0529
0530 memcpy( boot_rec, block->buffer, FAT_MAX_BPB_SIZE);
0531
0532 sc = rtems_bdbuf_release( block);
0533 if (sc != RTEMS_SUCCESSFUL)
0534 {
0535 close(vol->fd);
0536 rtems_set_errno_and_return_minus_one( EIO );
0537 }
0538
0539
0540 vol->bps = FAT_GET_BR_BYTES_PER_SECTOR(boot_rec);
0541
0542 if ( (vol->bps != 512) &&
0543 (vol->bps != 1024) &&
0544 (vol->bps != 2048) &&
0545 (vol->bps != 4096))
0546 {
0547 close(vol->fd);
0548 rtems_set_errno_and_return_minus_one( EINVAL );
0549 }
0550 for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0;
0551 i >>= 1, vol->sec_mul++);
0552 for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0;
0553 i >>= 1, vol->sec_log2++);
0554
0555
0556
0557
0558 sc = rtems_bdbuf_set_block_size (vol->dd, vol->bps, true);
0559 if (sc != RTEMS_SUCCESSFUL)
0560 {
0561 close(vol->fd);
0562 rtems_set_errno_and_return_minus_one( EINVAL );
0563 }
0564 vol->bytes_per_block = vol->bps;
0565 vol->bytes_per_block_log2 = vol->sec_log2;
0566 vol->sectors_per_block = 1;
0567
0568 vol->spc = FAT_GET_BR_SECTORS_PER_CLUSTER(boot_rec);
0569
0570
0571
0572
0573 if (vol->spc == 0)
0574 {
0575 close(vol->fd);
0576 rtems_set_errno_and_return_minus_one(EINVAL);
0577 }
0578
0579 for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0;
0580 i >>= 1, vol->spc_log2++);
0581
0582
0583 if (vol->spc != UINT32_C(1) << vol->spc_log2)
0584 {
0585 close(vol->fd);
0586 rtems_set_errno_and_return_minus_one(EINVAL);
0587 }
0588
0589 vol->bpc = ((uint32_t) vol->bps) << vol->spc_log2;
0590
0591 for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0;
0592 i >>= 1, vol->bpc_log2++);
0593
0594 vol->fats = FAT_GET_BR_FAT_NUM(boot_rec);
0595 vol->fat_loc = FAT_GET_BR_RESERVED_SECTORS_NUM(boot_rec);
0596
0597 vol->rdir_entrs = FAT_GET_BR_FILES_PER_ROOT_DIR(boot_rec);
0598
0599
0600 vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) /
0601 vol->bps;
0602
0603 vol->rdir_size = vol->rdir_secs << vol->sec_log2;
0604
0605 if ( (FAT_GET_BR_SECTORS_PER_FAT(boot_rec)) != 0)
0606 vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT(boot_rec);
0607 else
0608 vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT32(boot_rec);
0609
0610 vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length +
0611 vol->rdir_secs;
0612
0613
0614 vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length;
0615
0616 if ( (FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0)
0617 vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec);
0618 else
0619 vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM32(boot_rec);
0620
0621 data_secs = vol->tot_secs - vol->data_fsec;
0622
0623 vol->data_cls = data_secs / vol->spc;
0624
0625
0626 if ( vol->data_cls < FAT_FAT12_MAX_CLN)
0627 {
0628 vol->type = FAT_FAT12;
0629 vol->mask = FAT_FAT12_MASK;
0630 vol->eoc_val = FAT_FAT12_EOC;
0631 }
0632 else
0633 {
0634 if ( vol->data_cls < FAT_FAT16_MAX_CLN)
0635 {
0636 vol->type = FAT_FAT16;
0637 vol->mask = FAT_FAT16_MASK;
0638 vol->eoc_val = FAT_FAT16_EOC;
0639 }
0640 else if ( vol->data_cls < FAT_FAT32_MASK - 1 )
0641 {
0642 vol->type = FAT_FAT32;
0643 vol->mask = FAT_FAT32_MASK;
0644 vol->eoc_val = FAT_FAT32_EOC;
0645 }
0646 else
0647 {
0648 close(vol->fd);
0649 rtems_set_errno_and_return_minus_one( EINVAL );
0650 }
0651 }
0652
0653 if (vol->type == FAT_FAT32)
0654 {
0655 vol->rdir_cl = FAT_GET_BR_FAT32_ROOT_CLUSTER(boot_rec);
0656
0657 vol->mirror = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR;
0658 if (vol->mirror)
0659 vol->afat = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM;
0660 else
0661 vol->afat = 0;
0662
0663 vol->info_sec = FAT_GET_BR_FAT32_FS_INFO_SECTOR(boot_rec);
0664 if( vol->info_sec == 0 )
0665 {
0666 close(vol->fd);
0667 rtems_set_errno_and_return_minus_one( EINVAL );
0668 }
0669 else
0670 {
0671 ret = _fat_block_read(fs_info, vol->info_sec , 0,
0672 FAT_FSI_LEADSIG_SIZE, fs_info_sector);
0673 if ( ret < 0 )
0674 {
0675 close(vol->fd);
0676 return -1;
0677 }
0678
0679 if (FAT_GET_FSINFO_LEAD_SIGNATURE(fs_info_sector) !=
0680 FAT_FSINFO_LEAD_SIGNATURE_VALUE)
0681 {
0682 _fat_block_release(fs_info);
0683 close(vol->fd);
0684 rtems_set_errno_and_return_minus_one( EINVAL );
0685 }
0686 else
0687 {
0688 ret = _fat_block_read(fs_info, vol->info_sec , FAT_FSI_INFO,
0689 FAT_USEFUL_INFO_SIZE, fs_info_sector);
0690 if ( ret < 0 )
0691 {
0692 _fat_block_release(fs_info);
0693 close(vol->fd);
0694 return -1;
0695 }
0696
0697 vol->free_cls_in_fs_info =
0698 FAT_GET_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector);
0699 vol->free_cls = vol->free_cls_in_fs_info;
0700 vol->next_cl_in_fs_info =
0701 FAT_GET_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector);
0702 vol->next_cl = vol->next_cl_in_fs_info;
0703 }
0704 }
0705 }
0706 else
0707 {
0708 vol->rdir_cl = 0;
0709 vol->mirror = 0;
0710 vol->afat = 0;
0711 vol->free_cls = FAT_UNDEFINED_VALUE;
0712 vol->next_cl = FAT_UNDEFINED_VALUE;
0713 }
0714
0715 _fat_block_release(fs_info);
0716
0717 vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat;
0718
0719
0720 fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(rtems_chain_control));
0721 if ( fs_info->vhash == NULL )
0722 {
0723 close(vol->fd);
0724 rtems_set_errno_and_return_minus_one( ENOMEM );
0725 }
0726
0727 for (i = 0; i < FAT_HASH_SIZE; i++)
0728 rtems_chain_initialize_empty(fs_info->vhash + i);
0729
0730 fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(rtems_chain_control));
0731 if ( fs_info->rhash == NULL )
0732 {
0733 close(vol->fd);
0734 free(fs_info->vhash);
0735 rtems_set_errno_and_return_minus_one( ENOMEM );
0736 }
0737 for (i = 0; i < FAT_HASH_SIZE; i++)
0738 rtems_chain_initialize_empty(fs_info->rhash + i);
0739
0740 fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE;
0741 fs_info->uino_base = (vol->tot_secs << vol->sec_mul) << 4;
0742 fs_info->index = 0;
0743 fs_info->uino = (char *)calloc(fs_info->uino_pool_size, sizeof(char));
0744 if ( fs_info->uino == NULL )
0745 {
0746 close(vol->fd);
0747 free(fs_info->vhash);
0748 free(fs_info->rhash);
0749 rtems_set_errno_and_return_minus_one( ENOMEM );
0750 }
0751 fs_info->sec_buf = (uint8_t *)calloc(vol->bps, sizeof(uint8_t));
0752 if (fs_info->sec_buf == NULL)
0753 {
0754 close(vol->fd);
0755 free(fs_info->vhash);
0756 free(fs_info->rhash);
0757 free(fs_info->uino);
0758 rtems_set_errno_and_return_minus_one( ENOMEM );
0759 }
0760
0761
0762
0763
0764
0765
0766 if (is_cluster_aligned(vol, vol->data_fsec)
0767 && (FAT_FAT32 == vol->type || is_cluster_aligned(vol, vol->rdir_loc)))
0768 {
0769 sc = rtems_bdbuf_set_block_size (vol->dd, vol->bpc, true);
0770 if (sc == RTEMS_SUCCESSFUL)
0771 {
0772 vol->bytes_per_block = vol->bpc;
0773 vol->bytes_per_block_log2 = vol->bpc_log2;
0774 vol->sectors_per_block = vol->spc;
0775 }
0776 }
0777
0778 return RC_OK;
0779 }
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790 static int
0791 fat_fat32_update_fsinfo_sector(fat_fs_info_t *fs_info)
0792 {
0793 ssize_t ret1 = 0, ret2 = 0;
0794
0795 if (fs_info->vol.type == FAT_FAT32)
0796 {
0797 uint32_t free_count = fs_info->vol.free_cls;
0798 uint32_t next_free = fs_info->vol.next_cl;
0799
0800 if (free_count != fs_info->vol.free_cls_in_fs_info)
0801 {
0802 uint32_t le_free_count = CT_LE_L(free_count);
0803
0804 fs_info->vol.free_cls_in_fs_info = free_count;
0805
0806 ret1 = fat_sector_write(fs_info,
0807 fs_info->vol.info_sec,
0808 FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET,
0809 sizeof(le_free_count),
0810 &le_free_count);
0811 }
0812
0813 if (next_free != fs_info->vol.next_cl_in_fs_info)
0814 {
0815 uint32_t le_next_free = CT_LE_L(next_free);
0816
0817 fs_info->vol.next_cl_in_fs_info = next_free;
0818
0819 ret2 = fat_sector_write(fs_info,
0820 fs_info->vol.info_sec,
0821 FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET,
0822 sizeof(le_next_free),
0823 &le_next_free);
0824 }
0825 }
0826
0827 if ( (ret1 < 0) || (ret2 < 0) )
0828 return -1;
0829
0830 return RC_OK;
0831 }
0832
0833 int
0834 fat_sync(fat_fs_info_t *fs_info)
0835 {
0836 int rc = RC_OK;
0837
0838 rc = fat_fat32_update_fsinfo_sector(fs_info);
0839 if ( rc != RC_OK )
0840 rc = -1;
0841
0842 fat_buf_release(fs_info);
0843
0844 if (rtems_bdbuf_syncdev(fs_info->vol.dd) != RTEMS_SUCCESSFUL)
0845 rc = -1;
0846
0847 return rc;
0848 }
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860 int
0861 fat_shutdown_drive(fat_fs_info_t *fs_info)
0862 {
0863 int rc = RC_OK;
0864 int i = 0;
0865
0866 rc = fat_sync(fs_info);
0867 if ( rc != RC_OK )
0868 rc = -1;
0869
0870 for (i = 0; i < FAT_HASH_SIZE; i++)
0871 {
0872 rtems_chain_node *node = NULL;
0873 rtems_chain_control *the_chain = fs_info->vhash + i;
0874
0875 while ( (node = rtems_chain_get_unprotected(the_chain)) != NULL )
0876 free(node);
0877 }
0878
0879 for (i = 0; i < FAT_HASH_SIZE; i++)
0880 {
0881 rtems_chain_node *node = NULL;
0882 rtems_chain_control *the_chain = fs_info->rhash + i;
0883
0884 while ( (node = rtems_chain_get_unprotected(the_chain)) != NULL )
0885 free(node);
0886 }
0887
0888 free(fs_info->vhash);
0889 free(fs_info->rhash);
0890
0891 free(fs_info->uino);
0892 free(fs_info->sec_buf);
0893 close(fs_info->vol.fd);
0894
0895 if (rc)
0896 errno = EIO;
0897 return rc;
0898 }
0899
0900
0901
0902
0903
0904
0905
0906
0907
0908
0909
0910
0911 int
0912 fat_init_clusters_chain(
0913 fat_fs_info_t *fs_info,
0914 uint32_t start_cln
0915 )
0916 {
0917 int rc = RC_OK;
0918 ssize_t ret = 0;
0919 uint32_t cur_cln = start_cln;
0920
0921 while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
0922 {
0923 ret = fat_cluster_set(fs_info, cur_cln, 0, fs_info->vol.bpc, 0);
0924 if ( ret != fs_info->vol.bpc )
0925 {
0926 return -1;
0927 }
0928
0929 rc = fat_get_fat_cluster(fs_info, cur_cln, &cur_cln);
0930 if ( rc != RC_OK )
0931 {
0932 return rc;
0933 }
0934
0935 }
0936
0937 return rc;
0938 }
0939
0940 #define FAT_UNIQ_INO_BASE 0x0FFFFF00
0941
0942 #define FAT_UNIQ_INO_IS_BUSY(index, arr) \
0943 (((arr)[((index)>>3)]>>((index) & (8-1))) & 0x01)
0944
0945 #define FAT_SET_UNIQ_INO_BUSY(index, arr) \
0946 ((arr)[((index)>>3)] |= (0x01<<((index) & (8-1))))
0947
0948 #define FAT_SET_UNIQ_INO_FREE(index, arr) \
0949 ((arr)[((index)>>3)] &= (~(0x01<<((index) & (8-1)))))
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963
0964
0965 uint32_t
0966 fat_get_unique_ino(fat_fs_info_t *fs_info)
0967 {
0968 uint32_t j = 0;
0969 bool resrc_unsuff = false;
0970
0971 while (!resrc_unsuff)
0972 {
0973 for (j = 0; j < fs_info->uino_pool_size; j++)
0974 {
0975 if (!FAT_UNIQ_INO_IS_BUSY(fs_info->index, fs_info->uino))
0976 {
0977 FAT_SET_UNIQ_INO_BUSY(fs_info->index, fs_info->uino);
0978 return (fs_info->uino_base + fs_info->index);
0979 }
0980 fs_info->index++;
0981 if (fs_info->index >= fs_info->uino_pool_size)
0982 fs_info->index = 0;
0983 }
0984
0985 if ((fs_info->uino_pool_size << 1) < (0x0FFFFFFF - fs_info->uino_base))
0986 {
0987 fs_info->uino_pool_size <<= 1;
0988 fs_info->uino = realloc(fs_info->uino, fs_info->uino_pool_size);
0989 if (fs_info->uino != NULL)
0990 fs_info->index = fs_info->uino_pool_size;
0991 else
0992 resrc_unsuff = true;
0993 }
0994 else
0995 resrc_unsuff = true;
0996 }
0997 return 0;
0998 }
0999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010 void
1011 fat_free_unique_ino(
1012 fat_fs_info_t *fs_info,
1013 uint32_t ino
1014 )
1015 {
1016 FAT_SET_UNIQ_INO_FREE((ino - fs_info->uino_base), fs_info->uino);
1017 }
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029 inline bool
1030 fat_ino_is_unique(
1031 fat_fs_info_t *fs_info,
1032 uint32_t ino
1033 )
1034 {
1035
1036 return (ino >= fs_info->uino_base);
1037 }