UbixOS  2.0
fat_access.c
Go to the documentation of this file.
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  uint8 num_of_fats;
45  uint16 reserved_sectors;
46  uint32 FATSz;
47  uint32 root_dir_sectors;
48  uint32 total_sectors;
49  uint32 data_sectors;
50  uint32 count_of_clusters;
51  uint8 valid_partition = 0;
52 
53  fs->currentsector.address = FAT32_INVALID_CLUSTER;
54  fs->currentsector.dirty = 0;
55 
56  fs->next_free_cluster = 0; // Invalid
57 
59 
60  // Make sure we have a read function (write function is optional)
61  if (!fs->disk_io.read_media)
63 
64  // MBR: Sector 0 on the disk
65  // NOTE: Some removeable media does not have this.
66 
67  // Load MBR (LBA 0) into the 512 byte buffer
68  if (!fs->disk_io.read_media(0, fs->currentsector.sector, 1))
70 
71  // Make Sure 0x55 and 0xAA are at end of sector
72  // (this should be the case regardless of the MBR or boot sector)
73  if (fs->currentsector.sector[SIGNATURE_POSITION] != 0x55 || fs->currentsector.sector[SIGNATURE_POSITION + 1] != 0xAA)
75 
76  // Now check again using the access function to prove endian conversion function
77  if (GET_16BIT_WORD(fs->currentsector.sector,
79  return FAT_INIT_ENDIAN_ERROR;
80 
81  // Verify packed structures
82  if (sizeof(struct fat_dir_entry) != FAT_DIR_ENTRY_SIZE)
84 
85  // Check the partition type code
86  switch (fs->currentsector.sector[PARTITION1_TYPECODE_LOCATION]) {
87  case 0x0B:
88  case 0x06:
89  case 0x0C:
90  case 0x0E:
91  case 0x0F:
92  case 0x05:
93  valid_partition = 1;
94  break;
95  case 0x00:
96  valid_partition = 0;
97  break;
98  default:
99  if (fs->currentsector.sector[PARTITION1_TYPECODE_LOCATION] <= 0x06)
100  valid_partition = 1;
101  break;
102  }
103 
104  // Read LBA Begin for the file system
105  if (valid_partition)
106  fs->lba_begin = GET_32BIT_WORD(fs->currentsector.sector, PARTITION1_LBA_BEGIN_LOCATION);
107  // Else possibly MBR less disk
108  else
109  fs->lba_begin = 0;
110 
111  // Load Volume 1 table into sector buffer
112  // (We may already have this in the buffer if MBR less drive!)
113  if (!fs->disk_io.read_media(fs->lba_begin, fs->currentsector.sector, 1))
115 
116  // Make sure there are 512 bytes per cluster
117  if (GET_16BIT_WORD(fs->currentsector.sector, 0x0B) != FAT_SECTOR_SIZE)
119 
120  // Load Parameters of FAT partition
121  fs->sectors_per_cluster = fs->currentsector.sector[BPB_SECPERCLUS];
122  reserved_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_RSVDSECCNT);
123  num_of_fats = fs->currentsector.sector[BPB_NUMFATS];
124  fs->root_entry_count = GET_16BIT_WORD(fs->currentsector.sector, BPB_ROOTENTCNT);
125 
126  if (GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16) != 0)
127  fs->fat_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16);
128  else
129  fs->fat_sectors = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_FATSZ32);
130 
131  // For FAT32 (which this may be)
132  fs->rootdir_first_cluster = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_ROOTCLUS);
133  fs->fs_info_sector = GET_16BIT_WORD(fs->currentsector.sector, BPB_FAT32_FSINFO);
134 
135  // For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector
136  fs->rootdir_first_sector = reserved_sectors + (num_of_fats * fs->fat_sectors);
137  fs->rootdir_sectors = ((fs->root_entry_count * 32) + (FAT_SECTOR_SIZE - 1)) / FAT_SECTOR_SIZE;
138 
139  // First FAT LBA address
140  fs->fat_begin_lba = fs->lba_begin + reserved_sectors;
141 
142  // The address of the first data cluster on this volume
143  fs->cluster_begin_lba = fs->fat_begin_lba + (num_of_fats * fs->fat_sectors);
144 
145  if (GET_16BIT_WORD(fs->currentsector.sector, 0x1FE) != 0xAA55) // This signature should be AA55
147 
148  // Calculate the root dir sectors
149  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);
150 
151  if (GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16) != 0)
152  FATSz = GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16);
153  else
154  FATSz = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_FATSZ32);
155 
156  if (GET_16BIT_WORD(fs->currentsector.sector, BPB_TOTSEC16) != 0)
157  total_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_TOTSEC16);
158  else
159  total_sectors = GET_32BIT_WORD(fs->currentsector.sector, BPB_TOTSEC32);
160 
161  data_sectors = total_sectors - (GET_16BIT_WORD(fs->currentsector.sector, BPB_RSVDSECCNT) + (fs->currentsector.sector[BPB_NUMFATS] * FATSz) + root_dir_sectors);
162 
163  // Find out which version of FAT this is...
164  if (fs->sectors_per_cluster != 0) {
165  count_of_clusters = data_sectors / fs->sectors_per_cluster;
166 
167  if (count_of_clusters < 4085)
168  // Volume is FAT12
170  else if (count_of_clusters < 65525) {
171  // Clear this FAT32 specific param
172  fs->rootdir_first_cluster = 0;
173 
174  // Volume is FAT16
175  fs->fat_type = FAT_TYPE_16;
176  return FAT_INIT_OK;
177  }
178  else {
179  // Volume is FAT32
180  fs->fat_type = FAT_TYPE_32;
181  return FAT_INIT_OK;
182  }
183  }
184  else
186 }
187 //-----------------------------------------------------------------------------
188 // fatfs_lba_of_cluster: This function converts a cluster number into a sector /
189 // LBA number.
190 //-----------------------------------------------------------------------------
191 uint32 fatfs_lba_of_cluster(struct fatfs *fs, uint32 Cluster_Number) {
192  if (fs->fat_type == FAT_TYPE_16)
193  return (fs->cluster_begin_lba + (fs->root_entry_count * 32 / FAT_SECTOR_SIZE) + ((Cluster_Number - 2) * fs->sectors_per_cluster));
194  else
195  return ((fs->cluster_begin_lba + ((Cluster_Number - 2) * fs->sectors_per_cluster)));
196 }
197 //-----------------------------------------------------------------------------
198 // fatfs_sector_read:
199 //-----------------------------------------------------------------------------
200 int fatfs_sector_read(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count) {
201  return fs->disk_io.read_media(lba, target, count);
202 }
203 //-----------------------------------------------------------------------------
204 // fatfs_sector_write:
205 //-----------------------------------------------------------------------------
206 int fatfs_sector_write(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count) {
207  return fs->disk_io.write_media(lba, target, count);
208 }
209 //-----------------------------------------------------------------------------
210 // fatfs_sector_reader: From the provided startcluster and sector offset
211 // Returns True if success, returns False if not (including if read out of range)
212 //-----------------------------------------------------------------------------
213 int fatfs_sector_reader(struct fatfs *fs, uint32 start_cluster, uint32 offset, uint8 *target) {
214  uint32 sector_to_read = 0;
215  uint32 cluster_to_read = 0;
216  uint32 cluster_chain = 0;
217  uint32 i;
218  uint32 lba;
219 
220  // FAT16 Root directory
221  if (fs->fat_type == FAT_TYPE_16 && start_cluster == 0) {
222  if (offset < fs->rootdir_sectors)
223  lba = fs->lba_begin + fs->rootdir_first_sector + offset;
224  else
225  return 0;
226  }
227  // FAT16/32 Other
228  else {
229  // Set start of cluster chain to initial value
230  cluster_chain = start_cluster;
231 
232  // Find parameters
233  cluster_to_read = offset / fs->sectors_per_cluster;
234  sector_to_read = offset - (cluster_to_read * fs->sectors_per_cluster);
235 
236  // Follow chain to find cluster to read
237  for (i = 0; i < cluster_to_read; i++)
238  cluster_chain = fatfs_find_next_cluster(fs, cluster_chain);
239 
240  // If end of cluster chain then return false
241  if (cluster_chain == FAT32_LAST_CLUSTER)
242  return 0;
243 
244  // Calculate sector address
245  lba = fatfs_lba_of_cluster(fs, cluster_chain) + sector_to_read;
246  }
247 
248  // User provided target array
249  if (target)
250  return fs->disk_io.read_media(lba, target, 1);
251  // Else read sector if not already loaded
252  else if (lba != fs->currentsector.address) {
253  fs->currentsector.address = lba;
254  return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1);
255  }
256  else
257  return 1;
258 }
259 //-----------------------------------------------------------------------------
260 // fatfs_read_sector: Read from the provided cluster and sector offset
261 // Returns True if success, returns False if not
262 //-----------------------------------------------------------------------------
263 int fatfs_read_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target) {
264  // FAT16 Root directory
265  if (fs->fat_type == FAT_TYPE_16 && cluster == 0) {
266  uint32 lba;
267 
268  // In FAT16, there are a limited amount of sectors in root dir!
269  if (sector < fs->rootdir_sectors)
270  lba = fs->lba_begin + fs->rootdir_first_sector + sector;
271  else
272  return 0;
273 
274  // User target buffer passed in
275  if (target) {
276  // Read from disk
277  return fs->disk_io.read_media(lba, target, 1);
278  }
279  else {
280  // Calculate read address
281  fs->currentsector.address = lba;
282 
283  // Read from disk
284  return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1);
285  }
286  }
287  // FAT16/32 Other
288  else {
289  // User target buffer passed in
290  if (target) {
291  // Calculate read address
292  uint32 lba = fatfs_lba_of_cluster(fs, cluster) + sector;
293 
294  // Read from disk
295  return fs->disk_io.read_media(lba, target, 1);
296  }
297  else {
298  // Calculate write address
299  fs->currentsector.address = fatfs_lba_of_cluster(fs, cluster) + sector;
300 
301  // Read from disk
302  return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1);
303  }
304  }
305 }
306 //-----------------------------------------------------------------------------
307 // fatfs_write_sector: Write to the provided cluster and sector offset
308 // Returns True if success, returns False if not
309 //-----------------------------------------------------------------------------
310 #if FATFS_INC_WRITE_SUPPORT
311 int fatfs_write_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target) {
312  // No write access?
313  if (!fs->disk_io.write_media)
314  return 0;
315 
316  // FAT16 Root directory
317  if (fs->fat_type == FAT_TYPE_16 && cluster == 0) {
318  uint32 lba;
319 
320  // In FAT16 we cannot extend the root dir!
321  if (sector < fs->rootdir_sectors)
322  lba = fs->lba_begin + fs->rootdir_first_sector + sector;
323  else
324  return 0;
325 
326  // User target buffer passed in
327  if (target) {
328  // Write to disk
329  return fs->disk_io.write_media(lba, target, 1);
330  }
331  else {
332  // Calculate write address
333  fs->currentsector.address = lba;
334 
335  // Write to disk
336  return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
337  }
338  }
339  // FAT16/32 Other
340  else {
341  // User target buffer passed in
342  if (target) {
343  // Calculate write address
344  uint32 lba = fatfs_lba_of_cluster(fs, cluster) + sector;
345 
346  // Write to disk
347  return fs->disk_io.write_media(lba, target, 1);
348  }
349  else {
350  // Calculate write address
351  fs->currentsector.address = fatfs_lba_of_cluster(fs, cluster) + sector;
352 
353  // Write to disk
354  return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
355  }
356  }
357 }
358 #endif
359 //-----------------------------------------------------------------------------
360 // fatfs_show_details: Show the details about the filesystem
361 //-----------------------------------------------------------------------------
362 void fatfs_show_details(struct fatfs *fs) {
363  FAT_PRINTF(("FAT details:\r\n"));
364  FAT_PRINTF((" Type =%s", (fs->fat_type == FAT_TYPE_32) ? "FAT32": "FAT16"));
365  FAT_PRINTF((" Root Dir First Cluster = %x\r\n", fs->rootdir_first_cluster));
366  FAT_PRINTF((" FAT Begin LBA = 0x%x\r\n",fs->fat_begin_lba));
367  FAT_PRINTF((" Cluster Begin LBA = 0x%x\r\n",fs->cluster_begin_lba));
368  FAT_PRINTF((" Sectors Per Cluster = %d\r\n", fs->sectors_per_cluster));
369 }
370 //-----------------------------------------------------------------------------
371 // fatfs_get_root_cluster: Get the root dir cluster
372 //-----------------------------------------------------------------------------
374  // NOTE: On FAT16 this will be 0 which has a special meaning...
375  return fs->rootdir_first_cluster;
376 }
377 //-------------------------------------------------------------
378 // fatfs_get_file_entry: Find the file entry for a filename
379 //-------------------------------------------------------------
380 uint32 fatfs_get_file_entry(struct fatfs *fs, uint32 Cluster, char *name_to_find, struct fat_dir_entry *sfEntry) {
381  uint8 item = 0;
382  uint16 recordoffset = 0;
383  uint8 i = 0;
384  int x = 0;
385  char *long_filename = NULL;
386  char short_filename[13];
387  struct lfn_cache lfn;
388  int dotRequired = 0;
390 
391  fatfs_lfn_cache_init(&lfn, 1);
392 
393  // Main cluster following loop
394  while (1) {
395  // Read sector
396  if (fatfs_sector_reader(fs, Cluster, x++, 0)) { // If sector read was successfull
397  // Analyse Sector
398  for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++) {
399  // Create the multiplier for sector access
400  recordoffset = FAT_DIR_ENTRY_SIZE * item;
401 
402  // Overlay directory entry over buffer
403  directoryEntry = (struct fat_dir_entry*) (fs->currentsector.sector + recordoffset);
404 
405 #if FATFS_INC_LFN_SUPPORT
406 
407  if (fatfs_entry_lfn_text(directoryEntry)) { // Long File Name Text Found
408  fatfs_lfn_cache_entry(&lfn, fs->currentsector.sector + recordoffset);
409  }
410  else if (fatfs_entry_lfn_invalid(directoryEntry)) { // If Invalid record found delete any long file name information collated
411 
412  fatfs_lfn_cache_init(&lfn, 0);
413  }
414  else if (fatfs_entry_lfn_exists(&lfn, directoryEntry)) { // Normal SFN Entry and Long text exists
415  long_filename = fatfs_lfn_cache_get(&lfn);
416 
417  // Compare names to see if they match
418  if (fatfs_compare_names(long_filename, name_to_find)) {
419  memcpy(sfEntry, directoryEntry, sizeof(struct fat_dir_entry));
420  return 1;
421  }
422 
423  fatfs_lfn_cache_init(&lfn, 0);
424  }
425  else {
426 #endif
427  if (fatfs_entry_sfn_only(directoryEntry)) { // Normal Entry, only 8.3 Text
428  memset(short_filename, 0, sizeof(short_filename));
429 
430  // Copy name to string
431  for (i = 0; i < 8; i++)
432  short_filename[i] = directoryEntry->Name[i];
433 
434  // Extension
435  dotRequired = 0;
436  for (i = 8; i < 11; i++) {
437  short_filename[i + 1] = directoryEntry->Name[i];
438  if (directoryEntry->Name[i] != ' ')
439  dotRequired = 1;
440  }
441 
442  // Dot only required if extension present
443  if (dotRequired) {
444  // If not . or .. entry
445  if (short_filename[0] != '.')
446  short_filename[8] = '.';
447  else
448  short_filename[8] = ' ';
449  }
450  else
451  short_filename[8] = ' ';
452 
453  // Compare names to see if they match
454  if (fatfs_compare_names(short_filename, name_to_find)) {
455  memcpy(sfEntry, directoryEntry, sizeof(struct fat_dir_entry));
456  return 1;
457  }
458 
459  fatfs_lfn_cache_init(&lfn, 0);
460  }
461 #if FATFS_INC_LFN_SUPPORT
462  }
463 #endif
464 
465  } // End of for
466  }
467  else
468  break;
469  } // End of while loop
470 
471  return 0;
472 }
473 //-------------------------------------------------------------
474 // fatfs_sfn_exists: Check if a short filename exists.
475 // NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
476 //-------------------------------------------------------------
477 #if FATFS_INC_WRITE_SUPPORT
478 int fatfs_sfn_exists(struct fatfs *fs, uint32 Cluster, char *shortname) {
479  uint8 item = 0;
480  uint16 recordoffset = 0;
481  int x = 0;
483 
484  // Main cluster following loop
485  while (1) {
486  // Read sector
487  if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
488  {
489  // Analyse Sector
490  for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++) {
491  // Create the multiplier for sector access
492  recordoffset = FAT_DIR_ENTRY_SIZE * item;
493 
494  // Overlay directory entry over buffer
495  directoryEntry = (struct fat_dir_entry*) (fs->currentsector.sector + recordoffset);
496 
497 #if FATFS_INC_LFN_SUPPORT
498  // Long File Name Text Found
500  ;
501 
502  // If Invalid record found delete any long file name information collated
504  ;
505  else
506 #endif
507  // Normal Entry, only 8.3 Text
509  if (strncmp((const char*) directoryEntry->Name, shortname, 11) == 0)
510  return 1;
511  }
512  } // End of if
513  }
514  else
515  break;
516  } // End of while loop
517 
518  return 0;
519 }
520 #endif
521 //-------------------------------------------------------------
522 // fatfs_update_timestamps: Update date/time details
523 //-------------------------------------------------------------
524 #if FATFS_INC_TIME_DATE_SUPPORT
525 int fatfs_update_timestamps(struct fat_dir_entry *directoryEntry, int create, int modify, int access)
526 {
527  time_t time_now;
528  struct tm * time_info;
529  uint16 fat_time;
530  uint16 fat_date;
531 
532  // Get system time
533  time(&time_now);
534 
535  // Convert to local time
536  time_info = localtime(&time_now);
537 
538  // Convert time to FAT format
539  fat_time = fatfs_convert_to_fat_time(time_info->tm_hour, time_info->tm_min, time_info->tm_sec);
540 
541  // Convert date to FAT format
542  fat_date = fatfs_convert_to_fat_date(time_info->tm_mday, time_info->tm_mon + 1, time_info->tm_year + 1900);
543 
544  // Update requested fields
545  if (create)
546  {
547  directoryEntry->CrtTime[1] = fat_time >> 8;
548  directoryEntry->CrtTime[0] = fat_time >> 0;
549  directoryEntry->CrtDate[1] = fat_date >> 8;
550  directoryEntry->CrtDate[0] = fat_date >> 0;
551  }
552 
553  if (modify)
554  {
555  directoryEntry->WrtTime[1] = fat_time >> 8;
556  directoryEntry->WrtTime[0] = fat_time >> 0;
557  directoryEntry->WrtDate[1] = fat_date >> 8;
558  directoryEntry->WrtDate[0] = fat_date >> 0;
559  }
560 
561  if (access)
562  {
563  directoryEntry->LstAccDate[1] = fat_time >> 8;
564  directoryEntry->LstAccDate[0] = fat_time >> 0;
565  directoryEntry->LstAccDate[1] = fat_date >> 8;
566  directoryEntry->LstAccDate[0] = fat_date >> 0;
567  }
568 
569  return 1;
570 }
571 #endif
572 
573 //-------------------------------------------------------------
574 // fatfs_update_file_length: Find a SFN entry and update it
575 // NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
576 //-------------------------------------------------------------
577 #if FATFS_INC_WRITE_SUPPORT
578 int fatfs_update_file_length(struct fatfs *fs, uint32 Cluster, char *shortname, uint32 fileLength) {
579  uint8 item = 0;
580  uint16 recordoffset = 0;
581  int x = 0;
583 
584  // No write access?
585  if (!fs->disk_io.write_media)
586  return 0;
587 
588  // Main cluster following loop
589  while (1) {
590  // Read sector
591  if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
592  {
593  // Analyse Sector
594  for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++) {
595  // Create the multiplier for sector access
596  recordoffset = FAT_DIR_ENTRY_SIZE * item;
597 
598  // Overlay directory entry over buffer
599  directoryEntry = (struct fat_dir_entry*) (fs->currentsector.sector + recordoffset);
600 
601 #if FATFS_INC_LFN_SUPPORT
602  // Long File Name Text Found
604  ;
605 
606  // If Invalid record found delete any long file name information collated
608  ;
609 
610  // Normal Entry, only 8.3 Text
611  else
612 #endif
614  if (strncmp((const char*) directoryEntry->Name, shortname, 11) == 0) {
615  directoryEntry->FileSize = FAT_HTONL(fileLength);
616 
617 #if FATFS_INC_TIME_DATE_SUPPORT
618  // Update access / modify time & date
620 #endif
621 
622  // Update sfn entry
623  memcpy((uint8*) (fs->currentsector.sector + recordoffset), (uint8*) directoryEntry, sizeof(struct fat_dir_entry));
624 
625  // Write sector back
626  return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
627  }
628  }
629  } // End of if
630  }
631  else
632  break;
633  } // End of while loop
634 
635  return 0;
636 }
637 #endif
638 //-------------------------------------------------------------
639 // fatfs_mark_file_deleted: Find a SFN entry and mark if as deleted
640 // NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
641 //-------------------------------------------------------------
642 #if FATFS_INC_WRITE_SUPPORT
643 int fatfs_mark_file_deleted(struct fatfs *fs, uint32 Cluster, char *shortname) {
644  uint8 item = 0;
645  uint16 recordoffset = 0;
646  int x = 0;
648 
649  // No write access?
650  if (!fs->disk_io.write_media)
651  return 0;
652 
653  // Main cluster following loop
654  while (1) {
655  // Read sector
656  if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
657  {
658  // Analyse Sector
659  for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++) {
660  // Create the multiplier for sector access
661  recordoffset = FAT_DIR_ENTRY_SIZE * item;
662 
663  // Overlay directory entry over buffer
664  directoryEntry = (struct fat_dir_entry*) (fs->currentsector.sector + recordoffset);
665 
666 #if FATFS_INC_LFN_SUPPORT
667  // Long File Name Text Found
669  ;
670 
671  // If Invalid record found delete any long file name information collated
673  ;
674 
675  // Normal Entry, only 8.3 Text
676  else
677 #endif
679  if (strncmp((const char*) directoryEntry->Name, shortname, 11) == 0) {
680  // Mark as deleted
682 
683 #if FATFS_INC_TIME_DATE_SUPPORT
684  // Update access / modify time & date
686 #endif
687 
688  // Update sfn entry
689  memcpy((uint8*) (fs->currentsector.sector + recordoffset), (uint8*) directoryEntry, sizeof(struct fat_dir_entry));
690 
691  // Write sector back
692  return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
693  }
694  }
695  } // End of if
696  }
697  else
698  break;
699  } // End of while loop
700 
701  return 0;
702 }
703 #endif
704 //-----------------------------------------------------------------------------
705 // fatfs_list_directory_start: Initialise a directory listing procedure
706 //-----------------------------------------------------------------------------
707 #if FATFS_DIR_LIST_SUPPORT
708 void fatfs_list_directory_start(struct fatfs *fs, struct fs_dir_list_status *dirls, uint32 StartCluster) {
709  dirls->cluster = StartCluster;
710  dirls->sector = 0;
711  dirls->offset = 0;
712 }
713 #endif
714 //-----------------------------------------------------------------------------
715 // fatfs_list_directory_next: Get the next entry in the directory.
716 // Returns: 1 = found, 0 = end of listing
717 //-----------------------------------------------------------------------------
718 #if FATFS_DIR_LIST_SUPPORT
719 int fatfs_list_directory_next(struct fatfs *fs, struct fs_dir_list_status *dirls, struct fs_dir_ent *entry) {
720  uint8 i, item;
721  uint16 recordoffset;
723  char *long_filename = NULL;
724  char short_filename[13];
725  struct lfn_cache lfn;
726  int dotRequired = 0;
727  int result = 0;
728 
729  // Initialise LFN cache first
730  fatfs_lfn_cache_init(&lfn, 0);
731 
732  while (1) {
733  // If data read OK
734  if (fatfs_sector_reader(fs, dirls->cluster, dirls->sector, 0)) {
735  // Maximum of 16 directory entries
736  for (item = dirls->offset; item < FAT_DIR_ENTRIES_PER_SECTOR; item++) {
737  // Increase directory offset
738  recordoffset = FAT_DIR_ENTRY_SIZE * item;
739 
740  // Overlay directory entry over buffer
741  directoryEntry = (struct fat_dir_entry*) (fs->currentsector.sector + recordoffset);
742 
743 #if FATFS_INC_LFN_SUPPORT
744  // Long File Name Text Found
746  fatfs_lfn_cache_entry(&lfn, fs->currentsector.sector + recordoffset);
747 
748  // If Invalid record found delete any long file name information collated
750  fatfs_lfn_cache_init(&lfn, 0);
751 
752  // Normal SFN Entry and Long text exists
753  else if (fatfs_entry_lfn_exists(&lfn, directoryEntry)) {
754  // Get text
755  long_filename = fatfs_lfn_cache_get(&lfn);
756  strncpy(entry->filename, long_filename, FATFS_MAX_LONG_FILENAME - 1);
757 
759  entry->is_dir = 1;
760  else
761  entry->is_dir = 0;
762 
763 #if FATFS_INC_TIME_DATE_SUPPORT
764  // Get time / dates
765  entry->create_time = ((uint16)directoryEntry->CrtTime[1] << 8) | directoryEntry->CrtTime[0];
766  entry->create_date = ((uint16)directoryEntry->CrtDate[1] << 8) | directoryEntry->CrtDate[0];
767  entry->access_date = ((uint16)directoryEntry->LstAccDate[1] << 8) | directoryEntry->LstAccDate[0];
768  entry->write_time = ((uint16)directoryEntry->WrtTime[1] << 8) | directoryEntry->WrtTime[0];
769  entry->write_date = ((uint16)directoryEntry->WrtDate[1] << 8) | directoryEntry->WrtDate[0];
770 #endif
771 
772  entry->size = FAT_HTONL(directoryEntry->FileSize);
773  entry->cluster = (FAT_HTONS(directoryEntry->FstClusHI) << 16) | FAT_HTONS(directoryEntry->FstClusLO);
774 
775  // Next starting position
776  dirls->offset = item + 1;
777  result = 1;
778  return 1;
779  }
780  // Normal Entry, only 8.3 Text
781  else
782 #endif
784  fatfs_lfn_cache_init(&lfn, 0);
785 
786  memset(short_filename, 0, sizeof(short_filename));
787 
788  // Copy name to string
789  for (i = 0; i < 8; i++)
790  short_filename[i] = directoryEntry->Name[i];
791 
792  // Extension
793  dotRequired = 0;
794  for (i = 8; i < 11; i++) {
795  short_filename[i + 1] = directoryEntry->Name[i];
796  if (directoryEntry->Name[i] != ' ')
797  dotRequired = 1;
798  }
799 
800  // Dot only required if extension present
801  if (dotRequired) {
802  // If not . or .. entry
803  if (short_filename[0] != '.')
804  short_filename[8] = '.';
805  else
806  short_filename[8] = ' ';
807  }
808  else
809  short_filename[8] = ' ';
810 
811  fatfs_get_sfn_display_name(entry->filename, short_filename);
812 
814  entry->is_dir = 1;
815  else
816  entry->is_dir = 0;
817 
818 #if FATFS_INC_TIME_DATE_SUPPORT
819  // Get time / dates
820  entry->create_time = ((uint16)directoryEntry->CrtTime[1] << 8) | directoryEntry->CrtTime[0];
821  entry->create_date = ((uint16)directoryEntry->CrtDate[1] << 8) | directoryEntry->CrtDate[0];
822  entry->access_date = ((uint16)directoryEntry->LstAccDate[1] << 8) | directoryEntry->LstAccDate[0];
823  entry->write_time = ((uint16)directoryEntry->WrtTime[1] << 8) | directoryEntry->WrtTime[0];
824  entry->write_date = ((uint16)directoryEntry->WrtDate[1] << 8) | directoryEntry->WrtDate[0];
825 #endif
826 
827  entry->size = FAT_HTONL(directoryEntry->FileSize);
828  entry->cluster = (FAT_HTONS(directoryEntry->FstClusHI) << 16) | FAT_HTONS(directoryEntry->FstClusLO);
829 
830  // Next starting position
831  dirls->offset = item + 1;
832  result = 1;
833  return 1;
834  }
835  } // end of for
836 
837  // If reached end of the dir move onto next sector
838  dirls->sector++;
839  dirls->offset = 0;
840  }
841  else
842  break;
843  }
844 
845  return result;
846 }
847 #endif
fatfs_update_timestamps
int fatfs_update_timestamps(struct fat_dir_entry *directoryEntry, int create, int modify, int access)
FAT_TYPE_32
Definition: fat_access.h:54
fatfs_sector_write
int fatfs_sector_write(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count)
Definition: fat_access.c:206
fs_dir_list_status
Definition: fat_access.h:90
fat_write.h
fat_access.h
FAT_INIT_MEDIA_ACCESS_ERROR
#define FAT_INIT_MEDIA_ACCESS_ERROR
Definition: fat_access.h:11
fs_dir_ent::filename
char filename[260]
Definition: fat_access.h:99
BPB_ROOTENTCNT
#define BPB_ROOTENTCNT
Definition: fat_defs.h:20
fat_table.h
PARTITION1_TYPECODE_LOCATION
#define PARTITION1_TYPECODE_LOCATION
Definition: fat_defs.h:61
uint8
unsigned char uint8
Definition: fat_types.h:15
fatfs_sfn_exists
int fatfs_sfn_exists(struct fatfs *fs, uint32 Cluster, char *shortname)
Definition: fat_access.c:478
FAT32_LAST_CLUSTER
#define FAT32_LAST_CLUSTER
Definition: fat_defs.h:108
fatfs_get_root_cluster
uint32 fatfs_get_root_cluster(struct fatfs *fs)
Definition: fat_access.c:373
fatfs_mark_file_deleted
int fatfs_mark_file_deleted(struct fatfs *fs, uint32 Cluster, char *shortname)
Definition: fat_access.c:643
string.h
FAT_INIT_WRONG_FILESYS_TYPE
#define FAT_INIT_WRONG_FILESYS_TYPE
Definition: fat_access.h:15
fs_dir_list_status::cluster
uint32 cluster
Definition: fat_access.h:93
fatfs_get_sfn_display_name
int fatfs_get_sfn_display_name(char *out, char *in)
Definition: fat_string.c:345
fatfs_convert_to_fat_time
uint16 fatfs_convert_to_fat_time(int hours, int minutes, int seconds)
FAT_INIT_ENDIAN_ERROR
#define FAT_INIT_ENDIAN_ERROR
Definition: fat_access.h:14
BPB_SECPERCLUS
#define BPB_SECPERCLUS
Definition: fat_defs.h:17
fatfs_lfn_cache_get
char * fatfs_lfn_cache_get(struct lfn_cache *lfn)
Definition: fat_misc.c:94
strncpy
char * strncpy(char *__restrict, const char *__restrict, size_t)
fatfs_find_next_cluster
uint32 fatfs_find_next_cluster(struct fatfs *fs, uint32 current_cluster)
Definition: fat_table.c:205
FAT_INIT_OK
#define FAT_INIT_OK
Definition: fat_access.h:10
fatfs_get_file_entry
uint32 fatfs_get_file_entry(struct fatfs *fs, uint32 Cluster, char *name_to_find, struct fat_dir_entry *sfEntry)
Definition: fat_access.c:380
FAT_INIT_INVALID_SIGNATURE
#define FAT_INIT_INVALID_SIGNATURE
Definition: fat_access.h:13
fatfs_convert_to_fat_date
uint16 fatfs_convert_to_fat_date(int day, int month, int year)
directoryEntry
Definition: ubixfs.h:98
BPB_FAT32_ROOTCLUS
#define BPB_FAT32_ROOTCLUS
Definition: fat_defs.h:40
fatfs_lfn_cache_entry
void fatfs_lfn_cache_entry(struct lfn_cache *lfn, uint8 *entryBuffer)
Definition: fat_misc.c:56
FAT_HTONL
#define FAT_HTONL(n)
Definition: fat_types.h:46
fat_defs.h
fatfs_show_details
void fatfs_show_details(struct fatfs *fs)
Definition: fat_access.c:362
memcpy
void * memcpy(const void *dst, const void *src, size_t length)
PARTITION1_LBA_BEGIN_LOCATION
#define PARTITION1_LBA_BEGIN_LOCATION
Definition: fat_defs.h:64
fs
Definition: fs.h:260
fatfs_entry_sfn_only
int fatfs_entry_sfn_only(struct fat_dir_entry *entry)
Definition: fat_misc.c:142
fatfs_entry_lfn_text
int fatfs_entry_lfn_text(struct fat_dir_entry *entry)
Definition: fat_misc.c:110
FAT_DIR_ENTRY_SIZE
#define FAT_DIR_ENTRY_SIZE
Definition: fat_defs.h:67
fatfs_sector_reader
int fatfs_sector_reader(struct fatfs *fs, uint32 start_cluster, uint32 offset, uint8 *target)
Definition: fat_access.c:213
BPB_TOTSEC32
#define BPB_TOTSEC32
Definition: fat_defs.h:27
fatfs_list_directory_start
void fatfs_list_directory_start(struct fatfs *fs, struct fs_dir_list_status *dirls, uint32 StartCluster)
Definition: fat_access.c:708
fs_dir_ent::is_dir
uint8 is_dir
Definition: fat_access.h:100
fatfs_write_sector
int fatfs_write_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target)
Definition: fat_access.c:311
BPB_RSVDSECCNT
#define BPB_RSVDSECCNT
Definition: fat_defs.h:18
FAT_SECTOR_SIZE
#define FAT_SECTOR_SIZE
Definition: fat_opts.h:70
FAT_INIT_INVALID_SECTOR_SIZE
#define FAT_INIT_INVALID_SECTOR_SIZE
Definition: fat_access.h:12
fat_misc.h
fatfs_sector_read
int fatfs_sector_read(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count)
Definition: fat_access.c:200
fatfs_lba_of_cluster
uint32 fatfs_lba_of_cluster(struct fatfs *fs, uint32 Cluster_Number)
Definition: fat_access.c:191
fs_dir_ent
Definition: fat_access.h:97
BPB_NUMFATS
#define BPB_NUMFATS
Definition: fat_defs.h:19
fat_string.h
lfn_cache
Definition: fat_misc.h:30
fatfs_lfn_cache_init
void fatfs_lfn_cache_init(struct lfn_cache *lfn, int wipeTable)
Definition: fat_misc.c:38
fatfs_update_file_length
int fatfs_update_file_length(struct fatfs *fs, uint32 Cluster, char *shortname, uint32 fileLength)
Definition: fat_access.c:578
fat_dir_entry
Definition: fat_defs.h:112
fatfs_read_sector
int fatfs_read_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target)
Definition: fat_access.c:263
FAT_HTONS
#define FAT_HTONS(n)
Definition: fat_types.h:45
BPB_FAT32_FATSZ32
#define BPB_FAT32_FATSZ32
Definition: fat_defs.h:37
fatfs_entry_lfn_invalid
int fatfs_entry_lfn_invalid(struct fat_dir_entry *entry)
Definition: fat_misc.c:121
SIGNATURE_POSITION
#define SIGNATURE_POSITION
Definition: fat_defs.h:59
BPB_FATSZ16
#define BPB_FATSZ16
Definition: fat_defs.h:23
FAT32_INVALID_CLUSTER
#define FAT32_INVALID_CLUSTER
Definition: fat_defs.h:109
FATFS_MAX_LONG_FILENAME
#define FATFS_MAX_LONG_FILENAME
Definition: fat_opts.h:19
fatfs_entry_lfn_exists
int fatfs_entry_lfn_exists(struct lfn_cache *lfn, struct fat_dir_entry *entry)
Definition: fat_misc.c:132
time_t
__time_t time_t
Definition: _timespec.h:7
GET_32BIT_WORD
#define GET_32BIT_WORD(buffer, location)
Definition: fat_misc.h:16
fatfs_compare_names
int fatfs_compare_names(char *strA, char *strB)
Definition: fat_string.c:260
SIGNATURE_VALUE
#define SIGNATURE_VALUE
Definition: fat_defs.h:60
BPB_FAT32_FSINFO
#define BPB_FAT32_FSINFO
Definition: fat_defs.h:41
FAT_PRINTF
#define FAT_PRINTF(a)
Definition: fat_opts.h:81
memset
void * memset(void *dst, int c, size_t length)
FAT_INIT_STRUCT_PACKING
#define FAT_INIT_STRUCT_PACKING
Definition: fat_access.h:17
FAT_DIR_ENTRIES_PER_SECTOR
#define FAT_DIR_ENTRIES_PER_SECTOR
Definition: fat_access.h:19
fs_dir_list_status::offset
uint8 offset
Definition: fat_access.h:94
fs_dir_ent::cluster
uint32 cluster
Definition: fat_access.h:101
uint16
unsigned short uint16
Definition: fat_types.h:16
FILE_HEADER_DELETED
#define FILE_HEADER_DELETED
Definition: fat_defs.h:83
GET_16BIT_WORD
#define GET_16BIT_WORD(buffer, location)
Definition: fat_misc.h:17
fatfs_entry_is_dir
int fatfs_entry_is_dir(struct fat_dir_entry *entry)
Definition: fat_misc.c:152
fatfs_fat_init
void fatfs_fat_init(struct fatfs *fs)
Definition: fat_table.c:60
uint32
unsigned long uint32
Definition: fat_types.h:23
access
unsigned char access
Definition: gdt.h:83
strncmp
int strncmp(const char *str1, const char *str2, int len)
BPB_TOTSEC16
#define BPB_TOTSEC16
Definition: fat_defs.h:21
fs_dir_list_status::sector
uint32 sector
Definition: fat_access.h:92
BPB_BYTSPERSEC
#define BPB_BYTSPERSEC
Definition: fat_defs.h:16
FAT_TYPE_16
Definition: fat_access.h:53
fs_dir_ent::size
uint32 size
Definition: fat_access.h:102
fatfs_init
int fatfs_init(struct fatfs *fs)
Definition: fat_access.c:43
fatfs_list_directory_next
int fatfs_list_directory_next(struct fatfs *fs, struct fs_dir_list_status *dirls, struct fs_dir_ent *entry)
Definition: fat_access.c:719
fatfs
Definition: fat_access.h:57
NULL
#define NULL
Definition: fat_string.h:17