1 //-----------------------------------------------------------------------------
2 //-----------------------------------------------------------------------------
3 // FAT16/32 File IO Library
6 // Copyright 2003 - 2012
8 // Email: admin@ultra-embedded.com
11 // If you would like a version with a more permissive license for use in
12 // closed source commercial applications please contact me for details.
13 //-----------------------------------------------------------------------------
15 // This file is part of FAT File IO Library.
17 // FAT File IO Library is free software; you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation; either version 2 of the License, or
20 // (at your option) any later version.
22 // FAT File IO Library is distributed in the hope that it will be useful,
23 // but WITHOUT ANY WARRANTY; without even the implied warranty of
24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 // GNU General Public License for more details.
27 // You should have received a copy of the GNU General Public License
28 // along with FAT File IO Library; if not, write to the Free Software
29 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 //-----------------------------------------------------------------------------
31 //-----------------------------------------------------------------------------
34 #include "fat_access.h"
35 #include "fat_table.h"
36 #include "fat_write.h"
37 #include "fat_string.h"
40 //-----------------------------------------------------------------------------
41 // fatfs_init: Load FAT Parameters
42 //-----------------------------------------------------------------------------
43 int fatfs_init(struct fatfs
*fs
)
46 uint16 reserved_sectors
;
48 uint32 root_dir_sectors
;
51 uint32 count_of_clusters
;
52 uint8 valid_partition
= 0;
54 fs
->currentsector
.address
= FAT32_INVALID_CLUSTER
;
55 fs
->currentsector
.dirty
= 0;
57 fs
->next_free_cluster
= 0; // Invalid
61 // Make sure we have a read function (write function is optional)
62 if (!fs
->disk_io
.read_media
)
63 return FAT_INIT_MEDIA_ACCESS_ERROR
;
65 // MBR: Sector 0 on the disk
66 // NOTE: Some removeable media does not have this.
68 // Load MBR (LBA 0) into the 512 byte buffer
69 if (!fs
->disk_io
.read_media(0, fs
->currentsector
.sector
, 1))
70 return FAT_INIT_MEDIA_ACCESS_ERROR
;
72 // Make Sure 0x55 and 0xAA are at end of sector
73 // (this should be the case regardless of the MBR or boot sector)
74 if (fs
->currentsector
.sector
[SIGNATURE_POSITION
] != 0x55 || fs
->currentsector
.sector
[SIGNATURE_POSITION
+1] != 0xAA)
75 return FAT_INIT_INVALID_SIGNATURE
;
77 // Now check again using the access function to prove endian conversion function
78 if (GET_16BIT_WORD(fs
->currentsector
.sector
, SIGNATURE_POSITION
) != SIGNATURE_VALUE
)
79 return FAT_INIT_ENDIAN_ERROR
;
81 // Verify packed structures
82 if (sizeof(struct fat_dir_entry
) != FAT_DIR_ENTRY_SIZE
)
83 return FAT_INIT_STRUCT_PACKING
;
85 // Check the partition type code
86 switch(fs
->currentsector
.sector
[PARTITION1_TYPECODE_LOCATION
])
100 if (fs
->currentsector
.sector
[PARTITION1_TYPECODE_LOCATION
] <= 0x06)
105 // Read LBA Begin for the file system
107 fs
->lba_begin
= GET_32BIT_WORD(fs
->currentsector
.sector
, PARTITION1_LBA_BEGIN_LOCATION
);
108 // Else possibly MBR less disk
112 // Load Volume 1 table into sector buffer
113 // (We may already have this in the buffer if MBR less drive!)
114 if (!fs
->disk_io
.read_media(fs
->lba_begin
, fs
->currentsector
.sector
, 1))
115 return FAT_INIT_MEDIA_ACCESS_ERROR
;
117 // Make sure there are 512 bytes per cluster
118 if (GET_16BIT_WORD(fs
->currentsector
.sector
, 0x0B) != FAT_SECTOR_SIZE
)
119 return FAT_INIT_INVALID_SECTOR_SIZE
;
121 // Load Parameters of FAT partition
122 fs
->sectors_per_cluster
= fs
->currentsector
.sector
[BPB_SECPERCLUS
];
123 reserved_sectors
= GET_16BIT_WORD(fs
->currentsector
.sector
, BPB_RSVDSECCNT
);
124 num_of_fats
= fs
->currentsector
.sector
[BPB_NUMFATS
];
125 fs
->root_entry_count
= GET_16BIT_WORD(fs
->currentsector
.sector
, BPB_ROOTENTCNT
);
127 if(GET_16BIT_WORD(fs
->currentsector
.sector
, BPB_FATSZ16
) != 0)
128 fs
->fat_sectors
= GET_16BIT_WORD(fs
->currentsector
.sector
, BPB_FATSZ16
);
130 fs
->fat_sectors
= GET_32BIT_WORD(fs
->currentsector
.sector
, BPB_FAT32_FATSZ32
);
132 // For FAT32 (which this may be)
133 fs
->rootdir_first_cluster
= GET_32BIT_WORD(fs
->currentsector
.sector
, BPB_FAT32_ROOTCLUS
);
134 fs
->fs_info_sector
= GET_16BIT_WORD(fs
->currentsector
.sector
, BPB_FAT32_FSINFO
);
136 // For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector
137 fs
->rootdir_first_sector
= reserved_sectors
+ (num_of_fats
* fs
->fat_sectors
);
138 fs
->rootdir_sectors
= ((fs
->root_entry_count
* 32) + (FAT_SECTOR_SIZE
- 1)) / FAT_SECTOR_SIZE
;
140 // First FAT LBA address
141 fs
->fat_begin_lba
= fs
->lba_begin
+ reserved_sectors
;
143 // The address of the first data cluster on this volume
144 fs
->cluster_begin_lba
= fs
->fat_begin_lba
+ (num_of_fats
* fs
->fat_sectors
);
146 if (GET_16BIT_WORD(fs
->currentsector
.sector
, 0x1FE) != 0xAA55) // This signature should be AA55
147 return FAT_INIT_INVALID_SIGNATURE
;
149 // Calculate the root dir sectors
150 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
);
152 if(GET_16BIT_WORD(fs
->currentsector
.sector
, BPB_FATSZ16
) != 0)
153 FATSz
= GET_16BIT_WORD(fs
->currentsector
.sector
, BPB_FATSZ16
);
155 FATSz
= GET_32BIT_WORD(fs
->currentsector
.sector
, BPB_FAT32_FATSZ32
);
157 if(GET_16BIT_WORD(fs
->currentsector
.sector
, BPB_TOTSEC16
) != 0)
158 total_sectors
= GET_16BIT_WORD(fs
->currentsector
.sector
, BPB_TOTSEC16
);
160 total_sectors
= GET_32BIT_WORD(fs
->currentsector
.sector
, BPB_TOTSEC32
);
162 data_sectors
= total_sectors
- (GET_16BIT_WORD(fs
->currentsector
.sector
, BPB_RSVDSECCNT
) + (fs
->currentsector
.sector
[BPB_NUMFATS
] * FATSz
) + root_dir_sectors
);
164 // Find out which version of FAT this is...
165 if (fs
->sectors_per_cluster
!= 0)
167 count_of_clusters
= data_sectors
/ fs
->sectors_per_cluster
;
169 if(count_of_clusters
< 4085)
171 return FAT_INIT_WRONG_FILESYS_TYPE
;
172 else if(count_of_clusters
< 65525)
174 // Clear this FAT32 specific param
175 fs
->rootdir_first_cluster
= 0;
178 fs
->fat_type
= FAT_TYPE_16
;
184 fs
->fat_type
= FAT_TYPE_32
;
189 return FAT_INIT_WRONG_FILESYS_TYPE
;
191 //-----------------------------------------------------------------------------
192 // fatfs_lba_of_cluster: This function converts a cluster number into a sector /
194 //-----------------------------------------------------------------------------
195 uint32
fatfs_lba_of_cluster(struct fatfs
*fs
, uint32 Cluster_Number
)
197 if (fs
->fat_type
== FAT_TYPE_16
)
198 return (fs
->cluster_begin_lba
+ (fs
->root_entry_count
* 32 / FAT_SECTOR_SIZE
) + ((Cluster_Number
-2) * fs
->sectors_per_cluster
));
200 return ((fs
->cluster_begin_lba
+ ((Cluster_Number
-2)*fs
->sectors_per_cluster
)));
202 //-----------------------------------------------------------------------------
203 // fatfs_sector_read:
204 //-----------------------------------------------------------------------------
205 int fatfs_sector_read(struct fatfs
*fs
, uint32 lba
, uint8
*target
, uint32 count
)
207 return fs
->disk_io
.read_media(lba
, target
, count
);
209 //-----------------------------------------------------------------------------
210 // fatfs_sector_write:
211 //-----------------------------------------------------------------------------
212 int fatfs_sector_write(struct fatfs
*fs
, uint32 lba
, uint8
*target
, uint32 count
)
214 return fs
->disk_io
.write_media(lba
, target
, count
);
216 //-----------------------------------------------------------------------------
217 // fatfs_sector_reader: From the provided startcluster and sector offset
218 // Returns True if success, returns False if not (including if read out of range)
219 //-----------------------------------------------------------------------------
220 int fatfs_sector_reader(struct fatfs
*fs
, uint32 start_cluster
, uint32 offset
, uint8
*target
)
222 uint32 sector_to_read
= 0;
223 uint32 cluster_to_read
= 0;
224 uint32 cluster_chain
= 0;
228 // FAT16 Root directory
229 if (fs
->fat_type
== FAT_TYPE_16
&& start_cluster
== 0)
231 if (offset
< fs
->rootdir_sectors
)
232 lba
= fs
->lba_begin
+ fs
->rootdir_first_sector
+ offset
;
239 // Set start of cluster chain to initial value
240 cluster_chain
= start_cluster
;
243 cluster_to_read
= offset
/ fs
->sectors_per_cluster
;
244 sector_to_read
= offset
- (cluster_to_read
*fs
->sectors_per_cluster
);
246 // Follow chain to find cluster to read
247 for (i
=0; i
<cluster_to_read
; i
++)
248 cluster_chain
= fatfs_find_next_cluster(fs
, cluster_chain
);
250 // If end of cluster chain then return false
251 if (cluster_chain
== FAT32_LAST_CLUSTER
)
254 // Calculate sector address
255 lba
= fatfs_lba_of_cluster(fs
, cluster_chain
)+sector_to_read
;
258 // User provided target array
260 return fs
->disk_io
.read_media(lba
, target
, 1);
261 // Else read sector if not already loaded
262 else if (lba
!= fs
->currentsector
.address
)
264 fs
->currentsector
.address
= lba
;
265 return fs
->disk_io
.read_media(fs
->currentsector
.address
, fs
->currentsector
.sector
, 1);
270 //-----------------------------------------------------------------------------
271 // fatfs_read_sector: Read from the provided cluster and sector offset
272 // Returns True if success, returns False if not
273 //-----------------------------------------------------------------------------
274 int fatfs_read_sector(struct fatfs
*fs
, uint32 cluster
, uint32 sector
, uint8
*target
)
276 // FAT16 Root directory
277 if (fs
->fat_type
== FAT_TYPE_16
&& cluster
== 0)
281 // In FAT16, there are a limited amount of sectors in root dir!
282 if (sector
< fs
->rootdir_sectors
)
283 lba
= fs
->lba_begin
+ fs
->rootdir_first_sector
+ sector
;
287 // User target buffer passed in
291 return fs
->disk_io
.read_media(lba
, target
, 1);
295 // Calculate read address
296 fs
->currentsector
.address
= lba
;
299 return fs
->disk_io
.read_media(fs
->currentsector
.address
, fs
->currentsector
.sector
, 1);
305 // User target buffer passed in
308 // Calculate read address
309 uint32 lba
= fatfs_lba_of_cluster(fs
, cluster
) + sector
;
312 return fs
->disk_io
.read_media(lba
, target
, 1);
316 // Calculate write address
317 fs
->currentsector
.address
= fatfs_lba_of_cluster(fs
, cluster
)+sector
;
320 return fs
->disk_io
.read_media(fs
->currentsector
.address
, fs
->currentsector
.sector
, 1);
324 //-----------------------------------------------------------------------------
325 // fatfs_write_sector: Write to the provided cluster and sector offset
326 // Returns True if success, returns False if not
327 //-----------------------------------------------------------------------------
328 #if FATFS_INC_WRITE_SUPPORT
329 int fatfs_write_sector(struct fatfs
*fs
, uint32 cluster
, uint32 sector
, uint8
*target
)
332 if (!fs
->disk_io
.write_media
)
335 // FAT16 Root directory
336 if (fs
->fat_type
== FAT_TYPE_16
&& cluster
== 0)
340 // In FAT16 we cannot extend the root dir!
341 if (sector
< fs
->rootdir_sectors
)
342 lba
= fs
->lba_begin
+ fs
->rootdir_first_sector
+ sector
;
346 // User target buffer passed in
350 return fs
->disk_io
.write_media(lba
, target
, 1);
354 // Calculate write address
355 fs
->currentsector
.address
= lba
;
358 return fs
->disk_io
.write_media(fs
->currentsector
.address
, fs
->currentsector
.sector
, 1);
364 // User target buffer passed in
367 // Calculate write address
368 uint32 lba
= fatfs_lba_of_cluster(fs
, cluster
) + sector
;
371 return fs
->disk_io
.write_media(lba
, target
, 1);
375 // Calculate write address
376 fs
->currentsector
.address
= fatfs_lba_of_cluster(fs
, cluster
)+sector
;
379 return fs
->disk_io
.write_media(fs
->currentsector
.address
, fs
->currentsector
.sector
, 1);
384 //-----------------------------------------------------------------------------
385 // fatfs_show_details: Show the details about the filesystem
386 //-----------------------------------------------------------------------------
387 void fatfs_show_details(struct fatfs
*fs
)
389 FAT_PRINTF(("FAT details:\r\n"));
390 FAT_PRINTF((" Type =%s", (fs
->fat_type
== FAT_TYPE_32
) ? "FAT32": "FAT16"));
391 FAT_PRINTF((" Root Dir First Cluster = %x\r\n", fs
->rootdir_first_cluster
));
392 FAT_PRINTF((" FAT Begin LBA = 0x%x\r\n",fs
->fat_begin_lba
));
393 FAT_PRINTF((" Cluster Begin LBA = 0x%x\r\n",fs
->cluster_begin_lba
));
394 FAT_PRINTF((" Sectors Per Cluster = %d\r\n", fs
->sectors_per_cluster
));
396 //-----------------------------------------------------------------------------
397 // fatfs_get_root_cluster: Get the root dir cluster
398 //-----------------------------------------------------------------------------
399 uint32
fatfs_get_root_cluster(struct fatfs
*fs
)
401 // NOTE: On FAT16 this will be 0 which has a special meaning...
402 return fs
->rootdir_first_cluster
;
404 //-------------------------------------------------------------
405 // fatfs_get_file_entry: Find the file entry for a filename
406 //-------------------------------------------------------------
407 uint32
fatfs_get_file_entry(struct fatfs
*fs
, uint32 Cluster
, char *name_to_find
, struct fat_dir_entry
*sfEntry
)
410 uint16 recordoffset
= 0;
413 char *long_filename
= NULL
;
414 char short_filename
[13];
415 struct lfn_cache lfn
;
417 struct fat_dir_entry
*directoryEntry
;
419 fatfs_lfn_cache_init(&lfn
, 1);
421 // Main cluster following loop
425 if (fatfs_sector_reader(fs
, Cluster
, x
++, 0)) // If sector read was successfull
428 for (item
= 0; item
< FAT_DIR_ENTRIES_PER_SECTOR
; item
++)
430 // Create the multiplier for sector access
431 recordoffset
= FAT_DIR_ENTRY_SIZE
* item
;
433 // Overlay directory entry over buffer
434 directoryEntry
= (struct fat_dir_entry
*)(fs
->currentsector
.sector
+recordoffset
);
436 #if FATFS_INC_LFN_SUPPORT
437 // Long File Name Text Found
438 if (fatfs_entry_lfn_text(directoryEntry
) )
439 fatfs_lfn_cache_entry(&lfn
, fs
->currentsector
.sector
+recordoffset
);
441 // If Invalid record found delete any long file name information collated
442 else if (fatfs_entry_lfn_invalid(directoryEntry
) )
443 fatfs_lfn_cache_init(&lfn
, 0);
445 // Normal SFN Entry and Long text exists
446 else if (fatfs_entry_lfn_exists(&lfn
, directoryEntry
) )
448 long_filename
= fatfs_lfn_cache_get(&lfn
);
450 // Compare names to see if they match
451 if (fatfs_compare_names(long_filename
, name_to_find
))
453 memcpy(sfEntry
,directoryEntry
,sizeof(struct fat_dir_entry
));
457 fatfs_lfn_cache_init(&lfn
, 0);
461 // Normal Entry, only 8.3 Text
462 if (fatfs_entry_sfn_only(directoryEntry
) )
464 memset(short_filename
, 0, sizeof(short_filename
));
466 // Copy name to string
468 short_filename
[i
] = directoryEntry
->Name
[i
];
474 short_filename
[i
+1] = directoryEntry
->Name
[i
];
475 if (directoryEntry
->Name
[i
] != ' ')
479 // Dot only required if extension present
482 // If not . or .. entry
483 if (short_filename
[0]!='.')
484 short_filename
[8] = '.';
486 short_filename
[8] = ' ';
489 short_filename
[8] = ' ';
491 // Compare names to see if they match
492 if (fatfs_compare_names(short_filename
, name_to_find
))
494 memcpy(sfEntry
,directoryEntry
,sizeof(struct fat_dir_entry
));
498 fatfs_lfn_cache_init(&lfn
, 0);
504 } // End of while loop
508 //-------------------------------------------------------------
509 // fatfs_sfn_exists: Check if a short filename exists.
510 // NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
511 //-------------------------------------------------------------
512 #if FATFS_INC_WRITE_SUPPORT
513 int fatfs_sfn_exists(struct fatfs
*fs
, uint32 Cluster
, char *shortname
)
516 uint16 recordoffset
= 0;
518 struct fat_dir_entry
*directoryEntry
;
520 // Main cluster following loop
524 if (fatfs_sector_reader(fs
, Cluster
, x
++, 0)) // If sector read was successfull
527 for (item
= 0; item
< FAT_DIR_ENTRIES_PER_SECTOR
; item
++)
529 // Create the multiplier for sector access
530 recordoffset
= FAT_DIR_ENTRY_SIZE
* item
;
532 // Overlay directory entry over buffer
533 directoryEntry
= (struct fat_dir_entry
*)(fs
->currentsector
.sector
+recordoffset
);
535 #if FATFS_INC_LFN_SUPPORT
536 // Long File Name Text Found
537 if (fatfs_entry_lfn_text(directoryEntry
) )
540 // If Invalid record found delete any long file name information collated
541 else if (fatfs_entry_lfn_invalid(directoryEntry
) )
545 // Normal Entry, only 8.3 Text
546 if (fatfs_entry_sfn_only(directoryEntry
) )
548 if (strncmp((const char*)directoryEntry
->Name
, shortname
, 11)==0)
555 } // End of while loop
560 //-------------------------------------------------------------
561 // fatfs_update_timestamps: Update date/time details
562 //-------------------------------------------------------------
563 #if FATFS_INC_TIME_DATE_SUPPORT
564 int fatfs_update_timestamps(struct fat_dir_entry
*directoryEntry
, int create
, int modify
, int access
)
567 struct tm
* time_info
;
574 // Convert to local time
575 time_info
= localtime(&time_now
);
577 // Convert time to FAT format
578 fat_time
= fatfs_convert_to_fat_time(time_info
->tm_hour
, time_info
->tm_min
, time_info
->tm_sec
);
580 // Convert date to FAT format
581 fat_date
= fatfs_convert_to_fat_date(time_info
->tm_mday
, time_info
->tm_mon
+ 1, time_info
->tm_year
+ 1900);
583 // Update requested fields
586 directoryEntry
->CrtTime
[1] = fat_time
>> 8;
587 directoryEntry
->CrtTime
[0] = fat_time
>> 0;
588 directoryEntry
->CrtDate
[1] = fat_date
>> 8;
589 directoryEntry
->CrtDate
[0] = fat_date
>> 0;
594 directoryEntry
->WrtTime
[1] = fat_time
>> 8;
595 directoryEntry
->WrtTime
[0] = fat_time
>> 0;
596 directoryEntry
->WrtDate
[1] = fat_date
>> 8;
597 directoryEntry
->WrtDate
[0] = fat_date
>> 0;
602 directoryEntry
->LstAccDate
[1] = fat_time
>> 8;
603 directoryEntry
->LstAccDate
[0] = fat_time
>> 0;
604 directoryEntry
->LstAccDate
[1] = fat_date
>> 8;
605 directoryEntry
->LstAccDate
[0] = fat_date
>> 0;
611 //-------------------------------------------------------------
612 // fatfs_update_file_length: Find a SFN entry and update it
613 // NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
614 //-------------------------------------------------------------
615 #if FATFS_INC_WRITE_SUPPORT
616 int fatfs_update_file_length(struct fatfs
*fs
, uint32 Cluster
, char *shortname
, uint32 fileLength
)
619 uint16 recordoffset
= 0;
621 struct fat_dir_entry
*directoryEntry
;
624 if (!fs
->disk_io
.write_media
)
627 // Main cluster following loop
631 if (fatfs_sector_reader(fs
, Cluster
, x
++, 0)) // If sector read was successfull
634 for (item
= 0; item
< FAT_DIR_ENTRIES_PER_SECTOR
; item
++)
636 // Create the multiplier for sector access
637 recordoffset
= FAT_DIR_ENTRY_SIZE
* item
;
639 // Overlay directory entry over buffer
640 directoryEntry
= (struct fat_dir_entry
*)(fs
->currentsector
.sector
+recordoffset
);
642 #if FATFS_INC_LFN_SUPPORT
643 // Long File Name Text Found
644 if (fatfs_entry_lfn_text(directoryEntry
) )
647 // If Invalid record found delete any long file name information collated
648 else if (fatfs_entry_lfn_invalid(directoryEntry
) )
651 // Normal Entry, only 8.3 Text
654 if (fatfs_entry_sfn_only(directoryEntry
) )
656 if (strncmp((const char*)directoryEntry
->Name
, shortname
, 11)==0)
658 directoryEntry
->FileSize
= FAT_HTONL(fileLength
);
660 #if FATFS_INC_TIME_DATE_SUPPORT
661 // Update access / modify time & date
662 fatfs_update_timestamps(directoryEntry
, 0, 1, 1);
666 memcpy((uint8
*)(fs
->currentsector
.sector
+recordoffset
), (uint8
*)directoryEntry
, sizeof(struct fat_dir_entry
));
669 return fs
->disk_io
.write_media(fs
->currentsector
.address
, fs
->currentsector
.sector
, 1);
676 } // End of while loop
681 //-------------------------------------------------------------
682 // fatfs_mark_file_deleted: Find a SFN entry and mark if as deleted
683 // NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
684 //-------------------------------------------------------------
685 #if FATFS_INC_WRITE_SUPPORT
686 int fatfs_mark_file_deleted(struct fatfs
*fs
, uint32 Cluster
, char *shortname
)
689 uint16 recordoffset
= 0;
691 struct fat_dir_entry
*directoryEntry
;
694 if (!fs
->disk_io
.write_media
)
697 // Main cluster following loop
701 if (fatfs_sector_reader(fs
, Cluster
, x
++, 0)) // If sector read was successfull
704 for (item
= 0; item
< FAT_DIR_ENTRIES_PER_SECTOR
; item
++)
706 // Create the multiplier for sector access
707 recordoffset
= FAT_DIR_ENTRY_SIZE
* item
;
709 // Overlay directory entry over buffer
710 directoryEntry
= (struct fat_dir_entry
*)(fs
->currentsector
.sector
+recordoffset
);
712 #if FATFS_INC_LFN_SUPPORT
713 // Long File Name Text Found
714 if (fatfs_entry_lfn_text(directoryEntry
) )
717 // If Invalid record found delete any long file name information collated
718 else if (fatfs_entry_lfn_invalid(directoryEntry
) )
721 // Normal Entry, only 8.3 Text
724 if (fatfs_entry_sfn_only(directoryEntry
) )
726 if (strncmp((const char *)directoryEntry
->Name
, shortname
, 11)==0)
729 directoryEntry
->Name
[0] = FILE_HEADER_DELETED
;
731 #if FATFS_INC_TIME_DATE_SUPPORT
732 // Update access / modify time & date
733 fatfs_update_timestamps(directoryEntry
, 0, 1, 1);
737 memcpy((uint8
*)(fs
->currentsector
.sector
+recordoffset
), (uint8
*)directoryEntry
, sizeof(struct fat_dir_entry
));
740 return fs
->disk_io
.write_media(fs
->currentsector
.address
, fs
->currentsector
.sector
, 1);
747 } // End of while loop
752 //-----------------------------------------------------------------------------
753 // fatfs_list_directory_start: Initialise a directory listing procedure
754 //-----------------------------------------------------------------------------
755 #if FATFS_DIR_LIST_SUPPORT
756 void fatfs_list_directory_start(struct fatfs
*fs
, struct fs_dir_list_status
*dirls
, uint32 StartCluster
)
758 dirls
->cluster
= StartCluster
;
763 //-----------------------------------------------------------------------------
764 // fatfs_list_directory_next: Get the next entry in the directory.
765 // Returns: 1 = found, 0 = end of listing
766 //-----------------------------------------------------------------------------
767 #if FATFS_DIR_LIST_SUPPORT
768 int fatfs_list_directory_next(struct fatfs
*fs
, struct fs_dir_list_status
*dirls
, struct fs_dir_ent
*entry
)
772 struct fat_dir_entry
*directoryEntry
;
773 char *long_filename
= NULL
;
774 char short_filename
[13];
775 struct lfn_cache lfn
;
779 // Initialise LFN cache first
780 fatfs_lfn_cache_init(&lfn
, 0);
785 if (fatfs_sector_reader(fs
, dirls
->cluster
, dirls
->sector
, 0))
787 // Maximum of 16 directory entries
788 for (item
= dirls
->offset
; item
< FAT_DIR_ENTRIES_PER_SECTOR
; item
++)
790 // Increase directory offset
791 recordoffset
= FAT_DIR_ENTRY_SIZE
* item
;
793 // Overlay directory entry over buffer
794 directoryEntry
= (struct fat_dir_entry
*)(fs
->currentsector
.sector
+recordoffset
);
796 #if FATFS_INC_LFN_SUPPORT
797 // Long File Name Text Found
798 if ( fatfs_entry_lfn_text(directoryEntry
) )
799 fatfs_lfn_cache_entry(&lfn
, fs
->currentsector
.sector
+recordoffset
);
801 // If Invalid record found delete any long file name information collated
802 else if ( fatfs_entry_lfn_invalid(directoryEntry
) )
803 fatfs_lfn_cache_init(&lfn
, 0);
805 // Normal SFN Entry and Long text exists
806 else if (fatfs_entry_lfn_exists(&lfn
, directoryEntry
) )
809 long_filename
= fatfs_lfn_cache_get(&lfn
);
810 strncpy(entry
->filename
, long_filename
, FATFS_MAX_LONG_FILENAME
-1);
812 if (fatfs_entry_is_dir(directoryEntry
))
817 #if FATFS_INC_TIME_DATE_SUPPORT
819 entry
->create_time
= ((uint16
)directoryEntry
->CrtTime
[1] << 8) | directoryEntry
->CrtTime
[0];
820 entry
->create_date
= ((uint16
)directoryEntry
->CrtDate
[1] << 8) | directoryEntry
->CrtDate
[0];
821 entry
->access_date
= ((uint16
)directoryEntry
->LstAccDate
[1] << 8) | directoryEntry
->LstAccDate
[0];
822 entry
->write_time
= ((uint16
)directoryEntry
->WrtTime
[1] << 8) | directoryEntry
->WrtTime
[0];
823 entry
->write_date
= ((uint16
)directoryEntry
->WrtDate
[1] << 8) | directoryEntry
->WrtDate
[0];
826 entry
->size
= FAT_HTONL(directoryEntry
->FileSize
);
827 entry
->cluster
= (FAT_HTONS(directoryEntry
->FstClusHI
)<<16) | FAT_HTONS(directoryEntry
->FstClusLO
);
829 // Next starting position
830 dirls
->offset
= item
+ 1;
834 // Normal Entry, only 8.3 Text
837 if ( fatfs_entry_sfn_only(directoryEntry
) )
839 fatfs_lfn_cache_init(&lfn
, 0);
841 memset(short_filename
, 0, sizeof(short_filename
));
843 // Copy name to string
845 short_filename
[i
] = directoryEntry
->Name
[i
];
851 short_filename
[i
+1] = directoryEntry
->Name
[i
];
852 if (directoryEntry
->Name
[i
] != ' ')
856 // Dot only required if extension present
859 // If not . or .. entry
860 if (short_filename
[0]!='.')
861 short_filename
[8] = '.';
863 short_filename
[8] = ' ';
866 short_filename
[8] = ' ';
868 fatfs_get_sfn_display_name(entry
->filename
, short_filename
);
870 if (fatfs_entry_is_dir(directoryEntry
))
875 #if FATFS_INC_TIME_DATE_SUPPORT
877 entry
->create_time
= ((uint16
)directoryEntry
->CrtTime
[1] << 8) | directoryEntry
->CrtTime
[0];
878 entry
->create_date
= ((uint16
)directoryEntry
->CrtDate
[1] << 8) | directoryEntry
->CrtDate
[0];
879 entry
->access_date
= ((uint16
)directoryEntry
->LstAccDate
[1] << 8) | directoryEntry
->LstAccDate
[0];
880 entry
->write_time
= ((uint16
)directoryEntry
->WrtTime
[1] << 8) | directoryEntry
->WrtTime
[0];
881 entry
->write_date
= ((uint16
)directoryEntry
->WrtDate
[1] << 8) | directoryEntry
->WrtDate
[0];
884 entry
->size
= FAT_HTONL(directoryEntry
->FileSize
);
885 entry
->cluster
= (FAT_HTONS(directoryEntry
->FstClusHI
)<<16) | FAT_HTONS(directoryEntry
->FstClusLO
);
887 // Next starting position
888 dirls
->offset
= item
+ 1;
894 // If reached end of the dir move onto next sector