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 //-----------------------------------------------------------------------------
34 #include "fat_access.h"
35 #include "fat_table.h"
36 #include "fat_write.h"
37 #include "fat_string.h"
40 #if FATFS_INC_WRITE_SUPPORT
41 //-----------------------------------------------------------------------------
42 // fatfs_add_free_space: Allocate another cluster of free space to the end
43 // of a files cluster chain.
44 //-----------------------------------------------------------------------------
45 int fatfs_add_free_space(struct fatfs
*fs
, uint32
*startCluster
, uint32 clusters
)
49 uint32 start
= *startCluster
;
51 // Set the next free cluster hint to unknown
52 if (fs
->next_free_cluster
!= FAT32_LAST_CLUSTER
)
53 fatfs_set_fs_info_next_free_cluster(fs
, FAT32_LAST_CLUSTER
);
55 for (i
=0;i
<clusters
;i
++)
57 // Start looking for free clusters from the beginning
58 if (fatfs_find_blank_cluster(fs
, fs
->rootdir_first_cluster
, &nextcluster
))
61 fatfs_fat_set_cluster(fs
, start
, nextcluster
);
63 // Point this to end of file
64 fatfs_fat_set_cluster(fs
, nextcluster
, FAT32_LAST_CLUSTER
);
66 // Adjust argument reference
69 *startCluster
= nextcluster
;
77 //-----------------------------------------------------------------------------
78 // fatfs_allocate_free_space: Add an ammount of free space to a file either from
79 // 'startCluster' if newFile = false, or allocating a new start to the chain if
81 //-----------------------------------------------------------------------------
82 int fatfs_allocate_free_space(struct fatfs
*fs
, int newFile
, uint32
*startCluster
, uint32 size
)
91 // Set the next free cluster hint to unknown
92 if (fs
->next_free_cluster
!= FAT32_LAST_CLUSTER
)
93 fatfs_set_fs_info_next_free_cluster(fs
, FAT32_LAST_CLUSTER
);
95 // Work out size and clusters
96 clusterSize
= fs
->sectors_per_cluster
* FAT_SECTOR_SIZE
;
97 clusterCount
= (size
/ clusterSize
);
100 if (size
-(clusterSize
*clusterCount
))
103 // Allocated first link in the chain if a new file
106 if (!fatfs_find_blank_cluster(fs
, fs
->rootdir_first_cluster
, &nextcluster
))
109 // If this is all that is needed then all done
112 fatfs_fat_set_cluster(fs
, nextcluster
, FAT32_LAST_CLUSTER
);
113 *startCluster
= nextcluster
;
117 // Allocate from end of current chain (startCluster is end of chain)
119 nextcluster
= *startCluster
;
121 if (!fatfs_add_free_space(fs
, &nextcluster
, clusterCount
))
126 //-----------------------------------------------------------------------------
127 // fatfs_find_free_dir_offset: Find a free space in the directory for a new entry
128 // which takes up 'entryCount' blocks (or allocate some more)
129 //-----------------------------------------------------------------------------
130 static int fatfs_find_free_dir_offset(struct fatfs
*fs
, uint32 dirCluster
, int entryCount
, uint32
*pSector
, uint8
*pOffset
)
132 struct fat_dir_entry
*directoryEntry
;
134 uint16 recordoffset
= 0;
137 int possible_spaces
= 0;
138 int start_recorded
= 0;
140 // No entries required?
144 // Main cluster following loop
148 if (fatfs_sector_reader(fs
, dirCluster
, x
++, 0))
151 for (item
= 0; item
< FAT_DIR_ENTRIES_PER_SECTOR
; item
++)
153 // Create the multiplier for sector access
154 recordoffset
= FAT_DIR_ENTRY_SIZE
* item
;
156 // Overlay directory entry over buffer
157 directoryEntry
= (struct fat_dir_entry
*)(fs
->currentsector
.sector
+recordoffset
);
160 if (fatfs_entry_lfn_text(directoryEntry
))
163 if (possible_spaces
== 0)
171 // Increment the count in-case the file turns
172 // out to be deleted...
178 // Has file been deleted?
179 if (fs
->currentsector
.sector
[recordoffset
] == FILE_HEADER_DELETED
)
182 if (possible_spaces
== 0)
192 // We have found enough space?
193 if (possible_spaces
>= entryCount
)
196 // Else continue counting until we find a valid entry!
198 // Is the file entry empty?
199 else if (fs
->currentsector
.sector
[recordoffset
] == FILE_HEADER_BLANK
)
202 if (possible_spaces
== 0)
210 // Increment the blank entries count
213 // We have found enough space?
214 if (possible_spaces
>= entryCount
)
217 // File entry is valid
227 // Run out of free space in the directory, allocate some more
232 // Get a new cluster for directory
233 if (!fatfs_find_blank_cluster(fs
, fs
->rootdir_first_cluster
, &newCluster
))
236 // Add cluster to end of directory tree
237 if (!fatfs_fat_add_cluster_to_chain(fs
, dirCluster
, newCluster
))
240 // Erase new directory cluster
241 memset(fs
->currentsector
.sector
, 0x00, FAT_SECTOR_SIZE
);
242 for (i
=0;i
<fs
->sectors_per_cluster
;i
++)
244 if (!fatfs_write_sector(fs
, newCluster
, i
, 0))
248 // If non of the name fitted on previous sectors
259 } // End of while loop
263 //-----------------------------------------------------------------------------
264 // fatfs_add_file_entry: Add a directory entry to a location found by FindFreeOffset
265 //-----------------------------------------------------------------------------
266 int fatfs_add_file_entry(struct fatfs
*fs
, uint32 dirCluster
, char *filename
, char *shortfilename
, uint32 startCluster
, uint32 size
, int dir
)
269 uint16 recordoffset
= 0;
273 struct fat_dir_entry shortEntry
;
276 uint32 dirSector
= 0;
284 if (!fs
->disk_io
.write_media
)
287 #if FATFS_INC_LFN_SUPPORT
288 // How many LFN entries are required?
289 // NOTE: We always request one LFN even if it would fit in a SFN!
290 entryCount
= fatfs_lfn_entries_required(filename
);
297 // Find space in the directory for this filename (or allocate some more)
298 // NOTE: We need to find space for at least the LFN + SFN (or just the SFN if LFNs not supported).
299 if (!fatfs_find_free_dir_offset(fs
, dirCluster
, entryCount
+ 1, &dirSector
, &dirOffset
))
302 // Generate checksum of short filename
303 pSname
= (uint8
*)shortfilename
;
305 for (i
=11; i
!=0; i
--) checksum
= ((checksum
& 1) ? 0x80 : 0) + (checksum
>> 1) + *pSname
++;
307 // Start from current sector where space was found!
310 // Main cluster following loop
314 if (fatfs_sector_reader(fs
, dirCluster
, x
++, 0))
317 for (item
= 0; item
< FAT_DIR_ENTRIES_PER_SECTOR
; item
++)
319 // Create the multiplier for sector access
320 recordoffset
= FAT_DIR_ENTRY_SIZE
* item
;
322 // If the start position for the entry has been found
324 if ( (dirSector
==(x
-1)) && (dirOffset
==item
) )
327 // Start adding filename
333 fatfs_sfn_create_entry(shortfilename
, size
, startCluster
, &shortEntry
, dir
);
335 #if FATFS_INC_TIME_DATE_SUPPORT
336 // Update create, access & modify time & date
337 fatfs_update_timestamps(&shortEntry
, 1, 1, 1);
340 memcpy(&fs
->currentsector
.sector
[recordoffset
], &shortEntry
, sizeof(shortEntry
));
343 return fs
->disk_io
.write_media(fs
->currentsector
.address
, fs
->currentsector
.sector
, 1);
345 #if FATFS_INC_LFN_SUPPORT
350 // Copy entry to directory buffer
351 fatfs_filename_to_lfn(filename
, &fs
->currentsector
.sector
[recordoffset
], entryCount
, checksum
);
358 // Write back to disk before loading another sector
361 if (!fs
->disk_io
.write_media(fs
->currentsector
.address
, fs
->currentsector
.sector
, 1))
369 } // End of while loop