]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - LinuxGUI/Ventoy2Disk/Lib/fat_io_lib/fat_access.c
Improve grammar (Readme.md) (#2086)
[Ventoy.git] / LinuxGUI / Ventoy2Disk / Lib / fat_io_lib / fat_access.c
1 //-----------------------------------------------------------------------------
2 //-----------------------------------------------------------------------------
3 // FAT16/32 File IO Library
4 // V2.6
5 // Ultra-Embedded.com
6 // Copyright 2003 - 2012
7 //
8 // Email: admin@ultra-embedded.com
9 //
10 // License: GPL
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 //-----------------------------------------------------------------------------
14 //
15 // This file is part of FAT File IO Library.
16 //
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.
21 //
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.
26 //
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 //-----------------------------------------------------------------------------
32 #include <string.h>
33 #include "fat_defs.h"
34 #include "fat_access.h"
35 #include "fat_table.h"
36 #include "fat_write.h"
37 #include "fat_string.h"
38 #include "fat_misc.h"
39
40 //-----------------------------------------------------------------------------
41 // fatfs_init: Load FAT Parameters
42 //-----------------------------------------------------------------------------
43 int fatfs_init(struct fatfs *fs)
44 {
45 uint8 num_of_fats;
46 uint16 reserved_sectors;
47 uint32 FATSz;
48 uint32 root_dir_sectors;
49 uint32 total_sectors;
50 uint32 data_sectors;
51 uint32 count_of_clusters;
52 uint8 valid_partition = 0;
53
54 fs->currentsector.address = FAT32_INVALID_CLUSTER;
55 fs->currentsector.dirty = 0;
56
57 fs->next_free_cluster = 0; // Invalid
58
59 fatfs_fat_init(fs);
60
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;
64
65 // MBR: Sector 0 on the disk
66 // NOTE: Some removeable media does not have this.
67
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;
71
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;
76
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;
80
81 // Verify packed structures
82 if (sizeof(struct fat_dir_entry) != FAT_DIR_ENTRY_SIZE)
83 return FAT_INIT_STRUCT_PACKING;
84
85 // Check the partition type code
86 switch(fs->currentsector.sector[PARTITION1_TYPECODE_LOCATION])
87 {
88 case 0x0B:
89 case 0x06:
90 case 0x0C:
91 case 0x0E:
92 case 0x0F:
93 case 0x05:
94 valid_partition = 1;
95 break;
96 case 0x00:
97 valid_partition = 0;
98 break;
99 default:
100 if (fs->currentsector.sector[PARTITION1_TYPECODE_LOCATION] <= 0x06)
101 valid_partition = 1;
102 break;
103 }
104
105 // Read LBA Begin for the file system
106 if (valid_partition)
107 fs->lba_begin = GET_32BIT_WORD(fs->currentsector.sector, PARTITION1_LBA_BEGIN_LOCATION);
108 // Else possibly MBR less disk
109 else
110 fs->lba_begin = 0;
111
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;
116
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;
120
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);
126
127 if(GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16) != 0)
128 fs->fat_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16);
129 else
130 fs->fat_sectors = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_FATSZ32);
131
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);
135
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;
139
140 // First FAT LBA address
141 fs->fat_begin_lba = fs->lba_begin + reserved_sectors;
142
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);
145
146 if (GET_16BIT_WORD(fs->currentsector.sector, 0x1FE) != 0xAA55) // This signature should be AA55
147 return FAT_INIT_INVALID_SIGNATURE;
148
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);
151
152 if(GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16) != 0)
153 FATSz = GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16);
154 else
155 FATSz = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_FATSZ32);
156
157 if(GET_16BIT_WORD(fs->currentsector.sector, BPB_TOTSEC16) != 0)
158 total_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_TOTSEC16);
159 else
160 total_sectors = GET_32BIT_WORD(fs->currentsector.sector, BPB_TOTSEC32);
161
162 data_sectors = total_sectors - (GET_16BIT_WORD(fs->currentsector.sector, BPB_RSVDSECCNT) + (fs->currentsector.sector[BPB_NUMFATS] * FATSz) + root_dir_sectors);
163
164 // Find out which version of FAT this is...
165 if (fs->sectors_per_cluster != 0)
166 {
167 count_of_clusters = data_sectors / fs->sectors_per_cluster;
168
169 if(count_of_clusters < 4085)
170 // Volume is FAT12
171 return FAT_INIT_WRONG_FILESYS_TYPE;
172 else if(count_of_clusters < 65525)
173 {
174 // Clear this FAT32 specific param
175 fs->rootdir_first_cluster = 0;
176
177 // Volume is FAT16
178 fs->fat_type = FAT_TYPE_16;
179 return FAT_INIT_OK;
180 }
181 else
182 {
183 // Volume is FAT32
184 fs->fat_type = FAT_TYPE_32;
185 return FAT_INIT_OK;
186 }
187 }
188 else
189 return FAT_INIT_WRONG_FILESYS_TYPE;
190 }
191 //-----------------------------------------------------------------------------
192 // fatfs_lba_of_cluster: This function converts a cluster number into a sector /
193 // LBA number.
194 //-----------------------------------------------------------------------------
195 uint32 fatfs_lba_of_cluster(struct fatfs *fs, uint32 Cluster_Number)
196 {
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));
199 else
200 return ((fs->cluster_begin_lba + ((Cluster_Number-2)*fs->sectors_per_cluster)));
201 }
202 //-----------------------------------------------------------------------------
203 // fatfs_sector_read:
204 //-----------------------------------------------------------------------------
205 int fatfs_sector_read(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count)
206 {
207 return fs->disk_io.read_media(lba, target, count);
208 }
209 //-----------------------------------------------------------------------------
210 // fatfs_sector_write:
211 //-----------------------------------------------------------------------------
212 int fatfs_sector_write(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count)
213 {
214 return fs->disk_io.write_media(lba, target, count);
215 }
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)
221 {
222 uint32 sector_to_read = 0;
223 uint32 cluster_to_read = 0;
224 uint32 cluster_chain = 0;
225 uint32 i;
226 uint32 lba;
227
228 // FAT16 Root directory
229 if (fs->fat_type == FAT_TYPE_16 && start_cluster == 0)
230 {
231 if (offset < fs->rootdir_sectors)
232 lba = fs->lba_begin + fs->rootdir_first_sector + offset;
233 else
234 return 0;
235 }
236 // FAT16/32 Other
237 else
238 {
239 // Set start of cluster chain to initial value
240 cluster_chain = start_cluster;
241
242 // Find parameters
243 cluster_to_read = offset / fs->sectors_per_cluster;
244 sector_to_read = offset - (cluster_to_read*fs->sectors_per_cluster);
245
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);
249
250 // If end of cluster chain then return false
251 if (cluster_chain == FAT32_LAST_CLUSTER)
252 return 0;
253
254 // Calculate sector address
255 lba = fatfs_lba_of_cluster(fs, cluster_chain)+sector_to_read;
256 }
257
258 // User provided target array
259 if (target)
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)
263 {
264 fs->currentsector.address = lba;
265 return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1);
266 }
267 else
268 return 1;
269 }
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)
275 {
276 // FAT16 Root directory
277 if (fs->fat_type == FAT_TYPE_16 && cluster == 0)
278 {
279 uint32 lba;
280
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;
284 else
285 return 0;
286
287 // User target buffer passed in
288 if (target)
289 {
290 // Read from disk
291 return fs->disk_io.read_media(lba, target, 1);
292 }
293 else
294 {
295 // Calculate read address
296 fs->currentsector.address = lba;
297
298 // Read from disk
299 return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1);
300 }
301 }
302 // FAT16/32 Other
303 else
304 {
305 // User target buffer passed in
306 if (target)
307 {
308 // Calculate read address
309 uint32 lba = fatfs_lba_of_cluster(fs, cluster) + sector;
310
311 // Read from disk
312 return fs->disk_io.read_media(lba, target, 1);
313 }
314 else
315 {
316 // Calculate write address
317 fs->currentsector.address = fatfs_lba_of_cluster(fs, cluster)+sector;
318
319 // Read from disk
320 return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1);
321 }
322 }
323 }
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)
330 {
331 // No write access?
332 if (!fs->disk_io.write_media)
333 return 0;
334
335 // FAT16 Root directory
336 if (fs->fat_type == FAT_TYPE_16 && cluster == 0)
337 {
338 uint32 lba;
339
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;
343 else
344 return 0;
345
346 // User target buffer passed in
347 if (target)
348 {
349 // Write to disk
350 return fs->disk_io.write_media(lba, target, 1);
351 }
352 else
353 {
354 // Calculate write address
355 fs->currentsector.address = lba;
356
357 // Write to disk
358 return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
359 }
360 }
361 // FAT16/32 Other
362 else
363 {
364 // User target buffer passed in
365 if (target)
366 {
367 // Calculate write address
368 uint32 lba = fatfs_lba_of_cluster(fs, cluster) + sector;
369
370 // Write to disk
371 return fs->disk_io.write_media(lba, target, 1);
372 }
373 else
374 {
375 // Calculate write address
376 fs->currentsector.address = fatfs_lba_of_cluster(fs, cluster)+sector;
377
378 // Write to disk
379 return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
380 }
381 }
382 }
383 #endif
384 //-----------------------------------------------------------------------------
385 // fatfs_show_details: Show the details about the filesystem
386 //-----------------------------------------------------------------------------
387 void fatfs_show_details(struct fatfs *fs)
388 {
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));
395 }
396 //-----------------------------------------------------------------------------
397 // fatfs_get_root_cluster: Get the root dir cluster
398 //-----------------------------------------------------------------------------
399 uint32 fatfs_get_root_cluster(struct fatfs *fs)
400 {
401 // NOTE: On FAT16 this will be 0 which has a special meaning...
402 return fs->rootdir_first_cluster;
403 }
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)
408 {
409 uint8 item=0;
410 uint16 recordoffset = 0;
411 uint8 i=0;
412 int x=0;
413 char *long_filename = NULL;
414 char short_filename[13];
415 struct lfn_cache lfn;
416 int dotRequired = 0;
417 struct fat_dir_entry *directoryEntry;
418
419 fatfs_lfn_cache_init(&lfn, 1);
420
421 // Main cluster following loop
422 while (1)
423 {
424 // Read sector
425 if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
426 {
427 // Analyse Sector
428 for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
429 {
430 // Create the multiplier for sector access
431 recordoffset = FAT_DIR_ENTRY_SIZE * item;
432
433 // Overlay directory entry over buffer
434 directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
435
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);
440
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);
444
445 // Normal SFN Entry and Long text exists
446 else if (fatfs_entry_lfn_exists(&lfn, directoryEntry) )
447 {
448 long_filename = fatfs_lfn_cache_get(&lfn);
449
450 // Compare names to see if they match
451 if (fatfs_compare_names(long_filename, name_to_find))
452 {
453 memcpy(sfEntry,directoryEntry,sizeof(struct fat_dir_entry));
454 return 1;
455 }
456
457 fatfs_lfn_cache_init(&lfn, 0);
458 }
459 else
460 #endif
461 // Normal Entry, only 8.3 Text
462 if (fatfs_entry_sfn_only(directoryEntry) )
463 {
464 memset(short_filename, 0, sizeof(short_filename));
465
466 // Copy name to string
467 for (i=0; i<8; i++)
468 short_filename[i] = directoryEntry->Name[i];
469
470 // Extension
471 dotRequired = 0;
472 for (i=8; i<11; i++)
473 {
474 short_filename[i+1] = directoryEntry->Name[i];
475 if (directoryEntry->Name[i] != ' ')
476 dotRequired = 1;
477 }
478
479 // Dot only required if extension present
480 if (dotRequired)
481 {
482 // If not . or .. entry
483 if (short_filename[0]!='.')
484 short_filename[8] = '.';
485 else
486 short_filename[8] = ' ';
487 }
488 else
489 short_filename[8] = ' ';
490
491 // Compare names to see if they match
492 if (fatfs_compare_names(short_filename, name_to_find))
493 {
494 memcpy(sfEntry,directoryEntry,sizeof(struct fat_dir_entry));
495 return 1;
496 }
497
498 fatfs_lfn_cache_init(&lfn, 0);
499 }
500 } // End of if
501 }
502 else
503 break;
504 } // End of while loop
505
506 return 0;
507 }
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)
514 {
515 uint8 item=0;
516 uint16 recordoffset = 0;
517 int x=0;
518 struct fat_dir_entry *directoryEntry;
519
520 // Main cluster following loop
521 while (1)
522 {
523 // Read sector
524 if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
525 {
526 // Analyse Sector
527 for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
528 {
529 // Create the multiplier for sector access
530 recordoffset = FAT_DIR_ENTRY_SIZE * item;
531
532 // Overlay directory entry over buffer
533 directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
534
535 #if FATFS_INC_LFN_SUPPORT
536 // Long File Name Text Found
537 if (fatfs_entry_lfn_text(directoryEntry) )
538 ;
539
540 // If Invalid record found delete any long file name information collated
541 else if (fatfs_entry_lfn_invalid(directoryEntry) )
542 ;
543 else
544 #endif
545 // Normal Entry, only 8.3 Text
546 if (fatfs_entry_sfn_only(directoryEntry) )
547 {
548 if (strncmp((const char*)directoryEntry->Name, shortname, 11)==0)
549 return 1;
550 }
551 } // End of if
552 }
553 else
554 break;
555 } // End of while loop
556
557 return 0;
558 }
559 #endif
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)
565 {
566 time_t time_now;
567 struct tm * time_info;
568 uint16 fat_time;
569 uint16 fat_date;
570
571 // Get system time
572 time(&time_now);
573
574 // Convert to local time
575 time_info = localtime(&time_now);
576
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);
579
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);
582
583 // Update requested fields
584 if (create)
585 {
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;
590 }
591
592 if (modify)
593 {
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;
598 }
599
600 if (access)
601 {
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;
606 }
607
608 return 1;
609 }
610 #endif
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)
617 {
618 uint8 item=0;
619 uint16 recordoffset = 0;
620 int x=0;
621 struct fat_dir_entry *directoryEntry;
622
623 // No write access?
624 if (!fs->disk_io.write_media)
625 return 0;
626
627 // Main cluster following loop
628 while (1)
629 {
630 // Read sector
631 if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
632 {
633 // Analyse Sector
634 for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
635 {
636 // Create the multiplier for sector access
637 recordoffset = FAT_DIR_ENTRY_SIZE * item;
638
639 // Overlay directory entry over buffer
640 directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
641
642 #if FATFS_INC_LFN_SUPPORT
643 // Long File Name Text Found
644 if (fatfs_entry_lfn_text(directoryEntry) )
645 ;
646
647 // If Invalid record found delete any long file name information collated
648 else if (fatfs_entry_lfn_invalid(directoryEntry) )
649 ;
650
651 // Normal Entry, only 8.3 Text
652 else
653 #endif
654 if (fatfs_entry_sfn_only(directoryEntry) )
655 {
656 if (strncmp((const char*)directoryEntry->Name, shortname, 11)==0)
657 {
658 directoryEntry->FileSize = FAT_HTONL(fileLength);
659
660 #if FATFS_INC_TIME_DATE_SUPPORT
661 // Update access / modify time & date
662 fatfs_update_timestamps(directoryEntry, 0, 1, 1);
663 #endif
664
665 // Update sfn entry
666 memcpy((uint8*)(fs->currentsector.sector+recordoffset), (uint8*)directoryEntry, sizeof(struct fat_dir_entry));
667
668 // Write sector back
669 return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
670 }
671 }
672 } // End of if
673 }
674 else
675 break;
676 } // End of while loop
677
678 return 0;
679 }
680 #endif
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)
687 {
688 uint8 item=0;
689 uint16 recordoffset = 0;
690 int x=0;
691 struct fat_dir_entry *directoryEntry;
692
693 // No write access?
694 if (!fs->disk_io.write_media)
695 return 0;
696
697 // Main cluster following loop
698 while (1)
699 {
700 // Read sector
701 if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
702 {
703 // Analyse Sector
704 for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
705 {
706 // Create the multiplier for sector access
707 recordoffset = FAT_DIR_ENTRY_SIZE * item;
708
709 // Overlay directory entry over buffer
710 directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
711
712 #if FATFS_INC_LFN_SUPPORT
713 // Long File Name Text Found
714 if (fatfs_entry_lfn_text(directoryEntry) )
715 ;
716
717 // If Invalid record found delete any long file name information collated
718 else if (fatfs_entry_lfn_invalid(directoryEntry) )
719 ;
720
721 // Normal Entry, only 8.3 Text
722 else
723 #endif
724 if (fatfs_entry_sfn_only(directoryEntry) )
725 {
726 if (strncmp((const char *)directoryEntry->Name, shortname, 11)==0)
727 {
728 // Mark as deleted
729 directoryEntry->Name[0] = FILE_HEADER_DELETED;
730
731 #if FATFS_INC_TIME_DATE_SUPPORT
732 // Update access / modify time & date
733 fatfs_update_timestamps(directoryEntry, 0, 1, 1);
734 #endif
735
736 // Update sfn entry
737 memcpy((uint8*)(fs->currentsector.sector+recordoffset), (uint8*)directoryEntry, sizeof(struct fat_dir_entry));
738
739 // Write sector back
740 return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
741 }
742 }
743 } // End of if
744 }
745 else
746 break;
747 } // End of while loop
748
749 return 0;
750 }
751 #endif
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)
757 {
758 dirls->cluster = StartCluster;
759 dirls->sector = 0;
760 dirls->offset = 0;
761 }
762 #endif
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)
769 {
770 uint8 i,item;
771 uint16 recordoffset;
772 struct fat_dir_entry *directoryEntry;
773 char *long_filename = NULL;
774 char short_filename[13];
775 struct lfn_cache lfn;
776 int dotRequired = 0;
777 int result = 0;
778
779 // Initialise LFN cache first
780 fatfs_lfn_cache_init(&lfn, 0);
781
782 while (1)
783 {
784 // If data read OK
785 if (fatfs_sector_reader(fs, dirls->cluster, dirls->sector, 0))
786 {
787 // Maximum of 16 directory entries
788 for (item = dirls->offset; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
789 {
790 // Increase directory offset
791 recordoffset = FAT_DIR_ENTRY_SIZE * item;
792
793 // Overlay directory entry over buffer
794 directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
795
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);
800
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);
804
805 // Normal SFN Entry and Long text exists
806 else if (fatfs_entry_lfn_exists(&lfn, directoryEntry) )
807 {
808 // Get text
809 long_filename = fatfs_lfn_cache_get(&lfn);
810 strncpy(entry->filename, long_filename, FATFS_MAX_LONG_FILENAME-1);
811
812 if (fatfs_entry_is_dir(directoryEntry))
813 entry->is_dir = 1;
814 else
815 entry->is_dir = 0;
816
817 #if FATFS_INC_TIME_DATE_SUPPORT
818 // Get time / dates
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];
824 #endif
825
826 entry->size = FAT_HTONL(directoryEntry->FileSize);
827 entry->cluster = (FAT_HTONS(directoryEntry->FstClusHI)<<16) | FAT_HTONS(directoryEntry->FstClusLO);
828
829 // Next starting position
830 dirls->offset = item + 1;
831 result = 1;
832 return 1;
833 }
834 // Normal Entry, only 8.3 Text
835 else
836 #endif
837 if ( fatfs_entry_sfn_only(directoryEntry) )
838 {
839 fatfs_lfn_cache_init(&lfn, 0);
840
841 memset(short_filename, 0, sizeof(short_filename));
842
843 // Copy name to string
844 for (i=0; i<8; i++)
845 short_filename[i] = directoryEntry->Name[i];
846
847 // Extension
848 dotRequired = 0;
849 for (i=8; i<11; i++)
850 {
851 short_filename[i+1] = directoryEntry->Name[i];
852 if (directoryEntry->Name[i] != ' ')
853 dotRequired = 1;
854 }
855
856 // Dot only required if extension present
857 if (dotRequired)
858 {
859 // If not . or .. entry
860 if (short_filename[0]!='.')
861 short_filename[8] = '.';
862 else
863 short_filename[8] = ' ';
864 }
865 else
866 short_filename[8] = ' ';
867
868 fatfs_get_sfn_display_name(entry->filename, short_filename);
869
870 if (fatfs_entry_is_dir(directoryEntry))
871 entry->is_dir = 1;
872 else
873 entry->is_dir = 0;
874
875 #if FATFS_INC_TIME_DATE_SUPPORT
876 // Get time / dates
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];
882 #endif
883
884 entry->size = FAT_HTONL(directoryEntry->FileSize);
885 entry->cluster = (FAT_HTONS(directoryEntry->FstClusHI)<<16) | FAT_HTONS(directoryEntry->FstClusLO);
886
887 // Next starting position
888 dirls->offset = item + 1;
889 result = 1;
890 return 1;
891 }
892 }// end of for
893
894 // If reached end of the dir move onto next sector
895 dirls->sector++;
896 dirls->offset = 0;
897 }
898 else
899 break;
900 }
901
902 return result;
903 }
904 #endif