UbixOS V2 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 //-----------------------------------------------------------------------------
606 int fl_attach_media(fn_diskio_read rd, fn_diskio_write wr) {
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;
1404 uint32 cluster = FAT32_INVALID_CLUSTER;
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)
1415 cluster = fatfs_get_root_cluster(&_fs);
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