]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - vtoycli/fat_io_lib/release/fat_filelib.c
1 //-----------------------------------------------------------------------------
2 //-----------------------------------------------------------------------------
3 // FAT16/32 File IO Library
6 // Copyright 2003 - 2012
8 // Email: admin@ultra-embedded.com
11 // If you would like a version with a more permissive license for use in
12 // closed source commercial applications please contact me for details.
13 //-----------------------------------------------------------------------------
15 // This file is part of FAT File IO Library.
17 // FAT File IO Library is free software; you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation; either version 2 of the License, or
20 // (at your option) any later version.
22 // FAT File IO Library is distributed in the hope that it will be useful,
23 // but WITHOUT ANY WARRANTY; without even the implied warranty of
24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 // GNU General Public License for more details.
27 // You should have received a copy of the GNU General Public License
28 // along with FAT File IO Library; if not, write to the Free Software
29 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 //-----------------------------------------------------------------------------
31 //-----------------------------------------------------------------------------
35 #include "fat_access.h"
36 #include "fat_table.h"
37 #include "fat_write.h"
39 #include "fat_string.h"
40 #include "fat_filelib.h"
41 #include "fat_cache.h"
43 //-----------------------------------------------------------------------------
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
;
53 //-----------------------------------------------------------------------------
55 //-----------------------------------------------------------------------------
57 // Macro for checking if file lib is initialised
58 #define CHECK_FL_INIT() { if (_filelib_init==0) fl_init(); }
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)
63 //-----------------------------------------------------------------------------
65 //-----------------------------------------------------------------------------
66 static void _fl_init();
68 //-----------------------------------------------------------------------------
69 // _allocate_file: Find a slot in the open files buffer for a new file
70 //-----------------------------------------------------------------------------
71 static FL_FILE
* _allocate_file(void)
74 struct fat_node
*node
= fat_list_pop_head(&_free_file_list
);
78 fat_list_insert_last(&_open_file_list
, node
);
80 return fat_list_entry(node
, FL_FILE
, list_node
);
82 //-----------------------------------------------------------------------------
83 // _check_file_open: Returns true if the file is already open
84 //-----------------------------------------------------------------------------
85 static int _check_file_open(FL_FILE
* file
)
87 struct fat_node
*node
;
90 fat_list_for_each(&_open_file_list
, node
)
92 FL_FILE
* openFile
= fat_list_entry(node
, FL_FILE
, list_node
);
94 // If not the current file
97 // Compare path and name
98 if ( (fatfs_compare_names(openFile
->path
,file
->path
)) && (fatfs_compare_names(openFile
->filename
,file
->filename
)) )
105 //-----------------------------------------------------------------------------
106 // _free_file: Free open file handle
107 //-----------------------------------------------------------------------------
108 static void _free_file(FL_FILE
* file
)
110 // Remove from open list
111 fat_list_remove(&_open_file_list
, &file
->list_node
);
114 fat_list_insert_last(&_free_file_list
, &file
->list_node
);
117 //-----------------------------------------------------------------------------
119 //-----------------------------------------------------------------------------
121 //-----------------------------------------------------------------------------
122 // _open_directory: Cycle through path string to find the start cluster
123 // address of the highest subdir.
124 //-----------------------------------------------------------------------------
125 static int _open_directory(char *path
, uint32
*pathCluster
)
129 char currentfolder
[FATFS_MAX_LONG_FILENAME
];
130 struct fat_dir_entry sfEntry
;
133 // Set starting cluster to root cluster
134 startcluster
= fatfs_get_root_cluster(&_fs
);
136 // Find number of levels
137 levels
= fatfs_total_path_levels(path
);
139 // Cycle through each level and get the start sector
140 for (sublevel
=0;sublevel
<(levels
+1);sublevel
++)
142 if (fatfs_get_substring(path
, sublevel
, currentfolder
, sizeof(currentfolder
)) == -1)
145 // Find clusteraddress for folder (currentfolder)
146 if (fatfs_get_file_entry(&_fs
, startcluster
, currentfolder
,&sfEntry
))
148 // Check entry is folder
149 if (fatfs_entry_is_dir(&sfEntry
))
150 startcluster
= ((FAT_HTONS((uint32
)sfEntry
.FstClusHI
))<<16) + FAT_HTONS(sfEntry
.FstClusLO
);
158 *pathCluster
= startcluster
;
161 //-----------------------------------------------------------------------------
162 // _create_directory: Cycle through path string and create the end directory
163 //-----------------------------------------------------------------------------
164 #if FATFS_INC_WRITE_SUPPORT
165 static int _create_directory(char *path
)
168 struct fat_dir_entry sfEntry
;
169 char shortFilename
[FAT_SFN_SIZE_FULL
];
173 // Allocate a new file handle
174 file
= _allocate_file();
179 memset(file
->path
, '\0', sizeof(file
->path
));
180 memset(file
->filename
, '\0', sizeof(file
->filename
));
182 // Split full path into filename and directory path
183 if (fatfs_split_path((char*)path
, file
->path
, sizeof(file
->path
), file
->filename
, sizeof(file
->filename
)) == -1)
189 // Check if file already open
190 if (_check_file_open(file
))
196 // If file is in the root dir
197 if (file
->path
[0] == 0)
198 file
->parentcluster
= fatfs_get_root_cluster(&_fs
);
201 // Find parent directory start cluster
202 if (!_open_directory(file
->path
, &file
->parentcluster
))
209 // Check if same filename exists in directory
210 if (fatfs_get_file_entry(&_fs
, file
->parentcluster
, file
->filename
,&sfEntry
) == 1)
216 file
->startcluster
= 0;
218 // Create the file space for the folder (at least one clusters worth!)
219 if (!fatfs_allocate_free_space(&_fs
, 1, &file
->startcluster
, 1))
225 // Erase new directory cluster
226 memset(file
->file_data_sector
, 0x00, FAT_SECTOR_SIZE
);
227 for (i
=0;i
<_fs
.sectors_per_cluster
;i
++)
229 if (!fatfs_write_sector(&_fs
, file
->startcluster
, i
, file
->file_data_sector
))
236 #if FATFS_INC_LFN_SUPPORT
238 // Generate a short filename & tail
242 // Create a standard short filename (without tail)
243 fatfs_lfn_create_sfn(shortFilename
, file
->filename
);
245 // If second hit or more, generate a ~n tail
247 fatfs_lfn_generate_tail((char*)file
->shortfilename
, shortFilename
, tailNum
);
248 // Try with no tail if first entry
250 memcpy(file
->shortfilename
, shortFilename
, FAT_SFN_SIZE_FULL
);
252 // Check if entry exists already or not
253 if (fatfs_sfn_exists(&_fs
, file
->parentcluster
, (char*)file
->shortfilename
) == 0)
258 while (tailNum
< 9999);
260 // We reached the max number of duplicate short file names (unlikely!)
263 // Delete allocated space
264 fatfs_free_cluster_chain(&_fs
, file
->startcluster
);
270 // Create a standard short filename (without tail)
271 if (!fatfs_lfn_create_sfn(shortFilename
, file
->filename
))
273 // Delete allocated space
274 fatfs_free_cluster_chain(&_fs
, file
->startcluster
);
281 memcpy(file
->shortfilename
, shortFilename
, FAT_SFN_SIZE_FULL
);
283 // Check if entry exists already
284 if (fatfs_sfn_exists(&_fs
, file
->parentcluster
, (char*)file
->shortfilename
))
286 // Delete allocated space
287 fatfs_free_cluster_chain(&_fs
, file
->startcluster
);
295 if (!fatfs_add_file_entry(&_fs
, file
->parentcluster
, (char*)file
->filename
, (char*)file
->shortfilename
, file
->startcluster
, 0, 1))
297 // Delete allocated space
298 fatfs_free_cluster_chain(&_fs
, file
->startcluster
);
305 file
->filelength
= 0;
307 file
->file_data_address
= 0xFFFFFFFF;
308 file
->file_data_dirty
= 0;
309 file
->filelength_changed
= 0;
311 // Quick lookup for next link in the chain
312 file
->last_fat_lookup
.ClusterIdx
= 0xFFFFFFFF;
313 file
->last_fat_lookup
.CurrentCluster
= 0xFFFFFFFF;
315 fatfs_fat_purge(&_fs
);
321 //-----------------------------------------------------------------------------
322 // _open_file: Open a file for reading
323 //-----------------------------------------------------------------------------
324 static FL_FILE
* _open_file(const char *path
)
327 struct fat_dir_entry sfEntry
;
329 // Allocate a new file handle
330 file
= _allocate_file();
335 memset(file
->path
, '\0', sizeof(file
->path
));
336 memset(file
->filename
, '\0', sizeof(file
->filename
));
338 // Split full path into filename and directory path
339 if (fatfs_split_path((char*)path
, file
->path
, sizeof(file
->path
), file
->filename
, sizeof(file
->filename
)) == -1)
345 // Check if file already open
346 if (_check_file_open(file
))
352 // If file is in the root dir
353 if (file
->path
[0]==0)
354 file
->parentcluster
= fatfs_get_root_cluster(&_fs
);
357 // Find parent directory start cluster
358 if (!_open_directory(file
->path
, &file
->parentcluster
))
365 // Using dir cluster address search for filename
366 if (fatfs_get_file_entry(&_fs
, file
->parentcluster
, file
->filename
,&sfEntry
))
367 // Make sure entry is file not dir!
368 if (fatfs_entry_is_file(&sfEntry
))
370 // Initialise file details
371 memcpy(file
->shortfilename
, sfEntry
.Name
, FAT_SFN_SIZE_FULL
);
372 file
->filelength
= FAT_HTONL(sfEntry
.FileSize
);
374 file
->startcluster
= ((FAT_HTONS((uint32
)sfEntry
.FstClusHI
))<<16) + FAT_HTONS(sfEntry
.FstClusLO
);
375 file
->file_data_address
= 0xFFFFFFFF;
376 file
->file_data_dirty
= 0;
377 file
->filelength_changed
= 0;
379 // Quick lookup for next link in the chain
380 file
->last_fat_lookup
.ClusterIdx
= 0xFFFFFFFF;
381 file
->last_fat_lookup
.CurrentCluster
= 0xFFFFFFFF;
383 fatfs_cache_init(&_fs
, file
);
385 fatfs_fat_purge(&_fs
);
393 //-----------------------------------------------------------------------------
394 // _create_file: Create a new file
395 //-----------------------------------------------------------------------------
396 #if FATFS_INC_WRITE_SUPPORT
397 static FL_FILE
* _create_file(const char *filename
)
400 struct fat_dir_entry sfEntry
;
401 char shortFilename
[FAT_SFN_SIZE_FULL
];
405 if (!_fs
.disk_io
.write_media
)
408 // Allocate a new file handle
409 file
= _allocate_file();
414 memset(file
->path
, '\0', sizeof(file
->path
));
415 memset(file
->filename
, '\0', sizeof(file
->filename
));
417 // Split full path into filename and directory path
418 if (fatfs_split_path((char*)filename
, file
->path
, sizeof(file
->path
), file
->filename
, sizeof(file
->filename
)) == -1)
424 // Check if file already open
425 if (_check_file_open(file
))
431 // If file is in the root dir
432 if (file
->path
[0] == 0)
433 file
->parentcluster
= fatfs_get_root_cluster(&_fs
);
436 // Find parent directory start cluster
437 if (!_open_directory(file
->path
, &file
->parentcluster
))
444 // Check if same filename exists in directory
445 if (fatfs_get_file_entry(&_fs
, file
->parentcluster
, file
->filename
,&sfEntry
) == 1)
451 file
->startcluster
= 0;
453 // Create the file space for the file (at least one clusters worth!)
454 if (!fatfs_allocate_free_space(&_fs
, 1, &file
->startcluster
, 1))
460 #if FATFS_INC_LFN_SUPPORT
461 // Generate a short filename & tail
465 // Create a standard short filename (without tail)
466 fatfs_lfn_create_sfn(shortFilename
, file
->filename
);
468 // If second hit or more, generate a ~n tail
470 fatfs_lfn_generate_tail((char*)file
->shortfilename
, shortFilename
, tailNum
);
471 // Try with no tail if first entry
473 memcpy(file
->shortfilename
, shortFilename
, FAT_SFN_SIZE_FULL
);
475 // Check if entry exists already or not
476 if (fatfs_sfn_exists(&_fs
, file
->parentcluster
, (char*)file
->shortfilename
) == 0)
481 while (tailNum
< 9999);
483 // We reached the max number of duplicate short file names (unlikely!)
486 // Delete allocated space
487 fatfs_free_cluster_chain(&_fs
, file
->startcluster
);
493 // Create a standard short filename (without tail)
494 if (!fatfs_lfn_create_sfn(shortFilename
, file
->filename
))
496 // Delete allocated space
497 fatfs_free_cluster_chain(&_fs
, file
->startcluster
);
504 memcpy(file
->shortfilename
, shortFilename
, FAT_SFN_SIZE_FULL
);
506 // Check if entry exists already
507 if (fatfs_sfn_exists(&_fs
, file
->parentcluster
, (char*)file
->shortfilename
))
509 // Delete allocated space
510 fatfs_free_cluster_chain(&_fs
, file
->startcluster
);
518 if (!fatfs_add_file_entry(&_fs
, file
->parentcluster
, (char*)file
->filename
, (char*)file
->shortfilename
, file
->startcluster
, 0, 0))
520 // Delete allocated space
521 fatfs_free_cluster_chain(&_fs
, file
->startcluster
);
528 file
->filelength
= 0;
530 file
->file_data_address
= 0xFFFFFFFF;
531 file
->file_data_dirty
= 0;
532 file
->filelength_changed
= 0;
534 // Quick lookup for next link in the chain
535 file
->last_fat_lookup
.ClusterIdx
= 0xFFFFFFFF;
536 file
->last_fat_lookup
.CurrentCluster
= 0xFFFFFFFF;
538 fatfs_cache_init(&_fs
, file
);
540 fatfs_fat_purge(&_fs
);
545 //-----------------------------------------------------------------------------
546 // _read_sectors: Read sector(s) from disk to file
547 //-----------------------------------------------------------------------------
548 static uint32
_read_sectors(FL_FILE
* file
, uint32 offset
, uint8
*buffer
, uint32 count
)
551 uint32 ClusterIdx
= 0;
556 // Find cluster index within file & sector with cluster
557 ClusterIdx
= offset
/ _fs
.sectors_per_cluster
;
558 Sector
= offset
- (ClusterIdx
* _fs
.sectors_per_cluster
);
560 // Limit number of sectors read to the number remaining in this cluster
561 if ((Sector
+ count
) > _fs
.sectors_per_cluster
)
562 count
= _fs
.sectors_per_cluster
- Sector
;
564 // Quick lookup for next link in the chain
565 if (ClusterIdx
== file
->last_fat_lookup
.ClusterIdx
)
566 Cluster
= file
->last_fat_lookup
.CurrentCluster
;
567 // Else walk the chain
570 // Starting from last recorded cluster?
571 if (ClusterIdx
&& ClusterIdx
== file
->last_fat_lookup
.ClusterIdx
+ 1)
573 i
= file
->last_fat_lookup
.ClusterIdx
;
574 Cluster
= file
->last_fat_lookup
.CurrentCluster
;
576 // Start searching from the beginning..
579 // Set start of cluster chain to initial value
581 Cluster
= file
->startcluster
;
584 // Follow chain to find cluster to read
585 for ( ;i
<ClusterIdx
; i
++)
589 // Does the entry exist in the cache?
590 if (!fatfs_cache_get_next_cluster(&_fs
, file
, i
, &nextCluster
))
592 // Scan file linked list to find next entry
593 nextCluster
= fatfs_find_next_cluster(&_fs
, Cluster
);
595 // Push entry into cache
596 fatfs_cache_set_next_cluster(&_fs
, file
, i
, nextCluster
);
599 Cluster
= nextCluster
;
602 // Record current cluster lookup details (if valid)
603 if (Cluster
!= FAT32_LAST_CLUSTER
)
605 file
->last_fat_lookup
.CurrentCluster
= Cluster
;
606 file
->last_fat_lookup
.ClusterIdx
= ClusterIdx
;
610 // If end of cluster chain then return false
611 if (Cluster
== FAT32_LAST_CLUSTER
)
614 // Calculate sector address
615 lba
= fatfs_lba_of_cluster(&_fs
, Cluster
) + Sector
;
617 // Read sector of file
618 if (fatfs_sector_read(&_fs
, lba
, buffer
, count
))
624 //-----------------------------------------------------------------------------
626 //-----------------------------------------------------------------------------
628 //-----------------------------------------------------------------------------
629 // fl_init: Initialise library
630 //-----------------------------------------------------------------------------
635 fat_list_init(&_free_file_list
);
636 fat_list_init(&_open_file_list
);
638 // Add all file objects to free list
639 for (i
=0;i
<FATFS_MAX_OPEN_FILES
;i
++)
640 fat_list_insert_last(&_free_file_list
, &_files
[i
].list_node
);
644 //-----------------------------------------------------------------------------
646 //-----------------------------------------------------------------------------
647 void fl_attach_locks(void (*lock
)(void), void (*unlock
)(void))
650 _fs
.fl_unlock
= unlock
;
652 //-----------------------------------------------------------------------------
654 //-----------------------------------------------------------------------------
655 int fl_attach_media(fn_diskio_read rd
, fn_diskio_write wr
)
659 // If first call to library, initialise
662 _fs
.disk_io
.read_media
= rd
;
663 _fs
.disk_io
.write_media
= wr
;
665 // Initialise FAT parameters
666 if ((res
= fatfs_init(&_fs
)) != FAT_INIT_OK
)
668 FAT_PRINTF(("FAT_FS: Error could not load FAT details (%d)!\r\n", res
));
675 //-----------------------------------------------------------------------------
676 // fl_shutdown: Call before shutting down system
677 //-----------------------------------------------------------------------------
678 void fl_shutdown(void)
680 // If first call to library, initialise
684 fatfs_fat_purge(&_fs
);
687 //-----------------------------------------------------------------------------
688 // fopen: Open or Create a file for reading or writing
689 //-----------------------------------------------------------------------------
690 void* fl_fopen(const char *path
, const char *mode
)
696 // If first call to library, initialise
706 // "r" Open a file for reading.
707 // The file must exist.
708 // "w" Create an empty file for writing.
709 // If a file with the same name already exists its content is erased and the file is treated as a new empty file.
710 // "a" Append to a file.
711 // Writing operations append data at the end of the file.
712 // The file is created if it does not exist.
713 // "r+" Open a file for update both reading and writing.
714 // The file must exist.
715 // "w+" Create an empty file for both reading and writing.
716 // If a file with the same name already exists its content is erased and the file is treated as a new empty file.
717 // "a+" Open a file for reading and appending.
718 // All writing operations are performed at the end of the file, protecting the previous content to be overwritten.
719 // You can reposition (fseek, rewind) the internal pointer to anywhere in the file for reading, but writing operations
720 // will move it back to the end of file.
721 // The file is created if it does not exist.
723 for (i
=0;i
<(int)strlen(mode
);i
++)
735 flags
|= FILE_CREATE
;
740 flags
|= FILE_APPEND
;
741 flags
|= FILE_CREATE
;
744 if (flags
& FILE_READ
)
746 else if (flags
& FILE_WRITE
)
750 flags
|= FILE_CREATE
;
752 else if (flags
& FILE_APPEND
)
756 flags
|= FILE_APPEND
;
757 flags
|= FILE_CREATE
;
762 flags
|= FILE_BINARY
;
769 #if FATFS_INC_WRITE_SUPPORT == 0
771 flags
&= ~(FILE_CREATE
| FILE_WRITE
| FILE_APPEND
);
774 // No write access - remove write/modify flags
775 if (!_fs
.disk_io
.write_media
)
776 flags
&= ~(FILE_CREATE
| FILE_WRITE
| FILE_APPEND
);
781 if (flags
& FILE_READ
)
782 file
= _open_file(path
);
785 #if FATFS_INC_WRITE_SUPPORT
786 if (!file
&& (flags
& FILE_CREATE
))
787 file
= _create_file(path
);
790 // Write Existing (and not open due to read or create)
791 if (!(flags
& FILE_READ
))
792 if ((flags
& FILE_CREATE
) && !file
)
793 if (flags
& (FILE_WRITE
| FILE_APPEND
))
794 file
= _open_file(path
);
802 //-----------------------------------------------------------------------------
803 // _write_sectors: Write sector(s) to disk
804 //-----------------------------------------------------------------------------
805 #if FATFS_INC_WRITE_SUPPORT
806 static uint32
_write_sectors(FL_FILE
* file
, uint32 offset
, uint8
*buf
, uint32 count
)
808 uint32 SectorNumber
= 0;
809 uint32 ClusterIdx
= 0;
811 uint32 LastCluster
= FAT32_LAST_CLUSTER
;
814 uint32 TotalWriteCount
= count
;
816 // Find values for Cluster index & sector within cluster
817 ClusterIdx
= offset
/ _fs
.sectors_per_cluster
;
818 SectorNumber
= offset
- (ClusterIdx
* _fs
.sectors_per_cluster
);
820 // Limit number of sectors written to the number remaining in this cluster
821 if ((SectorNumber
+ count
) > _fs
.sectors_per_cluster
)
822 count
= _fs
.sectors_per_cluster
- SectorNumber
;
824 // Quick lookup for next link in the chain
825 if (ClusterIdx
== file
->last_fat_lookup
.ClusterIdx
)
826 Cluster
= file
->last_fat_lookup
.CurrentCluster
;
827 // Else walk the chain
830 // Starting from last recorded cluster?
831 if (ClusterIdx
&& ClusterIdx
== file
->last_fat_lookup
.ClusterIdx
+ 1)
833 i
= file
->last_fat_lookup
.ClusterIdx
;
834 Cluster
= file
->last_fat_lookup
.CurrentCluster
;
836 // Start searching from the beginning..
839 // Set start of cluster chain to initial value
841 Cluster
= file
->startcluster
;
844 // Follow chain to find cluster to read
845 for ( ;i
<ClusterIdx
; i
++)
849 // Does the entry exist in the cache?
850 if (!fatfs_cache_get_next_cluster(&_fs
, file
, i
, &nextCluster
))
852 // Scan file linked list to find next entry
853 nextCluster
= fatfs_find_next_cluster(&_fs
, Cluster
);
855 // Push entry into cache
856 fatfs_cache_set_next_cluster(&_fs
, file
, i
, nextCluster
);
859 LastCluster
= Cluster
;
860 Cluster
= nextCluster
;
862 // Dont keep following a dead end
863 if (Cluster
== FAT32_LAST_CLUSTER
)
867 // If we have reached the end of the chain, allocate more!
868 if (Cluster
== FAT32_LAST_CLUSTER
)
870 // Add some more cluster(s) to the last good cluster chain
871 if (!fatfs_add_free_space(&_fs
, &LastCluster
, (TotalWriteCount
+ _fs
.sectors_per_cluster
-1) / _fs
.sectors_per_cluster
))
874 Cluster
= LastCluster
;
877 // Record current cluster lookup details
878 file
->last_fat_lookup
.CurrentCluster
= Cluster
;
879 file
->last_fat_lookup
.ClusterIdx
= ClusterIdx
;
882 // Calculate write address
883 lba
= fatfs_lba_of_cluster(&_fs
, Cluster
) + SectorNumber
;
885 if (fatfs_sector_write(&_fs
, lba
, buf
, count
))
891 //-----------------------------------------------------------------------------
892 // fl_fflush: Flush un-written data to the file
893 //-----------------------------------------------------------------------------
894 int fl_fflush(void *f
)
896 #if FATFS_INC_WRITE_SUPPORT
897 FL_FILE
*file
= (FL_FILE
*)f
;
899 // If first call to library, initialise
906 // If some write data still in buffer
907 if (file
->file_data_dirty
)
909 // Write back current sector before loading next
910 if (_write_sectors(file
, file
->file_data_address
, file
->file_data_sector
, 1))
911 file
->file_data_dirty
= 0;
919 //-----------------------------------------------------------------------------
920 // fl_fclose: Close an open file
921 //-----------------------------------------------------------------------------
922 void fl_fclose(void *f
)
924 FL_FILE
*file
= (FL_FILE
*)f
;
926 // If first call to library, initialise
933 // Flush un-written data to file
936 // File size changed?
937 if (file
->filelength_changed
)
939 #if FATFS_INC_WRITE_SUPPORT
940 // Update filesize in directory
941 fatfs_update_file_length(&_fs
, file
->parentcluster
, (char*)file
->shortfilename
, file
->filelength
);
943 file
->filelength_changed
= 0;
947 file
->filelength
= 0;
948 file
->startcluster
= 0;
949 file
->file_data_address
= 0xFFFFFFFF;
950 file
->file_data_dirty
= 0;
951 file
->filelength_changed
= 0;
956 fatfs_fat_purge(&_fs
);
961 //-----------------------------------------------------------------------------
962 // fl_fgetc: Get a character in the stream
963 //-----------------------------------------------------------------------------
964 int fl_fgetc(void *f
)
969 res
= fl_fread(&data
, 1, 1, f
);
975 //-----------------------------------------------------------------------------
976 // fl_fgets: Get a string from a stream
977 //-----------------------------------------------------------------------------
978 char *fl_fgets(char *s
, int n
, void *f
)
982 // Space for null terminator?
985 // While space (+space for null terminator)
988 int ch
= fl_fgetc(f
);
994 // Store character read from stream
1006 return (idx
> 0) ? s
: 0;
1008 //-----------------------------------------------------------------------------
1009 // fl_fread: Read a block of data from the file
1010 //-----------------------------------------------------------------------------
1011 int fl_fread(void * buffer
, int size
, int length
, void *f
)
1016 int count
= size
* length
;
1019 FL_FILE
*file
= (FL_FILE
*)f
;
1021 // If first call to library, initialise
1024 if (buffer
==NULL
|| file
==NULL
)
1027 // No read permissions
1028 if (!(file
->flags
& FILE_READ
))
1031 // Nothing to be done
1035 // Check if read starts past end of file
1036 if (file
->bytenum
>= file
->filelength
)
1039 // Limit to file size
1040 if ( (file
->bytenum
+ count
) > file
->filelength
)
1041 count
= file
->filelength
- file
->bytenum
;
1043 // Calculate start sector
1044 sector
= file
->bytenum
/ FAT_SECTOR_SIZE
;
1046 // Offset to start copying data from first sector
1047 offset
= file
->bytenum
% FAT_SECTOR_SIZE
;
1049 while (bytesRead
< count
)
1051 // Read whole sector, read from media directly into target buffer
1052 if ((offset
== 0) && ((count
- bytesRead
) >= FAT_SECTOR_SIZE
))
1054 // Read as many sectors as possible into target buffer
1055 uint32 sectorsRead
= _read_sectors(file
, sector
, (uint8
*)((uint8
*)buffer
+ bytesRead
), (count
- bytesRead
) / FAT_SECTOR_SIZE
);
1058 // We have upto one sector to copy
1059 copyCount
= FAT_SECTOR_SIZE
* sectorsRead
;
1061 // Move onto next sector and reset copy offset
1062 sector
+= sectorsRead
;
1070 // Do we need to re-read the sector?
1071 if (file
->file_data_address
!= sector
)
1073 // Flush un-written data to file
1074 if (file
->file_data_dirty
)
1077 // Get LBA of sector offset within file
1078 if (!_read_sectors(file
, sector
, file
->file_data_sector
, 1))
1079 // Read failed - out of range (probably)
1082 file
->file_data_address
= sector
;
1083 file
->file_data_dirty
= 0;
1086 // We have upto one sector to copy
1087 copyCount
= FAT_SECTOR_SIZE
- offset
;
1089 // Only require some of this sector?
1090 if (copyCount
> (count
- bytesRead
))
1091 copyCount
= (count
- bytesRead
);
1093 // Copy to application buffer
1094 memcpy( (uint8
*)((uint8
*)buffer
+ bytesRead
), (uint8
*)(file
->file_data_sector
+ offset
), copyCount
);
1096 // Move onto next sector and reset copy offset
1101 // Increase total read count
1102 bytesRead
+= copyCount
;
1104 // Increment file pointer
1105 file
->bytenum
+= copyCount
;
1110 //-----------------------------------------------------------------------------
1111 // fl_fseek: Seek to a specific place in the file
1112 //-----------------------------------------------------------------------------
1113 int fl_fseek( void *f
, long offset
, int origin
)
1115 FL_FILE
*file
= (FL_FILE
*)f
;
1118 // If first call to library, initialise
1124 if (origin
== SEEK_END
&& offset
!= 0)
1129 // Invalidate file buffer
1130 file
->file_data_address
= 0xFFFFFFFF;
1131 file
->file_data_dirty
= 0;
1133 if (origin
== SEEK_SET
)
1135 file
->bytenum
= (uint32
)offset
;
1137 if (file
->bytenum
> file
->filelength
)
1138 file
->bytenum
= file
->filelength
;
1142 else if (origin
== SEEK_CUR
)
1147 file
->bytenum
+= offset
;
1149 if (file
->bytenum
> file
->filelength
)
1150 file
->bytenum
= file
->filelength
;
1155 // Make shift positive
1158 // Limit to negative shift to start of file
1159 if ((uint32
)offset
> file
->bytenum
)
1162 file
->bytenum
-= offset
;
1167 else if (origin
== SEEK_END
)
1169 file
->bytenum
= file
->filelength
;
1179 //-----------------------------------------------------------------------------
1180 // fl_fgetpos: Get the current file position
1181 //-----------------------------------------------------------------------------
1182 int fl_fgetpos(void *f
, uint32
* position
)
1184 FL_FILE
*file
= (FL_FILE
*)f
;
1192 *position
= file
->bytenum
;
1198 //-----------------------------------------------------------------------------
1199 // fl_ftell: Get the current file position
1200 //-----------------------------------------------------------------------------
1201 long fl_ftell(void *f
)
1205 fl_fgetpos(f
, &pos
);
1209 //-----------------------------------------------------------------------------
1210 // fl_feof: Is the file pointer at the end of the stream?
1211 //-----------------------------------------------------------------------------
1212 int fl_feof(void *f
)
1214 FL_FILE
*file
= (FL_FILE
*)f
;
1222 if (file
->bytenum
== file
->filelength
)
1231 //-----------------------------------------------------------------------------
1232 // fl_fputc: Write a character to the stream
1233 //-----------------------------------------------------------------------------
1234 #if FATFS_INC_WRITE_SUPPORT
1235 int fl_fputc(int c
, void *f
)
1237 uint8 data
= (uint8
)c
;
1240 res
= fl_fwrite(&data
, 1, 1, f
);
1247 //-----------------------------------------------------------------------------
1248 // fl_fwrite: Write a block of data to the stream
1249 //-----------------------------------------------------------------------------
1250 #if FATFS_INC_WRITE_SUPPORT
1251 int fl_fwrite(const void * data
, int size
, int count
, void *f
)
1253 FL_FILE
*file
= (FL_FILE
*)f
;
1256 uint32 length
= (size
*count
);
1257 uint8
*buffer
= (uint8
*)data
;
1258 uint32 bytesWritten
= 0;
1261 // If first call to library, initialise
1269 // No write permissions
1270 if (!(file
->flags
& FILE_WRITE
))
1276 // Append writes to end of file
1277 if (file
->flags
& FILE_APPEND
)
1278 file
->bytenum
= file
->filelength
;
1279 // Else write to current position
1281 // Calculate start sector
1282 sector
= file
->bytenum
/ FAT_SECTOR_SIZE
;
1284 // Offset to start copying data from first sector
1285 offset
= file
->bytenum
% FAT_SECTOR_SIZE
;
1287 while (bytesWritten
< length
)
1289 // Whole sector or more to be written?
1290 if ((offset
== 0) && ((length
- bytesWritten
) >= FAT_SECTOR_SIZE
))
1292 uint32 sectorsWrote
;
1294 // Buffered sector, flush back to disk
1295 if (file
->file_data_address
!= 0xFFFFFFFF)
1297 // Flush un-written data to file
1298 if (file
->file_data_dirty
)
1301 file
->file_data_address
= 0xFFFFFFFF;
1302 file
->file_data_dirty
= 0;
1305 // Write as many sectors as possible
1306 sectorsWrote
= _write_sectors(file
, sector
, (uint8
*)(buffer
+ bytesWritten
), (length
- bytesWritten
) / FAT_SECTOR_SIZE
);
1307 copyCount
= FAT_SECTOR_SIZE
* sectorsWrote
;
1309 // Increase total read count
1310 bytesWritten
+= copyCount
;
1312 // Increment file pointer
1313 file
->bytenum
+= copyCount
;
1315 // Move onto next sector and reset copy offset
1316 sector
+= sectorsWrote
;
1324 // We have upto one sector to copy
1325 copyCount
= FAT_SECTOR_SIZE
- offset
;
1327 // Only require some of this sector?
1328 if (copyCount
> (length
- bytesWritten
))
1329 copyCount
= (length
- bytesWritten
);
1331 // Do we need to read a new sector?
1332 if (file
->file_data_address
!= sector
)
1334 // Flush un-written data to file
1335 if (file
->file_data_dirty
)
1338 // If we plan to overwrite the whole sector, we don't need to read it first!
1339 if (copyCount
!= FAT_SECTOR_SIZE
)
1341 // NOTE: This does not have succeed; if last sector of file
1342 // reached, no valid data will be read in, but write will
1343 // allocate some more space for new data.
1345 // Get LBA of sector offset within file
1346 if (!_read_sectors(file
, sector
, file
->file_data_sector
, 1))
1347 memset(file
->file_data_sector
, 0x00, FAT_SECTOR_SIZE
);
1350 file
->file_data_address
= sector
;
1351 file
->file_data_dirty
= 0;
1354 // Copy from application buffer into sector buffer
1355 memcpy((uint8
*)(file
->file_data_sector
+ offset
), (uint8
*)(buffer
+ bytesWritten
), copyCount
);
1357 // Mark buffer as dirty
1358 file
->file_data_dirty
= 1;
1360 // Increase total read count
1361 bytesWritten
+= copyCount
;
1363 // Increment file pointer
1364 file
->bytenum
+= copyCount
;
1366 // Move onto next sector and reset copy offset
1372 // Write increased extent of the file?
1373 if (file
->bytenum
> file
->filelength
)
1375 // Increase file size to new point
1376 file
->filelength
= file
->bytenum
;
1378 // We are changing the file length and this
1379 // will need to be writen back at some point
1380 file
->filelength_changed
= 1;
1383 #if FATFS_INC_TIME_DATE_SUPPORT
1384 // If time & date support is enabled, always force directory entry to be
1385 // written in-order to update file modify / access time & date.
1386 file
->filelength_changed
= 1;
1391 return (size
*count
);
1394 //-----------------------------------------------------------------------------
1395 // fl_fputs: Write a character string to the stream
1396 //-----------------------------------------------------------------------------
1397 #if FATFS_INC_WRITE_SUPPORT
1398 int fl_fputs(const char * str
, void *f
)
1400 int len
= (int)strlen(str
);
1401 int res
= fl_fwrite(str
, 1, len
, f
);
1409 //-----------------------------------------------------------------------------
1410 // fl_remove: Remove a file from the filesystem
1411 //-----------------------------------------------------------------------------
1412 #if FATFS_INC_WRITE_SUPPORT
1413 int fl_remove( const char * filename
)
1420 // Use read_file as this will check if the file is already open!
1421 file
= fl_fopen((char*)filename
, "r");
1424 // Delete allocated space
1425 if (fatfs_free_cluster_chain(&_fs
, file
->startcluster
))
1427 // Remove directory entries
1428 if (fatfs_mark_file_deleted(&_fs
, file
->parentcluster
, (char*)file
->shortfilename
))
1430 // Close the file handle (this should not write anything to the file
1431 // as we have not changed the file since opening it!)
1444 //-----------------------------------------------------------------------------
1445 // fl_createdirectory: Create a directory based on a path
1446 //-----------------------------------------------------------------------------
1447 #if FATFS_INC_WRITE_SUPPORT
1448 int fl_createdirectory(const char *path
)
1452 // If first call to library, initialise
1456 res
=_create_directory((char*)path
);
1462 //-----------------------------------------------------------------------------
1463 // fl_listdirectory: List a directory based on a path
1464 //-----------------------------------------------------------------------------
1465 #if FATFS_DIR_LIST_SUPPORT
1466 void fl_listdirectory(const char *path
)
1470 // If first call to library, initialise
1475 FAT_PRINTF(("\r\nDirectory %s\r\n", path
));
1477 if (fl_opendir(path
, &dirstat
))
1479 struct fs_dir_ent dirent
;
1481 while (fl_readdir(&dirstat
, &dirent
) == 0)
1483 #if FATFS_INC_TIME_DATE_SUPPORT
1485 fatfs_convert_from_fat_time(dirent
.write_time
, &h
,&m
,&s
);
1486 fatfs_convert_from_fat_date(dirent
.write_date
, &d
,&mn
,&y
);
1487 FAT_PRINTF(("%02d/%02d/%04d %02d:%02d ", d
,mn
,y
,h
,m
));
1492 FAT_PRINTF(("%s <DIR>\r\n", dirent
.filename
));
1496 FAT_PRINTF(("%s [%d bytes]\r\n", dirent
.filename
, dirent
.size
));
1500 fl_closedir(&dirstat
);
1506 //-----------------------------------------------------------------------------
1507 // fl_opendir: Opens a directory for listing
1508 //-----------------------------------------------------------------------------
1509 #if FATFS_DIR_LIST_SUPPORT
1510 FL_DIR
* fl_opendir(const char* path
, FL_DIR
*dir
)
1514 uint32 cluster
= FAT32_INVALID_CLUSTER
;
1516 // If first call to library, initialise
1521 levels
= fatfs_total_path_levels((char*)path
) + 1;
1523 // If path is in the root dir
1525 cluster
= fatfs_get_root_cluster(&_fs
);
1526 // Find parent directory start cluster
1528 res
= _open_directory((char*)path
, &cluster
);
1531 fatfs_list_directory_start(&_fs
, dir
, cluster
);
1535 return cluster
!= FAT32_INVALID_CLUSTER
? dir
: 0;
1538 //-----------------------------------------------------------------------------
1539 // fl_readdir: Get next item in directory
1540 //-----------------------------------------------------------------------------
1541 #if FATFS_DIR_LIST_SUPPORT
1542 int fl_readdir(FL_DIR
*dirls
, fl_dirent
*entry
)
1546 // If first call to library, initialise
1551 res
= fatfs_list_directory_next(&_fs
, dirls
, entry
);
1555 return res
? 0 : -1;
1558 //-----------------------------------------------------------------------------
1559 // fl_closedir: Close directory after listing
1560 //-----------------------------------------------------------------------------
1561 #if FATFS_DIR_LIST_SUPPORT
1562 int fl_closedir(FL_DIR
* dir
)
1568 //-----------------------------------------------------------------------------
1569 // fl_is_dir: Is this a directory?
1570 //-----------------------------------------------------------------------------
1571 #if FATFS_DIR_LIST_SUPPORT
1572 int fl_is_dir(const char *path
)
1577 if (fl_opendir(path
, &dir
))
1586 //-----------------------------------------------------------------------------
1587 // fl_format: Format a partition with either FAT16 or FAT32 based on size
1588 //-----------------------------------------------------------------------------
1589 #if FATFS_INC_FORMAT_SUPPORT
1590 int fl_format(uint32 volume_sectors
, const char *name
)
1592 return fatfs_format(&_fs
, volume_sectors
, name
);
1594 #endif /*FATFS_INC_FORMAT_SUPPORT*/
1595 //-----------------------------------------------------------------------------
1597 //-----------------------------------------------------------------------------
1598 #ifdef FATFS_INC_TEST_HOOKS
1599 struct fatfs
* fl_get_fs(void)