UbixOS  2.0
fat_filelib.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 <stdlib.h>
33 #include <string.h>
34 #include "fat_defs.h"
35 #include "fat_access.h"
36 #include "fat_table.h"
37 #include "fat_write.h"
38 #include "fat_misc.h"
39 #include "fat_string.h"
40 #include "fat_filelib.h"
41 #include "fat_cache.h"
42 
43 //-----------------------------------------------------------------------------
44 // Locals
45 //-----------------------------------------------------------------------------
46 static FL_FILE _files[FATFS_MAX_OPEN_FILES];
47 static int _filelib_init = 0;
48 static int _filelib_valid = 0;
49 static struct fatfs _fs;
50 static struct fat_list _open_file_list;
51 static struct fat_list _free_file_list;
52 
53 //-----------------------------------------------------------------------------
54 // Macros
55 //-----------------------------------------------------------------------------
56 
57 // Macro for checking if file lib is initialised
58 #define CHECK_FL_INIT() { if (_filelib_init==0) fl_init(); }
59 
60 #define FL_LOCK(a) do { if ((a)->fl_lock) (a)->fl_lock(); } while (0)
61 #define FL_UNLOCK(a) do { if ((a)->fl_unlock) (a)->fl_unlock(); } while (0)
62 
63 //-----------------------------------------------------------------------------
64 // Local Functions
65 //-----------------------------------------------------------------------------
66 static void _fl_init();
67 
68 //-----------------------------------------------------------------------------
69 // _allocate_file: Find a slot in the open files buffer for a new file
70 //-----------------------------------------------------------------------------
71 static FL_FILE* _allocate_file(void) {
72  // Allocate free file
73  struct fat_node *node = fat_list_pop_head(&_free_file_list);
74  // Add to open list
75  if (node)
76  fat_list_insert_last(&_open_file_list, node);
77 
78  return fat_list_entry(node, FL_FILE, list_node);
79 }
80 //-----------------------------------------------------------------------------
81 // _check_file_open: Returns true if the file is already open
82 //-----------------------------------------------------------------------------
83 static int _check_file_open(FL_FILE *file) {
84  struct fat_node *node;
85 
86  // Compare open files
87  fat_list_for_each(&_open_file_list, node)
88  {
89  FL_FILE *openFile = fat_list_entry(node, FL_FILE, list_node);
90 
91  // If not the current file
92  if (openFile != file) {
93  // Compare path and name
94  if ((fatfs_compare_names(openFile->path, file->path)) && (fatfs_compare_names(openFile->filename, file->filename)))
95  return 1;
96  }
97  }
98 
99  return 0;
100 }
101 //-----------------------------------------------------------------------------
102 // _free_file: Free open file handle
103 //-----------------------------------------------------------------------------
104 static void _free_file(FL_FILE *file) {
105  // Remove from open list
106  fat_list_remove(&_open_file_list, &file->list_node);
107 
108  // Add to free list
109  fat_list_insert_last(&_free_file_list, &file->list_node);
110 }
111 
112 //-----------------------------------------------------------------------------
113 // Low Level
114 //-----------------------------------------------------------------------------
115 
116 //-----------------------------------------------------------------------------
117 // _open_directory: Cycle through path string to find the start cluster
118 // address of the highest subdir.
119 //-----------------------------------------------------------------------------
120 static int _open_directory(char *path, uint32 *pathCluster) {
121  int levels;
122  int sublevel;
123  char currentfolder[FATFS_MAX_LONG_FILENAME];
124  struct fat_dir_entry sfEntry;
125  uint32 startcluster;
126 
127  // Set starting cluster to root cluster
128  startcluster = fatfs_get_root_cluster(&_fs);
129 
130  // Find number of levels
131  levels = fatfs_total_path_levels(path);
132 
133  // Cycle through each level and get the start sector
134  for (sublevel = 0; sublevel < (levels + 1); sublevel++) {
135  if (fatfs_get_substring(path, sublevel, currentfolder, sizeof(currentfolder)) == -1)
136  return 0;
137 
138  // Find clusteraddress for folder (currentfolder)
139  if (fatfs_get_file_entry(&_fs, startcluster, currentfolder, &sfEntry)) {
140  // Check entry is folder
141  if (fatfs_entry_is_dir(&sfEntry))
142  startcluster = ((FAT_HTONS((uint32 )sfEntry.FstClusHI)) << 16) + FAT_HTONS(sfEntry.FstClusLO);
143  else
144  return 0;
145  }
146  else
147  return 0;
148  }
149 
150  *pathCluster = startcluster;
151  return 1;
152 }
153 //-----------------------------------------------------------------------------
154 // _create_directory: Cycle through path string and create the end directory
155 //-----------------------------------------------------------------------------
156 #if FATFS_INC_WRITE_SUPPORT
157 static int _create_directory(char *path) {
158  FL_FILE *file;
159  struct fat_dir_entry sfEntry;
160  char shortFilename[FAT_SFN_SIZE_FULL];
161  int tailNum = 0;
162  int i;
163 
164  // Allocate a new file handle
165  file = _allocate_file();
166  if (!file)
167  return 0;
168 
169  // Clear filename
170  memset(file->path, '\0', sizeof(file->path));
171  memset(file->filename, '\0', sizeof(file->filename));
172 
173  // Split full path into filename and directory path
174  if (fatfs_split_path((char*) path, file->path, sizeof(file->path), file->filename, sizeof(file->filename)) == -1) {
175  _free_file(file);
176  return 0;
177  }
178 
179  // Check if file already open
180  if (_check_file_open(file)) {
181  _free_file(file);
182  return 0;
183  }
184 
185  // If file is in the root dir
186  if (file->path[0] == 0)
187  file->parentcluster = fatfs_get_root_cluster(&_fs);
188  else {
189  // Find parent directory start cluster
190  if (!_open_directory(file->path, &file->parentcluster)) {
191  _free_file(file);
192  return 0;
193  }
194  }
195 
196  // Check if same filename exists in directory
197  if (fatfs_get_file_entry(&_fs, file->parentcluster, file->filename, &sfEntry) == 1) {
198  _free_file(file);
199  return 0;
200  }
201 
202  file->startcluster = 0;
203 
204  // Create the file space for the folder (at least one clusters worth!)
205  if (!fatfs_allocate_free_space(&_fs, 1, &file->startcluster, 1)) {
206  _free_file(file);
207  return 0;
208  }
209 
210  // Erase new directory cluster
211  memset(file->file_data_sector, 0x00, FAT_SECTOR_SIZE);
212  for (i = 0; i < _fs.sectors_per_cluster; i++) {
213  if (!fatfs_write_sector(&_fs, file->startcluster, i, file->file_data_sector)) {
214  _free_file(file);
215  return 0;
216  }
217  }
218 
219 #if FATFS_INC_LFN_SUPPORT
220 
221  // Generate a short filename & tail
222  tailNum = 0;
223  do {
224  // Create a standard short filename (without tail)
225  fatfs_lfn_create_sfn(shortFilename, file->filename);
226 
227  // If second hit or more, generate a ~n tail
228  if (tailNum != 0)
229  fatfs_lfn_generate_tail((char*) file->shortfilename, shortFilename, tailNum);
230  // Try with no tail if first entry
231  else
232  memcpy(file->shortfilename, shortFilename, FAT_SFN_SIZE_FULL);
233 
234  // Check if entry exists already or not
235  if (fatfs_sfn_exists(&_fs, file->parentcluster, (char*) file->shortfilename) == 0)
236  break;
237 
238  tailNum++;
239  } while (tailNum < 9999);
240 
241  // We reached the max number of duplicate short file names (unlikely!)
242  if (tailNum == 9999) {
243  // Delete allocated space
244  fatfs_free_cluster_chain(&_fs, file->startcluster);
245 
246  _free_file(file);
247  return 0;
248  }
249 #else
250  // Create a standard short filename (without tail)
251  if (!fatfs_lfn_create_sfn(shortFilename, file->filename))
252  {
253  // Delete allocated space
254  fatfs_free_cluster_chain(&_fs, file->startcluster);
255 
256  _free_file(file);
257  return 0;
258  }
259 
260  // Copy to SFN space
261  memcpy(file->shortfilename, shortFilename, FAT_SFN_SIZE_FULL);
262 
263  // Check if entry exists already
264  if (fatfs_sfn_exists(&_fs, file->parentcluster, (char*)file->shortfilename))
265  {
266  // Delete allocated space
267  fatfs_free_cluster_chain(&_fs, file->startcluster);
268 
269  _free_file(file);
270  return 0;
271  }
272 #endif
273 
274  // Add file to disk
275  if (!fatfs_add_file_entry(&_fs, file->parentcluster, (char*) file->filename, (char*) file->shortfilename, file->startcluster, 0, 1)) {
276  // Delete allocated space
277  fatfs_free_cluster_chain(&_fs, file->startcluster);
278 
279  _free_file(file);
280  return 0;
281  }
282 
283  // General
284  file->filelength = 0;
285  file->bytenum = 0;
286  file->file_data_address = 0xFFFFFFFF;
287  file->file_data_dirty = 0;
288  file->filelength_changed = 0;
289 
290  // Quick lookup for next link in the chain
291  file->last_fat_lookup.ClusterIdx = 0xFFFFFFFF;
292  file->last_fat_lookup.CurrentCluster = 0xFFFFFFFF;
293 
294  fatfs_fat_purge(&_fs);
295 
296  _free_file(file);
297  return 1;
298 }
299 #endif
300 //-----------------------------------------------------------------------------
301 // _open_file: Open a file for reading
302 //-----------------------------------------------------------------------------
303 static FL_FILE* _open_file(const char *path) {
304  FL_FILE *file;
305  struct fat_dir_entry sfEntry;
306 
307  // Allocate a new file handle
308  file = _allocate_file();
309  if (!file)
310  return NULL;
311 
312  // Clear filename
313  memset(file->path, '\0', sizeof(file->path));
314  memset(file->filename, '\0', sizeof(file->filename));
315 
316  // Split full path into filename and directory path
317  if (fatfs_split_path((char*) path, file->path, sizeof(file->path), file->filename, sizeof(file->filename)) == -1) {
318  _free_file(file);
319  return NULL;
320  }
321 
322  // Check if file already open
323  if (_check_file_open(file)) {
324  _free_file(file);
325  return NULL;
326  }
327  // If file is in the root dir
328  if (file->path[0] == 0)
329  file->parentcluster = fatfs_get_root_cluster(&_fs);
330  else {
331  // Find parent directory start cluster
332  if (!_open_directory(file->path, &file->parentcluster)) {
333  _free_file(file);
334  return NULL;
335  }
336  }
337  // Using dir cluster address search for filename
338  if (fatfs_get_file_entry(&_fs, file->parentcluster, file->filename, &sfEntry)) {
339  // Make sure entry is file not dir!
340  if (fatfs_entry_is_file(&sfEntry)) {
341  // Initialise file details
342  memcpy(file->shortfilename, sfEntry.Name, FAT_SFN_SIZE_FULL);
343  file->filelength = FAT_HTONL(sfEntry.FileSize);
344  file->bytenum = 0;
345  file->startcluster = ((FAT_HTONS((uint32 )sfEntry.FstClusHI)) << 16) + FAT_HTONS(sfEntry.FstClusLO);
346  file->file_data_address = 0xFFFFFFFF;
347  file->file_data_dirty = 0;
348  file->filelength_changed = 0;
349 
350  // Quick lookup for next link in the chain
351  file->last_fat_lookup.ClusterIdx = 0xFFFFFFFF;
352  file->last_fat_lookup.CurrentCluster = 0xFFFFFFFF;
353 
354  fatfs_cache_init(&_fs, file);
355 
356  fatfs_fat_purge(&_fs);
357 
358  return file;
359  }
360  }
361  _free_file(file);
362  return NULL;
363 }
364 //-----------------------------------------------------------------------------
365 // _create_file: Create a new file
366 //-----------------------------------------------------------------------------
367 #if FATFS_INC_WRITE_SUPPORT
368 static FL_FILE* _create_file(const char *filename) {
369  FL_FILE *file;
370  struct fat_dir_entry sfEntry;
371  char shortFilename[FAT_SFN_SIZE_FULL];
372  int tailNum = 0;
373 
374  // No write access?
375  if (!_fs.disk_io.write_media)
376  return NULL;
377 
378  // Allocate a new file handle
379  file = _allocate_file();
380  if (!file)
381  return NULL;
382 
383  // Clear filename
384  memset(file->path, '\0', sizeof(file->path));
385  memset(file->filename, '\0', sizeof(file->filename));
386 
387  // Split full path into filename and directory path
388  if (fatfs_split_path((char*) filename, file->path, sizeof(file->path), file->filename, sizeof(file->filename)) == -1) {
389  _free_file(file);
390  return NULL;
391  }
392 
393  // Check if file already open
394  if (_check_file_open(file)) {
395  _free_file(file);
396  return NULL;
397  }
398 
399  // If file is in the root dir
400  if (file->path[0] == 0)
401  file->parentcluster = fatfs_get_root_cluster(&_fs);
402  else {
403  // Find parent directory start cluster
404  if (!_open_directory(file->path, &file->parentcluster)) {
405  _free_file(file);
406  return NULL;
407  }
408  }
409 
410  // Check if same filename exists in directory
411  if (fatfs_get_file_entry(&_fs, file->parentcluster, file->filename, &sfEntry) == 1) {
412  _free_file(file);
413  return NULL;
414  }
415 
416  file->startcluster = 0;
417 
418  // Create the file space for the file (at least one clusters worth!)
419  if (!fatfs_allocate_free_space(&_fs, 1, &file->startcluster, 1)) {
420  _free_file(file);
421  return NULL;
422  }
423 
424 #if FATFS_INC_LFN_SUPPORT
425  // Generate a short filename & tail
426  tailNum = 0;
427  do {
428  // Create a standard short filename (without tail)
429  fatfs_lfn_create_sfn(shortFilename, file->filename);
430 
431  // If second hit or more, generate a ~n tail
432  if (tailNum != 0)
433  fatfs_lfn_generate_tail((char*) file->shortfilename, shortFilename, tailNum);
434  // Try with no tail if first entry
435  else
436  memcpy(file->shortfilename, shortFilename, FAT_SFN_SIZE_FULL);
437 
438  // Check if entry exists already or not
439  if (fatfs_sfn_exists(&_fs, file->parentcluster, (char*) file->shortfilename) == 0)
440  break;
441 
442  tailNum++;
443  } while (tailNum < 9999);
444 
445  // We reached the max number of duplicate short file names (unlikely!)
446  if (tailNum == 9999) {
447  // Delete allocated space
448  fatfs_free_cluster_chain(&_fs, file->startcluster);
449 
450  _free_file(file);
451  return NULL;
452  }
453 #else
454  // Create a standard short filename (without tail)
455  if (!fatfs_lfn_create_sfn(shortFilename, file->filename))
456  {
457  // Delete allocated space
458  fatfs_free_cluster_chain(&_fs, file->startcluster);
459 
460  _free_file(file);
461  return NULL;
462  }
463 
464  // Copy to SFN space
465  memcpy(file->shortfilename, shortFilename, FAT_SFN_SIZE_FULL);
466 
467  // Check if entry exists already
468  if (fatfs_sfn_exists(&_fs, file->parentcluster, (char*)file->shortfilename))
469  {
470  // Delete allocated space
471  fatfs_free_cluster_chain(&_fs, file->startcluster);
472 
473  _free_file(file);
474  return NULL;
475  }
476 #endif
477 
478  // Add file to disk
479  if (!fatfs_add_file_entry(&_fs, file->parentcluster, (char*) file->filename, (char*) file->shortfilename, file->startcluster, 0, 0)) {
480  // Delete allocated space
481  fatfs_free_cluster_chain(&_fs, file->startcluster);
482 
483  _free_file(file);
484  return NULL;
485  }
486 
487  // General
488  file->filelength = 0;
489  file->bytenum = 0;
490  file->file_data_address = 0xFFFFFFFF;
491  file->file_data_dirty = 0;
492  file->filelength_changed = 0;
493 
494  // Quick lookup for next link in the chain
495  file->last_fat_lookup.ClusterIdx = 0xFFFFFFFF;
496  file->last_fat_lookup.CurrentCluster = 0xFFFFFFFF;
497 
498  fatfs_cache_init(&_fs, file);
499 
500  fatfs_fat_purge(&_fs);
501 
502  return file;
503 }
504 #endif
505 //-----------------------------------------------------------------------------
506 // _read_sectors: Read sector(s) from disk to file
507 //-----------------------------------------------------------------------------
508 static uint32 _read_sectors(FL_FILE *file, uint32 offset, uint8 *buffer, uint32 count) {
509  uint32 Sector = 0;
510  uint32 ClusterIdx = 0;
511  uint32 Cluster = 0;
512  uint32 i;
513  uint32 lba;
514 
515  // Find cluster index within file & sector with cluster
516  ClusterIdx = offset / _fs.sectors_per_cluster;
517  Sector = offset - (ClusterIdx * _fs.sectors_per_cluster);
518 
519  // Limit number of sectors read to the number remaining in this cluster
520  if ((Sector + count) > _fs.sectors_per_cluster)
521  count = _fs.sectors_per_cluster - Sector;
522 
523  // Quick lookup for next link in the chain
524  if (ClusterIdx == file->last_fat_lookup.ClusterIdx)
525  Cluster = file->last_fat_lookup.CurrentCluster;
526  // Else walk the chain
527  else {
528  // Starting from last recorded cluster?
529  if (ClusterIdx && ClusterIdx == file->last_fat_lookup.ClusterIdx + 1) {
530  i = file->last_fat_lookup.ClusterIdx;
531  Cluster = file->last_fat_lookup.CurrentCluster;
532  }
533  // Start searching from the beginning..
534  else {
535  // Set start of cluster chain to initial value
536  i = 0;
537  Cluster = file->startcluster;
538  }
539 
540  // Follow chain to find cluster to read
541  for (; i < ClusterIdx; i++) {
542  uint32 nextCluster;
543 
544  // Does the entry exist in the cache?
545  if (!fatfs_cache_get_next_cluster(&_fs, file, i, &nextCluster)) {
546  // Scan file linked list to find next entry
547  nextCluster = fatfs_find_next_cluster(&_fs, Cluster);
548 
549  // Push entry into cache
550  fatfs_cache_set_next_cluster(&_fs, file, i, nextCluster);
551  }
552 
553  Cluster = nextCluster;
554  }
555 
556  // Record current cluster lookup details (if valid)
557  if (Cluster != FAT32_LAST_CLUSTER) {
558  file->last_fat_lookup.CurrentCluster = Cluster;
559  file->last_fat_lookup.ClusterIdx = ClusterIdx;
560  }
561  }
562 
563  // If end of cluster chain then return false
564  if (Cluster == FAT32_LAST_CLUSTER)
565  return 0;
566 
567  // Calculate sector address
568  lba = fatfs_lba_of_cluster(&_fs, Cluster) + Sector;
569 
570  // Read sector of file
571  if (fatfs_sector_read(&_fs, lba, buffer, count))
572  return count;
573  else
574  return 0;
575 }
576 
577 //-----------------------------------------------------------------------------
578 // External API
579 //-----------------------------------------------------------------------------
580 
581 //-----------------------------------------------------------------------------
582 // fl_init: Initialise library
583 //-----------------------------------------------------------------------------
584 void fl_init(void) {
585  int i;
586 
587  fat_list_init(&_free_file_list);
588  fat_list_init(&_open_file_list);
589 
590  // Add all file objects to free list
591  for (i = 0; i < FATFS_MAX_OPEN_FILES; i++)
592  fat_list_insert_last(&_free_file_list, &_files[i].list_node);
593 
594  _filelib_init = 1;
595 }
596 //-----------------------------------------------------------------------------
597 // fl_attach_locks:
598 //-----------------------------------------------------------------------------
599 void fl_attach_locks(void (*lock)(void), void (*unlock)(void)) {
600  _fs.fl_lock = lock;
601  _fs.fl_unlock = unlock;
602 }
603 //-----------------------------------------------------------------------------
604 // fl_attach_media:
605 //-----------------------------------------------------------------------------
607  int res;
608 
609  // If first call to library, initialise
610  CHECK_FL_INIT();
611 
612  _fs.disk_io.read_media = rd;
613  _fs.disk_io.write_media = wr;
614 
615  // Initialise FAT parameters
616  if ((res = fatfs_init(&_fs)) != FAT_INIT_OK) {
617  FAT_PRINTF(("FAT_FS: Error could not load FAT details (%d)!\r\n", res));
618  return res;
619  }
620 
621  _filelib_valid = 1;
622  return FAT_INIT_OK;
623 }
624 //-----------------------------------------------------------------------------
625 // fl_shutdown: Call before shutting down system
626 //-----------------------------------------------------------------------------
627 void fl_shutdown(void) {
628  // If first call to library, initialise
629  CHECK_FL_INIT();
630 
631  FL_LOCK(&_fs);
632  fatfs_fat_purge(&_fs);
633  FL_UNLOCK(&_fs);
634 }
635 //-----------------------------------------------------------------------------
636 // fopen: Open or Create a file for reading or writing
637 //-----------------------------------------------------------------------------
638 void* fl_fopen(const char *path, const char *mode) {
639  int i;
640  FL_FILE *file;
641  uint8 flags = 0;
642 
643  // If first call to library, initialise
644  CHECK_FL_INIT();
645 
646  if (!_filelib_valid)
647  return NULL;
648 
649  if (!path || !mode)
650  return NULL;
651 
652  // Supported Modes:
653  // "r" Open a file for reading.
654  // The file must exist.
655  // "w" Create an empty file for writing.
656  // If a file with the same name already exists its content is erased and the file is treated as a new empty file.
657  // "a" Append to a file.
658  // Writing operations append data at the end of the file.
659  // The file is created if it does not exist.
660  // "r+" Open a file for update both reading and writing.
661  // The file must exist.
662  // "w+" Create an empty file for both reading and writing.
663  // If a file with the same name already exists its content is erased and the file is treated as a new empty file.
664  // "a+" Open a file for reading and appending.
665  // All writing operations are performed at the end of the file, protecting the previous content to be overwritten.
666  // You can reposition (fseek, rewind) the internal pointer to anywhere in the file for reading, but writing operations
667  // will move it back to the end of file.
668  // The file is created if it does not exist.
669 
670  for (i = 0; i < (int) strlen(mode); i++) {
671  switch (mode[i]) {
672  case 'r':
673  case 'R':
674  flags |= FILE_READ;
675  break;
676  case 'w':
677  case 'W':
678  flags |= FILE_WRITE;
679  flags |= FILE_ERASE;
680  flags |= FILE_CREATE;
681  break;
682  case 'a':
683  case 'A':
684  flags |= FILE_WRITE;
685  flags |= FILE_APPEND;
686  flags |= FILE_CREATE;
687  break;
688  case '+':
689  if (flags & FILE_READ)
690  flags |= FILE_WRITE;
691  else if (flags & FILE_WRITE) {
692  flags |= FILE_READ;
693  flags |= FILE_ERASE;
694  flags |= FILE_CREATE;
695  }
696  else if (flags & FILE_APPEND) {
697  flags |= FILE_READ;
698  flags |= FILE_WRITE;
699  flags |= FILE_APPEND;
700  flags |= FILE_CREATE;
701  }
702  break;
703  case 'b':
704  case 'B':
705  flags |= FILE_BINARY;
706  break;
707  }
708  }
709 
710  file = NULL;
711 
712 #if FATFS_INC_WRITE_SUPPORT == 0
713  // No write support!
714  flags &= ~(FILE_CREATE | FILE_WRITE | FILE_APPEND);
715 #endif
716 
717  // No write access - remove write/modify flags
718  if (!_fs.disk_io.write_media)
719  flags &= ~(FILE_CREATE | FILE_WRITE | FILE_APPEND);
720 
721  FL_LOCK(&_fs);
722 
723  // Read
724  if (flags & FILE_READ) {
725  file = _open_file(path);
726  }
727 
728  // Create New
729 #if FATFS_INC_WRITE_SUPPORT
730  if (!file && (flags & FILE_CREATE))
731  file = _create_file(path);
732 #endif
733 
734  // Write Existing (and not open due to read or create)
735  if (!(flags & FILE_READ))
736  if ((flags & FILE_CREATE) && !file)
737  if (flags & (FILE_WRITE | FILE_APPEND))
738  file = _open_file(path);
739 
740  if (file)
741  file->flags = flags;
742 
743  FL_UNLOCK(&_fs);
744  return file;
745 }
746 //-----------------------------------------------------------------------------
747 // _write_sectors: Write sector(s) to disk
748 //-----------------------------------------------------------------------------
749 #if FATFS_INC_WRITE_SUPPORT
750 static uint32 _write_sectors(FL_FILE *file, uint32 offset, uint8 *buf, uint32 count) {
751  uint32 SectorNumber = 0;
752  uint32 ClusterIdx = 0;
753  uint32 Cluster = 0;
754  uint32 LastCluster = FAT32_LAST_CLUSTER;
755  uint32 i;
756  uint32 lba;
757  uint32 TotalWriteCount = count;
758 
759  // Find values for Cluster index & sector within cluster
760  ClusterIdx = offset / _fs.sectors_per_cluster;
761  SectorNumber = offset - (ClusterIdx * _fs.sectors_per_cluster);
762 
763  // Limit number of sectors written to the number remaining in this cluster
764  if ((SectorNumber + count) > _fs.sectors_per_cluster)
765  count = _fs.sectors_per_cluster - SectorNumber;
766 
767  // Quick lookup for next link in the chain
768  if (ClusterIdx == file->last_fat_lookup.ClusterIdx)
769  Cluster = file->last_fat_lookup.CurrentCluster;
770  // Else walk the chain
771  else {
772  // Starting from last recorded cluster?
773  if (ClusterIdx && ClusterIdx == file->last_fat_lookup.ClusterIdx + 1) {
774  i = file->last_fat_lookup.ClusterIdx;
775  Cluster = file->last_fat_lookup.CurrentCluster;
776  }
777  // Start searching from the beginning..
778  else {
779  // Set start of cluster chain to initial value
780  i = 0;
781  Cluster = file->startcluster;
782  }
783 
784  // Follow chain to find cluster to read
785  for (; i < ClusterIdx; i++) {
786  uint32 nextCluster;
787 
788  // Does the entry exist in the cache?
789  if (!fatfs_cache_get_next_cluster(&_fs, file, i, &nextCluster)) {
790  // Scan file linked list to find next entry
791  nextCluster = fatfs_find_next_cluster(&_fs, Cluster);
792 
793  // Push entry into cache
794  fatfs_cache_set_next_cluster(&_fs, file, i, nextCluster);
795  }
796 
797  LastCluster = Cluster;
798  Cluster = nextCluster;
799 
800  // Dont keep following a dead end
801  if (Cluster == FAT32_LAST_CLUSTER)
802  break;
803  }
804 
805  // If we have reached the end of the chain, allocate more!
806  if (Cluster == FAT32_LAST_CLUSTER) {
807  // Add some more cluster(s) to the last good cluster chain
808  if (!fatfs_add_free_space(&_fs, &LastCluster, (TotalWriteCount + _fs.sectors_per_cluster - 1) / _fs.sectors_per_cluster))
809  return 0;
810 
811  Cluster = LastCluster;
812  }
813 
814  // Record current cluster lookup details
815  file->last_fat_lookup.CurrentCluster = Cluster;
816  file->last_fat_lookup.ClusterIdx = ClusterIdx;
817  }
818 
819  // Calculate write address
820  lba = fatfs_lba_of_cluster(&_fs, Cluster) + SectorNumber;
821 
822  if (fatfs_sector_write(&_fs, lba, buf, count))
823  return count;
824  else
825  return 0;
826 }
827 #endif
828 //-----------------------------------------------------------------------------
829 // fl_fflush: Flush un-written data to the file
830 //-----------------------------------------------------------------------------
831 int fl_fflush(void *f) {
832 #if FATFS_INC_WRITE_SUPPORT
833  FL_FILE *file = (FL_FILE*) f;
834 
835  // If first call to library, initialise
836  CHECK_FL_INIT();
837 
838  if (file) {
839  FL_LOCK(&_fs);
840 
841  // If some write data still in buffer
842  if (file->file_data_dirty) {
843  // Write back current sector before loading next
844  if (_write_sectors(file, file->file_data_address, file->file_data_sector, 1))
845  file->file_data_dirty = 0;
846  }
847 
848  FL_UNLOCK(&_fs);
849  }
850 #endif
851  return 0;
852 }
853 //-----------------------------------------------------------------------------
854 // fl_fclose: Close an open file
855 //-----------------------------------------------------------------------------
856 void fl_fclose(void *f) {
857  FL_FILE *file = (FL_FILE*) f;
858 
859  // If first call to library, initialise
860  CHECK_FL_INIT();
861 
862  if (file) {
863  FL_LOCK(&_fs);
864 
865  // Flush un-written data to file
866  fl_fflush(f);
867 
868  // File size changed?
869  if (file->filelength_changed) {
870 #if FATFS_INC_WRITE_SUPPORT
871  // Update filesize in directory
872  fatfs_update_file_length(&_fs, file->parentcluster, (char*) file->shortfilename, file->filelength);
873 #endif
874  file->filelength_changed = 0;
875  }
876 
877  file->bytenum = 0;
878  file->filelength = 0;
879  file->startcluster = 0;
880  file->file_data_address = 0xFFFFFFFF;
881  file->file_data_dirty = 0;
882  file->filelength_changed = 0;
883 
884  // Free file handle
885  _free_file(file);
886 
887  fatfs_fat_purge(&_fs);
888 
889  FL_UNLOCK(&_fs);
890  }
891 }
892 //-----------------------------------------------------------------------------
893 // fl_fgetc: Get a character in the stream
894 //-----------------------------------------------------------------------------
895 int fl_fgetc(void *f) {
896  int res;
897  uint8 data = 0;
898 
899  res = fl_fread(&data, 1, 1, f);
900  if (res == 1)
901  return (int) data;
902  else
903  return res;
904 }
905 //-----------------------------------------------------------------------------
906 // fl_fgets: Get a string from a stream
907 //-----------------------------------------------------------------------------
908 char* fl_fgets(char *s, int n, void *f) {
909  int idx = 0;
910 
911  // Space for null terminator?
912  if (n > 0) {
913  // While space (+space for null terminator)
914  while (idx < (n - 1)) {
915  int ch = fl_fgetc(f);
916 
917  // EOF / Error?
918  if (ch < 0)
919  break;
920 
921  // Store character read from stream
922  s[idx++] = (char) ch;
923 
924  // End of line?
925  if (ch == '\n')
926  break;
927  }
928 
929  if (idx > 0)
930  s[idx] = '\0';
931  }
932 
933  return (idx > 0) ? s : 0;
934 }
935 //-----------------------------------------------------------------------------
936 // fl_fread: Read a block of data from the file
937 //-----------------------------------------------------------------------------
938 int fl_fread(void *buffer, int size, int length, void *f) {
939  uint32 sector;
940  uint32 offset;
941  int copyCount;
942  int count = size * length;
943  int bytesRead = 0;
944 
945  FL_FILE *file = (FL_FILE*) f;
946 
947  // If first call to library, initialise
948  CHECK_FL_INIT();
949 
950  if (buffer == NULL || file == NULL)
951  return -1;
952 
953  // No read permissions
954  if (!(file->flags & FILE_READ))
955  return -1;
956 
957  // Nothing to be done
958  if (!count)
959  return 0;
960 
961  // Check if read starts past end of file
962  if (file->bytenum >= file->filelength)
963  return -1;
964 
965  // Limit to file size
966  if ((file->bytenum + count) > file->filelength)
967  count = file->filelength - file->bytenum;
968 
969  // Calculate start sector
970  sector = file->bytenum / FAT_SECTOR_SIZE;
971 
972  // Offset to start copying data from first sector
973  offset = file->bytenum % FAT_SECTOR_SIZE;
974 
975  while (bytesRead < count) {
976  // Read whole sector, read from media directly into target buffer
977  if ((offset == 0) && ((count - bytesRead) >= FAT_SECTOR_SIZE)) {
978  // Read as many sectors as possible into target buffer
979  uint32 sectorsRead = _read_sectors(file, sector, (uint8*) ((uint8*) buffer + bytesRead), (count - bytesRead) / FAT_SECTOR_SIZE);
980  if (sectorsRead) {
981  // We have upto one sector to copy
982  copyCount = FAT_SECTOR_SIZE * sectorsRead;
983 
984  // Move onto next sector and reset copy offset
985  sector += sectorsRead;
986  offset = 0;
987  }
988  else
989  break;
990  }
991  else {
992  // Do we need to re-read the sector?
993  if (file->file_data_address != sector) {
994  // Flush un-written data to file
995  if (file->file_data_dirty)
996  fl_fflush(file);
997 
998  // Get LBA of sector offset within file
999  if (!_read_sectors(file, sector, file->file_data_sector, 1))
1000  // Read failed - out of range (probably)
1001  break;
1002 
1003  file->file_data_address = sector;
1004  file->file_data_dirty = 0;
1005  }
1006 
1007  // We have upto one sector to copy
1008  copyCount = FAT_SECTOR_SIZE - offset;
1009 
1010  // Only require some of this sector?
1011  if (copyCount > (count - bytesRead))
1012  copyCount = (count - bytesRead);
1013 
1014  // Copy to application buffer
1015  memcpy((uint8*) ((uint8*) buffer + bytesRead), (uint8*) (file->file_data_sector + offset), copyCount);
1016 
1017  // Move onto next sector and reset copy offset
1018  sector++;
1019  offset = 0;
1020  }
1021 
1022  // Increase total read count
1023  bytesRead += copyCount;
1024 
1025  // Increment file pointer
1026  file->bytenum += copyCount;
1027  }
1028 
1029  return bytesRead;
1030 }
1031 //-----------------------------------------------------------------------------
1032 // fl_fseek: Seek to a specific place in the file
1033 //-----------------------------------------------------------------------------
1034 int fl_fseek(void *f, long offset, int origin) {
1035  FL_FILE *file = (FL_FILE*) f;
1036  int res = -1;
1037 
1038  // If first call to library, initialise
1039  CHECK_FL_INIT();
1040 
1041  if (!file)
1042  return -1;
1043 
1044  if (origin == SEEK_END && offset != 0)
1045  return -1;
1046 
1047  FL_LOCK(&_fs);
1048 
1049  // Invalidate file buffer
1050  file->file_data_address = 0xFFFFFFFF;
1051  file->file_data_dirty = 0;
1052 
1053  if (origin == SEEK_SET) {
1054  file->bytenum = (uint32) offset;
1055 
1056  if (file->bytenum > file->filelength)
1057  file->bytenum = file->filelength;
1058 
1059  res = 0;
1060  }
1061  else if (origin == SEEK_CUR) {
1062  // Positive shift
1063  if (offset >= 0) {
1064  file->bytenum += offset;
1065 
1066  if (file->bytenum > file->filelength)
1067  file->bytenum = file->filelength;
1068  }
1069  // Negative shift
1070  else {
1071  // Make shift positive
1072  offset = -offset;
1073 
1074  // Limit to negative shift to start of file
1075  if ((uint32) offset > file->bytenum)
1076  file->bytenum = 0;
1077  else
1078  file->bytenum -= offset;
1079  }
1080 
1081  res = 0;
1082  }
1083  else if (origin == SEEK_END) {
1084  file->bytenum = file->filelength;
1085  res = 0;
1086  }
1087  else
1088  res = -1;
1089 
1090  FL_UNLOCK(&_fs);
1091 
1092  return res;
1093 }
1094 //-----------------------------------------------------------------------------
1095 // fl_fgetpos: Get the current file position
1096 //-----------------------------------------------------------------------------
1097 int fl_fgetpos(void *f, uint32 *position) {
1098  FL_FILE *file = (FL_FILE*) f;
1099 
1100  if (!file)
1101  return -1;
1102 
1103  FL_LOCK(&_fs);
1104 
1105  // Get position
1106  *position = file->bytenum;
1107 
1108  FL_UNLOCK(&_fs);
1109 
1110  return 0;
1111 }
1112 //-----------------------------------------------------------------------------
1113 // fl_ftell: Get the current file position
1114 //-----------------------------------------------------------------------------
1115 long fl_ftell(void *f) {
1116  uint32 pos = 0;
1117 
1118  fl_fgetpos(f, &pos);
1119 
1120  return (long) pos;
1121 }
1122 //-----------------------------------------------------------------------------
1123 // fl_feof: Is the file pointer at the end of the stream?
1124 //-----------------------------------------------------------------------------
1125 int fl_feof(void *f) {
1126  FL_FILE *file = (FL_FILE*) f;
1127  int res;
1128 
1129  if (!file)
1130  return -1;
1131 
1132  FL_LOCK(&_fs);
1133 
1134  if (file->bytenum == file->filelength)
1135  res = EOF;
1136  else
1137  res = 0;
1138 
1139  FL_UNLOCK(&_fs);
1140 
1141  return res;
1142 }
1143 //-----------------------------------------------------------------------------
1144 // fl_fputc: Write a character to the stream
1145 //-----------------------------------------------------------------------------
1146 #if FATFS_INC_WRITE_SUPPORT
1147 int fl_fputc(int c, void *f) {
1148  uint8 data = (uint8) c;
1149  int res;
1150 
1151  res = fl_fwrite(&data, 1, 1, f);
1152  if (res == 1)
1153  return c;
1154  else
1155  return res;
1156 }
1157 #endif
1158 //-----------------------------------------------------------------------------
1159 // fl_fwrite: Write a block of data to the stream
1160 //-----------------------------------------------------------------------------
1161 #if FATFS_INC_WRITE_SUPPORT
1162 int fl_fwrite(const void *data, int size, int count, void *f) {
1163  FL_FILE *file = (FL_FILE*) f;
1164  uint32 sector;
1165  uint32 offset;
1166  uint32 length = (size * count);
1167  uint8 *buffer = (uint8*) data;
1168  uint32 bytesWritten = 0;
1169  uint32 copyCount;
1170 
1171  // If first call to library, initialise
1172  CHECK_FL_INIT();
1173 
1174  if (!file)
1175  return -1;
1176 
1177  FL_LOCK(&_fs);
1178 
1179  // No write permissions
1180  if (!(file->flags & FILE_WRITE)) {
1181  FL_UNLOCK(&_fs);
1182  return -1;
1183  }
1184 
1185  // Append writes to end of file
1186  if (file->flags & FILE_APPEND)
1187  file->bytenum = file->filelength;
1188  // Else write to current position
1189 
1190  // Calculate start sector
1191  sector = file->bytenum / FAT_SECTOR_SIZE;
1192 
1193  // Offset to start copying data from first sector
1194  offset = file->bytenum % FAT_SECTOR_SIZE;
1195 
1196  while (bytesWritten < length) {
1197  // Whole sector or more to be written?
1198  if ((offset == 0) && ((length - bytesWritten) >= FAT_SECTOR_SIZE)) {
1199  uint32 sectorsWrote;
1200 
1201  // Buffered sector, flush back to disk
1202  if (file->file_data_address != 0xFFFFFFFF) {
1203  // Flush un-written data to file
1204  if (file->file_data_dirty)
1205  fl_fflush(file);
1206 
1207  file->file_data_address = 0xFFFFFFFF;
1208  file->file_data_dirty = 0;
1209  }
1210 
1211  // Write as many sectors as possible
1212  sectorsWrote = _write_sectors(file, sector, (uint8*) (buffer + bytesWritten), (length - bytesWritten) / FAT_SECTOR_SIZE);
1213  copyCount = FAT_SECTOR_SIZE * sectorsWrote;
1214 
1215  // Increase total read count
1216  bytesWritten += copyCount;
1217 
1218  // Increment file pointer
1219  file->bytenum += copyCount;
1220 
1221  // Move onto next sector and reset copy offset
1222  sector += sectorsWrote;
1223  offset = 0;
1224 
1225  if (!sectorsWrote)
1226  break;
1227  }
1228  else {
1229  // We have upto one sector to copy
1230  copyCount = FAT_SECTOR_SIZE - offset;
1231 
1232  // Only require some of this sector?
1233  if (copyCount > (length - bytesWritten))
1234  copyCount = (length - bytesWritten);
1235 
1236  // Do we need to read a new sector?
1237  if (file->file_data_address != sector) {
1238  // Flush un-written data to file
1239  if (file->file_data_dirty)
1240  fl_fflush(file);
1241 
1242  // If we plan to overwrite the whole sector, we don't need to read it first!
1243  if (copyCount != FAT_SECTOR_SIZE) {
1244  // NOTE: This does not have succeed; if last sector of file
1245  // reached, no valid data will be read in, but write will
1246  // allocate some more space for new data.
1247 
1248  // Get LBA of sector offset within file
1249  if (!_read_sectors(file, sector, file->file_data_sector, 1))
1250  memset(file->file_data_sector, 0x00, FAT_SECTOR_SIZE);
1251  }
1252 
1253  file->file_data_address = sector;
1254  file->file_data_dirty = 0;
1255  }
1256 
1257  // Copy from application buffer into sector buffer
1258  memcpy((uint8*) (file->file_data_sector + offset), (uint8*) (buffer + bytesWritten), copyCount);
1259 
1260  // Mark buffer as dirty
1261  file->file_data_dirty = 1;
1262 
1263  // Increase total read count
1264  bytesWritten += copyCount;
1265 
1266  // Increment file pointer
1267  file->bytenum += copyCount;
1268 
1269  // Move onto next sector and reset copy offset
1270  sector++;
1271  offset = 0;
1272  }
1273  }
1274 
1275  // Write increased extent of the file?
1276  if (file->bytenum > file->filelength) {
1277  // Increase file size to new point
1278  file->filelength = file->bytenum;
1279 
1280  // We are changing the file length and this
1281  // will need to be writen back at some point
1282  file->filelength_changed = 1;
1283  }
1284 
1285 #if FATFS_INC_TIME_DATE_SUPPORT
1286  // If time & date support is enabled, always force directory entry to be
1287  // written in-order to update file modify / access time & date.
1288  file->filelength_changed = 1;
1289 #endif
1290 
1291  FL_UNLOCK(&_fs);
1292 
1293  return (size * count);
1294 }
1295 #endif
1296 //-----------------------------------------------------------------------------
1297 // fl_fputs: Write a character string to the stream
1298 //-----------------------------------------------------------------------------
1299 #if FATFS_INC_WRITE_SUPPORT
1300 int fl_fputs(const char *str, void *f) {
1301  int len = (int) strlen(str);
1302  int res = fl_fwrite(str, 1, len, f);
1303 
1304  if (res == len)
1305  return len;
1306  else
1307  return res;
1308 }
1309 #endif
1310 //-----------------------------------------------------------------------------
1311 // fl_remove: Remove a file from the filesystem
1312 //-----------------------------------------------------------------------------
1313 #if FATFS_INC_WRITE_SUPPORT
1314 int fl_remove(const char *filename) {
1315  FL_FILE *file;
1316  int res = -1;
1317 
1318  FL_LOCK(&_fs);
1319 
1320  // Use read_file as this will check if the file is already open!
1321  file = fl_fopen((char*) filename, "r");
1322  if (file) {
1323  // Delete allocated space
1324  if (fatfs_free_cluster_chain(&_fs, file->startcluster)) {
1325  // Remove directory entries
1326  if (fatfs_mark_file_deleted(&_fs, file->parentcluster, (char*) file->shortfilename)) {
1327  // Close the file handle (this should not write anything to the file
1328  // as we have not changed the file since opening it!)
1329  fl_fclose(file);
1330 
1331  res = 0;
1332  }
1333  }
1334  }
1335 
1336  FL_UNLOCK(&_fs);
1337 
1338  return res;
1339 }
1340 #endif
1341 //-----------------------------------------------------------------------------
1342 // fl_createdirectory: Create a directory based on a path
1343 //-----------------------------------------------------------------------------
1344 #if FATFS_INC_WRITE_SUPPORT
1345 int fl_createdirectory(const char *path) {
1346  int res;
1347 
1348  // If first call to library, initialise
1349  CHECK_FL_INIT();
1350 
1351  FL_LOCK(&_fs);
1352  res = _create_directory((char*) path);
1353  FL_UNLOCK(&_fs);
1354 
1355  return res;
1356 }
1357 #endif
1358 //-----------------------------------------------------------------------------
1359 // fl_listdirectory: List a directory based on a path
1360 //-----------------------------------------------------------------------------
1361 #if FATFS_DIR_LIST_SUPPORT
1362 void fl_listdirectory(const char *path) {
1363  FL_DIR dirstat;
1364 
1365  // If first call to library, initialise
1366  CHECK_FL_INIT();
1367 
1368  FL_LOCK(&_fs);
1369 
1370  FAT_PRINTF(("\r\nDirectory %s\r\n", path));
1371 
1372  if (fl_opendir(path, &dirstat)) {
1373  struct fs_dir_ent dirent;
1374 
1375  while (fl_readdir(&dirstat, &dirent) == 0) {
1376 #if FATFS_INC_TIME_DATE_SUPPORT
1377  int d,m,y,h,mn,s;
1378  fatfs_convert_from_fat_time(dirent.write_time, &h,&m,&s);
1379  fatfs_convert_from_fat_date(dirent.write_date, &d,&mn,&y);
1380  FAT_PRINTF(("%02d/%02d/%04d %02d:%02d ", d,mn,y,h,m));
1381 #endif
1382 
1383  if (dirent.is_dir) {
1384  FAT_PRINTF(("%s <DIR>\r\n", dirent.filename));
1385  }
1386  else {
1387  FAT_PRINTF(("%s [%d bytes]\r\n", dirent.filename, dirent.size));
1388  }
1389  }
1390 
1391  fl_closedir(&dirstat);
1392  }
1393 
1394  FL_UNLOCK(&_fs);
1395 }
1396 #endif
1397 //-----------------------------------------------------------------------------
1398 // fl_opendir: Opens a directory for listing
1399 //-----------------------------------------------------------------------------
1400 #if FATFS_DIR_LIST_SUPPORT
1401 FL_DIR* fl_opendir(const char *path, FL_DIR *dir) {
1402  int levels;
1403  int res = 1;
1405 
1406  // If first call to library, initialise
1407  CHECK_FL_INIT();
1408 
1409  FL_LOCK(&_fs);
1410 
1411  levels = fatfs_total_path_levels((char*) path) + 1;
1412 
1413  // If path is in the root dir
1414  if (levels == 0)
1416  // Find parent directory start cluster
1417  else
1418  res = _open_directory((char*) path, &cluster);
1419 
1420  if (res)
1421  fatfs_list_directory_start(&_fs, dir, cluster);
1422 
1423  FL_UNLOCK(&_fs);
1424 
1425  return cluster != FAT32_INVALID_CLUSTER ? dir : 0;
1426 }
1427 #endif
1428 //-----------------------------------------------------------------------------
1429 // fl_readdir: Get next item in directory
1430 //-----------------------------------------------------------------------------
1431 #if FATFS_DIR_LIST_SUPPORT
1432 int fl_readdir(FL_DIR *dirls, fl_dirent *entry) {
1433  int res = 0;
1434 
1435  // If first call to library, initialise
1436  CHECK_FL_INIT();
1437 
1438  FL_LOCK(&_fs);
1439 
1440  res = fatfs_list_directory_next(&_fs, dirls, entry);
1441 
1442  FL_UNLOCK(&_fs);
1443 
1444  return res ? 0 : -1;
1445 }
1446 #endif
1447 //-----------------------------------------------------------------------------
1448 // fl_closedir: Close directory after listing
1449 //-----------------------------------------------------------------------------
1450 #if FATFS_DIR_LIST_SUPPORT
1451 int fl_closedir(FL_DIR *dir) {
1452  // Not used
1453  return 0;
1454 }
1455 #endif
1456 //-----------------------------------------------------------------------------
1457 // fl_is_dir: Is this a directory?
1458 //-----------------------------------------------------------------------------
1459 #if FATFS_DIR_LIST_SUPPORT
1460 int fl_is_dir(const char *path) {
1461  int res = 0;
1462  FL_DIR dir;
1463 
1464  if (fl_opendir(path, &dir)) {
1465  res = 1;
1466  fl_closedir(&dir);
1467  }
1468 
1469  return res;
1470 }
1471 #endif
1472 //-----------------------------------------------------------------------------
1473 // fl_format: Format a partition with either FAT16 or FAT32 based on size
1474 //-----------------------------------------------------------------------------
1475 #if FATFS_INC_FORMAT_SUPPORT
1476 int fl_format(uint32 volume_sectors, const char *name) {
1477  return fatfs_format(&_fs, volume_sectors, name);
1478 }
1479 #endif /*FATFS_INC_FORMAT_SUPPORT*/
1480 //-----------------------------------------------------------------------------
1481 // fl_get_fs:
1482 //-----------------------------------------------------------------------------
1483 #ifdef FATFS_INC_TEST_HOOKS
1484 struct fatfs* fl_get_fs(void)
1485 {
1486  return &_fs;
1487 }
1488 #endif
fl_createdirectory
int fl_createdirectory(const char *path)
Definition: fat_filelib.c:1345
fatfs_cache_set_next_cluster
int fatfs_cache_set_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 nextCluster)
Definition: fat_cache.c:76
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
file
fileDescriptor * file
Definition: tcpdump.c:45
fat_access.h
fatfs::fl_lock
void(* fl_lock)(void)
Definition: fat_access.h:79
fat_cache.h
fat_table.h
fl_fclose
void fl_fclose(void *f)
Definition: fat_filelib.c:856
buffer
char * buffer
Definition: shell.c:47
disk_if::write_media
fn_diskio_write write_media
Definition: fat_access.h:34
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
fatfs_add_file_entry
int fatfs_add_file_entry(struct fatfs *fs, uint32 dirCluster, char *filename, char *shortfilename, uint32 startCluster, uint32 size, int dir)
Definition: fat_write.c:266
FL_LOCK
#define FL_LOCK(a)
Definition: fat_filelib.c:60
fat_list_for_each
#define fat_list_for_each(l, p)
Definition: fat_list.h:37
FAT32_LAST_CLUSTER
#define FAT32_LAST_CLUSTER
Definition: fat_defs.h:108
fat_node
Definition: fat_list.h:17
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
fl_remove
int fl_remove(const char *filename)
Definition: fat_filelib.c:1314
disk_if::read_media
fn_diskio_read read_media
Definition: fat_access.h:33
file
Definition: descrip.h:67
SEEK_END
#define SEEK_END
Definition: fat_filelib.h:16
fatfs_entry_is_file
int fatfs_entry_is_file(struct fat_dir_entry *entry)
Definition: fat_misc.c:161
sFL_FILE::path
char path[260]
Definition: fat_filelib.h:45
fl_readdir
int fl_readdir(FL_DIR *dirls, fl_dirent *entry)
Definition: fat_filelib.c:1432
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
fl_fwrite
int fl_fwrite(const void *data, int size, int count, void *f)
Definition: fat_filelib.c:1162
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_filelib.h
strlen
int strlen(const char *str)
Definition: strlen.c:55
fl_fgetc
int fl_fgetc(void *f)
Definition: fat_filelib.c:895
fl_init
void fl_init(void)
Definition: fat_filelib.c:584
FILE_APPEND
#define FILE_APPEND
Definition: fat_filelib.h:66
FILE_ERASE
#define FILE_ERASE
Definition: fat_filelib.h:68
fatfs_get_substring
int fatfs_get_substring(char *path, int levelreq, char *output, int max_len)
Definition: fat_string.c:92
FAT_HTONL
#define FAT_HTONL(n)
Definition: fat_types.h:46
FILE_READ
#define FILE_READ
Definition: fat_filelib.h:64
fat_defs.h
memcpy
void * memcpy(const void *dst, const void *src, size_t length)
fl_is_dir
int fl_is_dir(const char *path)
Definition: fat_filelib.c:1460
fatfs::sectors_per_cluster
uint8 sectors_per_cluster
Definition: fat_access.h:60
EOF
#define EOF
Definition: fat_filelib.h:24
fatfs_cache_init
int fatfs_cache_init(struct fatfs *fs, FL_FILE *file)
Definition: fat_cache.c:42
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
fatfs_write_sector
int fatfs_write_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target)
Definition: fat_access.c:311
fl_attach_locks
void fl_attach_locks(void(*lock)(void), void(*unlock)(void))
Definition: fat_filelib.c:599
FILE_WRITE
#define FILE_WRITE
Definition: fat_filelib.h:65
FAT_SFN_SIZE_FULL
#define FAT_SFN_SIZE_FULL
Definition: fat_defs.h:68
FAT_SECTOR_SIZE
#define FAT_SECTOR_SIZE
Definition: fat_opts.h:70
fat_list
Definition: fat_list.h:23
FL_UNLOCK
#define FL_UNLOCK(a)
Definition: fat_filelib.c:61
fl_fgets
char * fl_fgets(char *s, int n, void *f)
Definition: fat_filelib.c:908
fatfs_free_cluster_chain
int fatfs_free_cluster_chain(struct fatfs *fs, uint32 start_cluster)
Definition: fat_table.c:389
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
fatfs_convert_from_fat_time
void fatfs_convert_from_fat_time(uint16 fat_time, int *hours, int *minutes, int *seconds)
dirent
Definition: ufs.h:92
fs_dir_ent
Definition: fat_access.h:97
buf
Definition: buf.h:35
fl_opendir
FL_DIR * fl_opendir(const char *path, FL_DIR *dir)
Definition: fat_filelib.c:1401
fl_fputc
int fl_fputc(int c, void *f)
Definition: fat_filelib.c:1147
fat_string.h
fl_listdirectory
void fl_listdirectory(const char *path)
Definition: fat_filelib.c:1362
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
FAT_HTONS
#define FAT_HTONS(n)
Definition: fat_types.h:45
CHECK_FL_INIT
#define CHECK_FL_INIT()
Definition: fat_filelib.c:58
FAT32_INVALID_CLUSTER
#define FAT32_INVALID_CLUSTER
Definition: fat_defs.h:109
fl_ftell
long fl_ftell(void *f)
Definition: fat_filelib.c:1115
fl_fflush
int fl_fflush(void *f)
Definition: fat_filelib.c:831
FATFS_MAX_LONG_FILENAME
#define FATFS_MAX_LONG_FILENAME
Definition: fat_opts.h:19
fl_fgetpos
int fl_fgetpos(void *f, uint32 *position)
Definition: fat_filelib.c:1097
fn_diskio_write
int(* fn_diskio_write)(uint32 sector, uint8 *buffer, uint32 sector_count)
Definition: fat_access.h:25
fl_fread
int fl_fread(void *buffer, int size, int length, void *f)
Definition: fat_filelib.c:938
fatfs_add_free_space
int fatfs_add_free_space(struct fatfs *fs, uint32 *startCluster, uint32 clusters)
Definition: fat_write.c:45
name
const char * name
Definition: pci.c:37
fl_fopen
void * fl_fopen(const char *path, const char *mode)
Definition: fat_filelib.c:638
fatfs::fl_unlock
void(* fl_unlock)(void)
Definition: fat_access.h:80
fatfs::disk_io
struct disk_if disk_io
Definition: fat_access.h:76
fatfs_split_path
int fatfs_split_path(char *full_path, char *path, int max_path, char *filename, int max_filename)
Definition: fat_string.c:151
sFL_FILE
Definition: fat_filelib.h:38
fatfs_compare_names
int fatfs_compare_names(char *strA, char *strB)
Definition: fat_string.c:260
SEEK_CUR
#define SEEK_CUR
Definition: fat_filelib.h:12
FAT_PRINTF
#define FAT_PRINTF(a)
Definition: fat_opts.h:81
sFL_FILE::filename
char filename[260]
Definition: fat_filelib.h:46
FATFS_MAX_OPEN_FILES
#define FATFS_MAX_OPEN_FILES
Definition: fat_opts.h:24
fat_list_entry
#define fat_list_entry(p, t, m)
Definition: fat_list.h:32
memset
void * memset(void *dst, int c, size_t length)
fatfs_allocate_free_space
int fatfs_allocate_free_space(struct fatfs *fs, int newFile, uint32 *startCluster, uint32 size)
Definition: fat_write.c:82
fl_feof
int fl_feof(void *f)
Definition: fat_filelib.c:1125
fs_dir_ent::cluster
uint32 cluster
Definition: fat_access.h:101
FILE_BINARY
#define FILE_BINARY
Definition: fat_filelib.h:67
fatfs_entry_is_dir
int fatfs_entry_is_dir(struct fat_dir_entry *entry)
Definition: fat_misc.c:152
uint32
unsigned long uint32
Definition: fat_types.h:23
fl_closedir
int fl_closedir(FL_DIR *dir)
Definition: fat_filelib.c:1451
fatfs_lfn_generate_tail
int fatfs_lfn_generate_tail(char *sfn_output, char *sfn_input, uint32 tailNum)
Definition: fat_misc.c:346
fatfs_cache_get_next_cluster
int fatfs_cache_get_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 *pNextCluster)
Definition: fat_cache.c:59
fatfs_convert_from_fat_date
void fatfs_convert_from_fat_date(uint16 fat_date, int *day, int *month, int *year)
fl_fseek
int fl_fseek(void *f, long offset, int origin)
Definition: fat_filelib.c:1034
fatfs_fat_purge
int fatfs_fat_purge(struct fatfs *fs)
Definition: fat_table.c:179
fatfs_format
int fatfs_format(struct fatfs *fs, uint32 volume_sectors, const char *name)
Definition: fat_format.c:524
fl_shutdown
void fl_shutdown(void)
Definition: fat_filelib.c:627
fl_attach_media
int fl_attach_media(fn_diskio_read rd, fn_diskio_write wr)
Definition: fat_filelib.c:606
SEEK_SET
#define SEEK_SET
Definition: fat_filelib.h:20
fatfs_init
int fatfs_init(struct fatfs *fs)
Definition: fat_access.c:43
fl_format
int fl_format(uint32 volume_sectors, const char *name)
Definition: fat_filelib.c:1476
FILE_CREATE
#define FILE_CREATE
Definition: fat_filelib.h:69
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
fn_diskio_read
int(* fn_diskio_read)(uint32 sector, uint8 *buffer, uint32 sector_count)
Definition: fat_access.h:24
fl_fputs
int fl_fputs(const char *str, void *f)
Definition: fat_filelib.c:1300
fatfs
Definition: fat_access.h:57
fatfs_total_path_levels
int fatfs_total_path_levels(char *path)
Definition: fat_string.c:44
fatfs_lfn_create_sfn
int fatfs_lfn_create_sfn(char *sfn_output, char *filename)
Definition: fat_misc.c:260
NULL
#define NULL
Definition: fat_string.h:17