//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // FAT16/32 File IO Library // V2.6 // Ultra-Embedded.com // Copyright 2003 - 2012 // // Email: admin@ultra-embedded.com // // License: GPL // If you would like a version with a more permissive license for use in // closed source commercial applications please contact me for details. //----------------------------------------------------------------------------- // // This file is part of FAT File IO Library. // // FAT File IO Library is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // FAT File IO Library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FAT File IO Library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- #include #include "fat_defs.h" #include "fat_access.h" #include "fat_table.h" #include "fat_write.h" #include "fat_string.h" #include "fat_misc.h" //----------------------------------------------------------------------------- // fatfs_init: Load FAT Parameters //----------------------------------------------------------------------------- int fatfs_init(struct fatfs *fs) { uint8 num_of_fats; uint16 reserved_sectors; uint32 FATSz; uint32 root_dir_sectors; uint32 total_sectors; uint32 data_sectors; uint32 count_of_clusters; uint8 valid_partition = 0; fs->currentsector.address = FAT32_INVALID_CLUSTER; fs->currentsector.dirty = 0; fs->next_free_cluster = 0; // Invalid fatfs_fat_init(fs); // Make sure we have a read function (write function is optional) if (!fs->disk_io.read_media) return FAT_INIT_MEDIA_ACCESS_ERROR; // MBR: Sector 0 on the disk // NOTE: Some removeable media does not have this. // Load MBR (LBA 0) into the 512 byte buffer if (!fs->disk_io.read_media(0, fs->currentsector.sector, 1)) return FAT_INIT_MEDIA_ACCESS_ERROR; // Make Sure 0x55 and 0xAA are at end of sector // (this should be the case regardless of the MBR or boot sector) if (fs->currentsector.sector[SIGNATURE_POSITION] != 0x55 || fs->currentsector.sector[SIGNATURE_POSITION+1] != 0xAA) return FAT_INIT_INVALID_SIGNATURE; // Now check again using the access function to prove endian conversion function if (GET_16BIT_WORD(fs->currentsector.sector, SIGNATURE_POSITION) != SIGNATURE_VALUE) return FAT_INIT_ENDIAN_ERROR; // Verify packed structures if (sizeof(struct fat_dir_entry) != FAT_DIR_ENTRY_SIZE) return FAT_INIT_STRUCT_PACKING; // Check the partition type code switch(fs->currentsector.sector[PARTITION1_TYPECODE_LOCATION]) { case 0x0B: case 0x06: case 0x0C: case 0x0E: case 0x0F: case 0x05: valid_partition = 1; break; case 0x00: valid_partition = 0; break; default: if (fs->currentsector.sector[PARTITION1_TYPECODE_LOCATION] <= 0x06) valid_partition = 1; break; } // Read LBA Begin for the file system if (valid_partition) fs->lba_begin = GET_32BIT_WORD(fs->currentsector.sector, PARTITION1_LBA_BEGIN_LOCATION); // Else possibly MBR less disk else fs->lba_begin = 0; // Load Volume 1 table into sector buffer // (We may already have this in the buffer if MBR less drive!) if (!fs->disk_io.read_media(fs->lba_begin, fs->currentsector.sector, 1)) return FAT_INIT_MEDIA_ACCESS_ERROR; // Make sure there are 512 bytes per cluster if (GET_16BIT_WORD(fs->currentsector.sector, 0x0B) != FAT_SECTOR_SIZE) return FAT_INIT_INVALID_SECTOR_SIZE; // Load Parameters of FAT partition fs->sectors_per_cluster = fs->currentsector.sector[BPB_SECPERCLUS]; reserved_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_RSVDSECCNT); num_of_fats = fs->currentsector.sector[BPB_NUMFATS]; fs->root_entry_count = GET_16BIT_WORD(fs->currentsector.sector, BPB_ROOTENTCNT); if(GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16) != 0) fs->fat_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16); else fs->fat_sectors = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_FATSZ32); // For FAT32 (which this may be) fs->rootdir_first_cluster = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_ROOTCLUS); fs->fs_info_sector = GET_16BIT_WORD(fs->currentsector.sector, BPB_FAT32_FSINFO); // For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector fs->rootdir_first_sector = reserved_sectors + (num_of_fats * fs->fat_sectors); fs->rootdir_sectors = ((fs->root_entry_count * 32) + (FAT_SECTOR_SIZE - 1)) / FAT_SECTOR_SIZE; // First FAT LBA address fs->fat_begin_lba = fs->lba_begin + reserved_sectors; // The address of the first data cluster on this volume fs->cluster_begin_lba = fs->fat_begin_lba + (num_of_fats * fs->fat_sectors); if (GET_16BIT_WORD(fs->currentsector.sector, 0x1FE) != 0xAA55) // This signature should be AA55 return FAT_INIT_INVALID_SIGNATURE; // Calculate the root dir sectors root_dir_sectors = ((GET_16BIT_WORD(fs->currentsector.sector, BPB_ROOTENTCNT) * 32) + (GET_16BIT_WORD(fs->currentsector.sector, BPB_BYTSPERSEC) - 1)) / GET_16BIT_WORD(fs->currentsector.sector, BPB_BYTSPERSEC); if(GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16) != 0) FATSz = GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16); else FATSz = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_FATSZ32); if(GET_16BIT_WORD(fs->currentsector.sector, BPB_TOTSEC16) != 0) total_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_TOTSEC16); else total_sectors = GET_32BIT_WORD(fs->currentsector.sector, BPB_TOTSEC32); data_sectors = total_sectors - (GET_16BIT_WORD(fs->currentsector.sector, BPB_RSVDSECCNT) + (fs->currentsector.sector[BPB_NUMFATS] * FATSz) + root_dir_sectors); // Find out which version of FAT this is... if (fs->sectors_per_cluster != 0) { count_of_clusters = data_sectors / fs->sectors_per_cluster; if(count_of_clusters < 4085) // Volume is FAT12 return FAT_INIT_WRONG_FILESYS_TYPE; else if(count_of_clusters < 65525) { // Clear this FAT32 specific param fs->rootdir_first_cluster = 0; // Volume is FAT16 fs->fat_type = FAT_TYPE_16; return FAT_INIT_OK; } else { // Volume is FAT32 fs->fat_type = FAT_TYPE_32; return FAT_INIT_OK; } } else return FAT_INIT_WRONG_FILESYS_TYPE; } //----------------------------------------------------------------------------- // fatfs_lba_of_cluster: This function converts a cluster number into a sector / // LBA number. //----------------------------------------------------------------------------- uint32 fatfs_lba_of_cluster(struct fatfs *fs, uint32 Cluster_Number) { if (fs->fat_type == FAT_TYPE_16) return (fs->cluster_begin_lba + (fs->root_entry_count * 32 / FAT_SECTOR_SIZE) + ((Cluster_Number-2) * fs->sectors_per_cluster)); else return ((fs->cluster_begin_lba + ((Cluster_Number-2)*fs->sectors_per_cluster))); } //----------------------------------------------------------------------------- // fatfs_sector_read: //----------------------------------------------------------------------------- int fatfs_sector_read(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count) { return fs->disk_io.read_media(lba, target, count); } //----------------------------------------------------------------------------- // fatfs_sector_write: //----------------------------------------------------------------------------- int fatfs_sector_write(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count) { return fs->disk_io.write_media(lba, target, count); } //----------------------------------------------------------------------------- // fatfs_sector_reader: From the provided startcluster and sector offset // Returns True if success, returns False if not (including if read out of range) //----------------------------------------------------------------------------- int fatfs_sector_reader(struct fatfs *fs, uint32 start_cluster, uint32 offset, uint8 *target) { uint32 sector_to_read = 0; uint32 cluster_to_read = 0; uint32 cluster_chain = 0; uint32 i; uint32 lba; // FAT16 Root directory if (fs->fat_type == FAT_TYPE_16 && start_cluster == 0) { if (offset < fs->rootdir_sectors) lba = fs->lba_begin + fs->rootdir_first_sector + offset; else return 0; } // FAT16/32 Other else { // Set start of cluster chain to initial value cluster_chain = start_cluster; // Find parameters cluster_to_read = offset / fs->sectors_per_cluster; sector_to_read = offset - (cluster_to_read*fs->sectors_per_cluster); // Follow chain to find cluster to read for (i=0; idisk_io.read_media(lba, target, 1); // Else read sector if not already loaded else if (lba != fs->currentsector.address) { fs->currentsector.address = lba; return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1); } else return 1; } //----------------------------------------------------------------------------- // fatfs_read_sector: Read from the provided cluster and sector offset // Returns True if success, returns False if not //----------------------------------------------------------------------------- int fatfs_read_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target) { // FAT16 Root directory if (fs->fat_type == FAT_TYPE_16 && cluster == 0) { uint32 lba; // In FAT16, there are a limited amount of sectors in root dir! if (sector < fs->rootdir_sectors) lba = fs->lba_begin + fs->rootdir_first_sector + sector; else return 0; // User target buffer passed in if (target) { // Read from disk return fs->disk_io.read_media(lba, target, 1); } else { // Calculate read address fs->currentsector.address = lba; // Read from disk return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1); } } // FAT16/32 Other else { // User target buffer passed in if (target) { // Calculate read address uint32 lba = fatfs_lba_of_cluster(fs, cluster) + sector; // Read from disk return fs->disk_io.read_media(lba, target, 1); } else { // Calculate write address fs->currentsector.address = fatfs_lba_of_cluster(fs, cluster)+sector; // Read from disk return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1); } } } //----------------------------------------------------------------------------- // fatfs_write_sector: Write to the provided cluster and sector offset // Returns True if success, returns False if not //----------------------------------------------------------------------------- #if FATFS_INC_WRITE_SUPPORT int fatfs_write_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target) { // No write access? if (!fs->disk_io.write_media) return 0; // FAT16 Root directory if (fs->fat_type == FAT_TYPE_16 && cluster == 0) { uint32 lba; // In FAT16 we cannot extend the root dir! if (sector < fs->rootdir_sectors) lba = fs->lba_begin + fs->rootdir_first_sector + sector; else return 0; // User target buffer passed in if (target) { // Write to disk return fs->disk_io.write_media(lba, target, 1); } else { // Calculate write address fs->currentsector.address = lba; // Write to disk return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1); } } // FAT16/32 Other else { // User target buffer passed in if (target) { // Calculate write address uint32 lba = fatfs_lba_of_cluster(fs, cluster) + sector; // Write to disk return fs->disk_io.write_media(lba, target, 1); } else { // Calculate write address fs->currentsector.address = fatfs_lba_of_cluster(fs, cluster)+sector; // Write to disk return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1); } } } #endif //----------------------------------------------------------------------------- // fatfs_show_details: Show the details about the filesystem //----------------------------------------------------------------------------- void fatfs_show_details(struct fatfs *fs) { FAT_PRINTF(("FAT details:\r\n")); FAT_PRINTF((" Type =%s", (fs->fat_type == FAT_TYPE_32) ? "FAT32": "FAT16")); FAT_PRINTF((" Root Dir First Cluster = %x\r\n", fs->rootdir_first_cluster)); FAT_PRINTF((" FAT Begin LBA = 0x%x\r\n",fs->fat_begin_lba)); FAT_PRINTF((" Cluster Begin LBA = 0x%x\r\n",fs->cluster_begin_lba)); FAT_PRINTF((" Sectors Per Cluster = %d\r\n", fs->sectors_per_cluster)); } //----------------------------------------------------------------------------- // fatfs_get_root_cluster: Get the root dir cluster //----------------------------------------------------------------------------- uint32 fatfs_get_root_cluster(struct fatfs *fs) { // NOTE: On FAT16 this will be 0 which has a special meaning... return fs->rootdir_first_cluster; } //------------------------------------------------------------- // fatfs_get_file_entry: Find the file entry for a filename //------------------------------------------------------------- uint32 fatfs_get_file_entry(struct fatfs *fs, uint32 Cluster, char *name_to_find, struct fat_dir_entry *sfEntry) { uint8 item=0; uint16 recordoffset = 0; uint8 i=0; int x=0; char *long_filename = NULL; char short_filename[13]; struct lfn_cache lfn; int dotRequired = 0; struct fat_dir_entry *directoryEntry; fatfs_lfn_cache_init(&lfn, 1); // Main cluster following loop while (1) { // Read sector if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull { // Analyse Sector for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++) { // Create the multiplier for sector access recordoffset = FAT_DIR_ENTRY_SIZE * item; // Overlay directory entry over buffer directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset); #if FATFS_INC_LFN_SUPPORT // Long File Name Text Found if (fatfs_entry_lfn_text(directoryEntry) ) fatfs_lfn_cache_entry(&lfn, fs->currentsector.sector+recordoffset); // If Invalid record found delete any long file name information collated else if (fatfs_entry_lfn_invalid(directoryEntry) ) fatfs_lfn_cache_init(&lfn, 0); // Normal SFN Entry and Long text exists else if (fatfs_entry_lfn_exists(&lfn, directoryEntry) ) { long_filename = fatfs_lfn_cache_get(&lfn); // Compare names to see if they match if (fatfs_compare_names(long_filename, name_to_find)) { memcpy(sfEntry,directoryEntry,sizeof(struct fat_dir_entry)); return 1; } fatfs_lfn_cache_init(&lfn, 0); } else #endif // Normal Entry, only 8.3 Text if (fatfs_entry_sfn_only(directoryEntry) ) { memset(short_filename, 0, sizeof(short_filename)); // Copy name to string for (i=0; i<8; i++) short_filename[i] = directoryEntry->Name[i]; // Extension dotRequired = 0; for (i=8; i<11; i++) { short_filename[i+1] = directoryEntry->Name[i]; if (directoryEntry->Name[i] != ' ') dotRequired = 1; } // Dot only required if extension present if (dotRequired) { // If not . or .. entry if (short_filename[0]!='.') short_filename[8] = '.'; else short_filename[8] = ' '; } else short_filename[8] = ' '; // Compare names to see if they match if (fatfs_compare_names(short_filename, name_to_find)) { memcpy(sfEntry,directoryEntry,sizeof(struct fat_dir_entry)); return 1; } fatfs_lfn_cache_init(&lfn, 0); } } // End of if } else break; } // End of while loop return 0; } //------------------------------------------------------------- // fatfs_sfn_exists: Check if a short filename exists. // NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY //------------------------------------------------------------- #if FATFS_INC_WRITE_SUPPORT int fatfs_sfn_exists(struct fatfs *fs, uint32 Cluster, char *shortname) { uint8 item=0; uint16 recordoffset = 0; int x=0; struct fat_dir_entry *directoryEntry; // Main cluster following loop while (1) { // Read sector if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull { // Analyse Sector for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++) { // Create the multiplier for sector access recordoffset = FAT_DIR_ENTRY_SIZE * item; // Overlay directory entry over buffer directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset); #if FATFS_INC_LFN_SUPPORT // Long File Name Text Found if (fatfs_entry_lfn_text(directoryEntry) ) ; // If Invalid record found delete any long file name information collated else if (fatfs_entry_lfn_invalid(directoryEntry) ) ; else #endif // Normal Entry, only 8.3 Text if (fatfs_entry_sfn_only(directoryEntry) ) { if (strncmp((const char*)directoryEntry->Name, shortname, 11)==0) return 1; } } // End of if } else break; } // End of while loop return 0; } #endif //------------------------------------------------------------- // fatfs_update_timestamps: Update date/time details //------------------------------------------------------------- #if FATFS_INC_TIME_DATE_SUPPORT int fatfs_update_timestamps(struct fat_dir_entry *directoryEntry, int create, int modify, int access) { time_t time_now; struct tm * time_info; uint16 fat_time; uint16 fat_date; // Get system time time(&time_now); // Convert to local time time_info = localtime(&time_now); // Convert time to FAT format fat_time = fatfs_convert_to_fat_time(time_info->tm_hour, time_info->tm_min, time_info->tm_sec); // Convert date to FAT format fat_date = fatfs_convert_to_fat_date(time_info->tm_mday, time_info->tm_mon + 1, time_info->tm_year + 1900); // Update requested fields if (create) { directoryEntry->CrtTime[1] = fat_time >> 8; directoryEntry->CrtTime[0] = fat_time >> 0; directoryEntry->CrtDate[1] = fat_date >> 8; directoryEntry->CrtDate[0] = fat_date >> 0; } if (modify) { directoryEntry->WrtTime[1] = fat_time >> 8; directoryEntry->WrtTime[0] = fat_time >> 0; directoryEntry->WrtDate[1] = fat_date >> 8; directoryEntry->WrtDate[0] = fat_date >> 0; } if (access) { directoryEntry->LstAccDate[1] = fat_time >> 8; directoryEntry->LstAccDate[0] = fat_time >> 0; directoryEntry->LstAccDate[1] = fat_date >> 8; directoryEntry->LstAccDate[0] = fat_date >> 0; } return 1; } #endif //------------------------------------------------------------- // fatfs_update_file_length: Find a SFN entry and update it // NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY //------------------------------------------------------------- #if FATFS_INC_WRITE_SUPPORT int fatfs_update_file_length(struct fatfs *fs, uint32 Cluster, char *shortname, uint32 fileLength) { uint8 item=0; uint16 recordoffset = 0; int x=0; struct fat_dir_entry *directoryEntry; // No write access? if (!fs->disk_io.write_media) return 0; // Main cluster following loop while (1) { // Read sector if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull { // Analyse Sector for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++) { // Create the multiplier for sector access recordoffset = FAT_DIR_ENTRY_SIZE * item; // Overlay directory entry over buffer directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset); #if FATFS_INC_LFN_SUPPORT // Long File Name Text Found if (fatfs_entry_lfn_text(directoryEntry) ) ; // If Invalid record found delete any long file name information collated else if (fatfs_entry_lfn_invalid(directoryEntry) ) ; // Normal Entry, only 8.3 Text else #endif if (fatfs_entry_sfn_only(directoryEntry) ) { if (strncmp((const char*)directoryEntry->Name, shortname, 11)==0) { directoryEntry->FileSize = FAT_HTONL(fileLength); #if FATFS_INC_TIME_DATE_SUPPORT // Update access / modify time & date fatfs_update_timestamps(directoryEntry, 0, 1, 1); #endif // Update sfn entry memcpy((uint8*)(fs->currentsector.sector+recordoffset), (uint8*)directoryEntry, sizeof(struct fat_dir_entry)); // Write sector back return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1); } } } // End of if } else break; } // End of while loop return 0; } #endif //------------------------------------------------------------- // fatfs_mark_file_deleted: Find a SFN entry and mark if as deleted // NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY //------------------------------------------------------------- #if FATFS_INC_WRITE_SUPPORT int fatfs_mark_file_deleted(struct fatfs *fs, uint32 Cluster, char *shortname) { uint8 item=0; uint16 recordoffset = 0; int x=0; struct fat_dir_entry *directoryEntry; // No write access? if (!fs->disk_io.write_media) return 0; // Main cluster following loop while (1) { // Read sector if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull { // Analyse Sector for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++) { // Create the multiplier for sector access recordoffset = FAT_DIR_ENTRY_SIZE * item; // Overlay directory entry over buffer directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset); #if FATFS_INC_LFN_SUPPORT // Long File Name Text Found if (fatfs_entry_lfn_text(directoryEntry) ) ; // If Invalid record found delete any long file name information collated else if (fatfs_entry_lfn_invalid(directoryEntry) ) ; // Normal Entry, only 8.3 Text else #endif if (fatfs_entry_sfn_only(directoryEntry) ) { if (strncmp((const char *)directoryEntry->Name, shortname, 11)==0) { // Mark as deleted directoryEntry->Name[0] = FILE_HEADER_DELETED; #if FATFS_INC_TIME_DATE_SUPPORT // Update access / modify time & date fatfs_update_timestamps(directoryEntry, 0, 1, 1); #endif // Update sfn entry memcpy((uint8*)(fs->currentsector.sector+recordoffset), (uint8*)directoryEntry, sizeof(struct fat_dir_entry)); // Write sector back return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1); } } } // End of if } else break; } // End of while loop return 0; } #endif //----------------------------------------------------------------------------- // fatfs_list_directory_start: Initialise a directory listing procedure //----------------------------------------------------------------------------- #if FATFS_DIR_LIST_SUPPORT void fatfs_list_directory_start(struct fatfs *fs, struct fs_dir_list_status *dirls, uint32 StartCluster) { dirls->cluster = StartCluster; dirls->sector = 0; dirls->offset = 0; } #endif //----------------------------------------------------------------------------- // fatfs_list_directory_next: Get the next entry in the directory. // Returns: 1 = found, 0 = end of listing //----------------------------------------------------------------------------- #if FATFS_DIR_LIST_SUPPORT int fatfs_list_directory_next(struct fatfs *fs, struct fs_dir_list_status *dirls, struct fs_dir_ent *entry) { uint8 i,item; uint16 recordoffset; struct fat_dir_entry *directoryEntry; char *long_filename = NULL; char short_filename[13]; struct lfn_cache lfn; int dotRequired = 0; int result = 0; // Initialise LFN cache first fatfs_lfn_cache_init(&lfn, 0); while (1) { // If data read OK if (fatfs_sector_reader(fs, dirls->cluster, dirls->sector, 0)) { // Maximum of 16 directory entries for (item = dirls->offset; item < FAT_DIR_ENTRIES_PER_SECTOR; item++) { // Increase directory offset recordoffset = FAT_DIR_ENTRY_SIZE * item; // Overlay directory entry over buffer directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset); #if FATFS_INC_LFN_SUPPORT // Long File Name Text Found if ( fatfs_entry_lfn_text(directoryEntry) ) fatfs_lfn_cache_entry(&lfn, fs->currentsector.sector+recordoffset); // If Invalid record found delete any long file name information collated else if ( fatfs_entry_lfn_invalid(directoryEntry) ) fatfs_lfn_cache_init(&lfn, 0); // Normal SFN Entry and Long text exists else if (fatfs_entry_lfn_exists(&lfn, directoryEntry) ) { // Get text long_filename = fatfs_lfn_cache_get(&lfn); strncpy(entry->filename, long_filename, FATFS_MAX_LONG_FILENAME-1); if (fatfs_entry_is_dir(directoryEntry)) entry->is_dir = 1; else entry->is_dir = 0; #if FATFS_INC_TIME_DATE_SUPPORT // Get time / dates entry->create_time = ((uint16)directoryEntry->CrtTime[1] << 8) | directoryEntry->CrtTime[0]; entry->create_date = ((uint16)directoryEntry->CrtDate[1] << 8) | directoryEntry->CrtDate[0]; entry->access_date = ((uint16)directoryEntry->LstAccDate[1] << 8) | directoryEntry->LstAccDate[0]; entry->write_time = ((uint16)directoryEntry->WrtTime[1] << 8) | directoryEntry->WrtTime[0]; entry->write_date = ((uint16)directoryEntry->WrtDate[1] << 8) | directoryEntry->WrtDate[0]; #endif entry->size = FAT_HTONL(directoryEntry->FileSize); entry->cluster = (FAT_HTONS(directoryEntry->FstClusHI)<<16) | FAT_HTONS(directoryEntry->FstClusLO); // Next starting position dirls->offset = item + 1; result = 1; return 1; } // Normal Entry, only 8.3 Text else #endif if ( fatfs_entry_sfn_only(directoryEntry) ) { fatfs_lfn_cache_init(&lfn, 0); memset(short_filename, 0, sizeof(short_filename)); // Copy name to string for (i=0; i<8; i++) short_filename[i] = directoryEntry->Name[i]; // Extension dotRequired = 0; for (i=8; i<11; i++) { short_filename[i+1] = directoryEntry->Name[i]; if (directoryEntry->Name[i] != ' ') dotRequired = 1; } // Dot only required if extension present if (dotRequired) { // If not . or .. entry if (short_filename[0]!='.') short_filename[8] = '.'; else short_filename[8] = ' '; } else short_filename[8] = ' '; fatfs_get_sfn_display_name(entry->filename, short_filename); if (fatfs_entry_is_dir(directoryEntry)) entry->is_dir = 1; else entry->is_dir = 0; #if FATFS_INC_TIME_DATE_SUPPORT // Get time / dates entry->create_time = ((uint16)directoryEntry->CrtTime[1] << 8) | directoryEntry->CrtTime[0]; entry->create_date = ((uint16)directoryEntry->CrtDate[1] << 8) | directoryEntry->CrtDate[0]; entry->access_date = ((uint16)directoryEntry->LstAccDate[1] << 8) | directoryEntry->LstAccDate[0]; entry->write_time = ((uint16)directoryEntry->WrtTime[1] << 8) | directoryEntry->WrtTime[0]; entry->write_date = ((uint16)directoryEntry->WrtDate[1] << 8) | directoryEntry->WrtDate[0]; #endif entry->size = FAT_HTONL(directoryEntry->FileSize); entry->cluster = (FAT_HTONS(directoryEntry->FstClusHI)<<16) | FAT_HTONS(directoryEntry->FstClusLO); // Next starting position dirls->offset = item + 1; result = 1; return 1; } }// end of for // If reached end of the dir move onto next sector dirls->sector++; dirls->offset = 0; } else break; } return result; } #endif