]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Plugson/src/Lib/fat_io_lib/fat_write.c
update Russian and Bengali languages.json (#2167)
[Ventoy.git] / Plugson / src / Lib / fat_io_lib / fat_write.c
1 //-----------------------------------------------------------------------------
2 //-----------------------------------------------------------------------------
3 // FAT16/32 File IO Library
4 // V2.6
5 // Ultra-Embedded.com
6 // Copyright 2003 - 2012
7 //
8 // Email: admin@ultra-embedded.com
9 //
10 // License: GPL
11 // If you would like a version with a more permissive license for use in
12 // closed source commercial applications please contact me for details.
13 //-----------------------------------------------------------------------------
14 //
15 // This file is part of FAT File IO Library.
16 //
17 // FAT File IO Library is free software; you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation; either version 2 of the License, or
20 // (at your option) any later version.
21 //
22 // FAT File IO Library is distributed in the hope that it will be useful,
23 // but WITHOUT ANY WARRANTY; without even the implied warranty of
24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 // GNU General Public License for more details.
26 //
27 // You should have received a copy of the GNU General Public License
28 // along with FAT File IO Library; if not, write to the Free Software
29 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 //-----------------------------------------------------------------------------
31 //-----------------------------------------------------------------------------
32 #include <string.h>
33 #include "fat_defs.h"
34 #include "fat_access.h"
35 #include "fat_table.h"
36 #include "fat_write.h"
37 #include "fat_string.h"
38 #include "fat_misc.h"
39
40 #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)
46 {
47 uint32 i;
48 uint32 nextcluster;
49 uint32 start = *startCluster;
50
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);
54
55 for (i=0;i<clusters;i++)
56 {
57 // Start looking for free clusters from the beginning
58 if (fatfs_find_blank_cluster(fs, fs->rootdir_first_cluster, &nextcluster))
59 {
60 // Point last to this
61 fatfs_fat_set_cluster(fs, start, nextcluster);
62
63 // Point this to end of file
64 fatfs_fat_set_cluster(fs, nextcluster, FAT32_LAST_CLUSTER);
65
66 // Adjust argument reference
67 start = nextcluster;
68 if (i == 0)
69 *startCluster = nextcluster;
70 }
71 else
72 return 0;
73 }
74
75 return 1;
76 }
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
80 // newFile = true.
81 //-----------------------------------------------------------------------------
82 int fatfs_allocate_free_space(struct fatfs *fs, int newFile, uint32 *startCluster, uint32 size)
83 {
84 uint32 clusterSize;
85 uint32 clusterCount;
86 uint32 nextcluster;
87
88 if (size==0)
89 return 0;
90
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);
94
95 // Work out size and clusters
96 clusterSize = fs->sectors_per_cluster * FAT_SECTOR_SIZE;
97 clusterCount = (size / clusterSize);
98
99 // If any left over
100 if (size-(clusterSize*clusterCount))
101 clusterCount++;
102
103 // Allocated first link in the chain if a new file
104 if (newFile)
105 {
106 if (!fatfs_find_blank_cluster(fs, fs->rootdir_first_cluster, &nextcluster))
107 return 0;
108
109 // If this is all that is needed then all done
110 if (clusterCount==1)
111 {
112 fatfs_fat_set_cluster(fs, nextcluster, FAT32_LAST_CLUSTER);
113 *startCluster = nextcluster;
114 return 1;
115 }
116 }
117 // Allocate from end of current chain (startCluster is end of chain)
118 else
119 nextcluster = *startCluster;
120
121 if (!fatfs_add_free_space(fs, &nextcluster, clusterCount))
122 return 0;
123
124 return 1;
125 }
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)
131 {
132 struct fat_dir_entry *directoryEntry;
133 uint8 item=0;
134 uint16 recordoffset = 0;
135 uint8 i=0;
136 int x=0;
137 int possible_spaces = 0;
138 int start_recorded = 0;
139
140 // No entries required?
141 if (entryCount == 0)
142 return 0;
143
144 // Main cluster following loop
145 while (1)
146 {
147 // Read sector
148 if (fatfs_sector_reader(fs, dirCluster, x++, 0))
149 {
150 // Analyse Sector
151 for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
152 {
153 // Create the multiplier for sector access
154 recordoffset = FAT_DIR_ENTRY_SIZE * item;
155
156 // Overlay directory entry over buffer
157 directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
158
159 // LFN Entry
160 if (fatfs_entry_lfn_text(directoryEntry))
161 {
162 // First entry?
163 if (possible_spaces == 0)
164 {
165 // Store start
166 *pSector = x-1;
167 *pOffset = item;
168 start_recorded = 1;
169 }
170
171 // Increment the count in-case the file turns
172 // out to be deleted...
173 possible_spaces++;
174 }
175 // SFN Entry
176 else
177 {
178 // Has file been deleted?
179 if (fs->currentsector.sector[recordoffset] == FILE_HEADER_DELETED)
180 {
181 // First entry?
182 if (possible_spaces == 0)
183 {
184 // Store start
185 *pSector = x-1;
186 *pOffset = item;
187 start_recorded = 1;
188 }
189
190 possible_spaces++;
191
192 // We have found enough space?
193 if (possible_spaces >= entryCount)
194 return 1;
195
196 // Else continue counting until we find a valid entry!
197 }
198 // Is the file entry empty?
199 else if (fs->currentsector.sector[recordoffset] == FILE_HEADER_BLANK)
200 {
201 // First entry?
202 if (possible_spaces == 0)
203 {
204 // Store start
205 *pSector = x-1;
206 *pOffset = item;
207 start_recorded = 1;
208 }
209
210 // Increment the blank entries count
211 possible_spaces++;
212
213 // We have found enough space?
214 if (possible_spaces >= entryCount)
215 return 1;
216 }
217 // File entry is valid
218 else
219 {
220 // Reset all flags
221 possible_spaces = 0;
222 start_recorded = 0;
223 }
224 }
225 } // End of for
226 } // End of if
227 // Run out of free space in the directory, allocate some more
228 else
229 {
230 uint32 newCluster;
231
232 // Get a new cluster for directory
233 if (!fatfs_find_blank_cluster(fs, fs->rootdir_first_cluster, &newCluster))
234 return 0;
235
236 // Add cluster to end of directory tree
237 if (!fatfs_fat_add_cluster_to_chain(fs, dirCluster, newCluster))
238 return 0;
239
240 // Erase new directory cluster
241 memset(fs->currentsector.sector, 0x00, FAT_SECTOR_SIZE);
242 for (i=0;i<fs->sectors_per_cluster;i++)
243 {
244 if (!fatfs_write_sector(fs, newCluster, i, 0))
245 return 0;
246 }
247
248 // If non of the name fitted on previous sectors
249 if (!start_recorded)
250 {
251 // Store start
252 *pSector = (x-1);
253 *pOffset = 0;
254 start_recorded = 1;
255 }
256
257 return 1;
258 }
259 } // End of while loop
260
261 return 0;
262 }
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)
267 {
268 uint8 item=0;
269 uint16 recordoffset = 0;
270 uint8 i=0;
271 uint32 x=0;
272 int entryCount;
273 struct fat_dir_entry shortEntry;
274 int dirtySector = 0;
275
276 uint32 dirSector = 0;
277 uint8 dirOffset = 0;
278 int foundEnd = 0;
279
280 uint8 checksum;
281 uint8 *pSname;
282
283 // No write access?
284 if (!fs->disk_io.write_media)
285 return 0;
286
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);
291 if (!entryCount)
292 return 0;
293 #else
294 entryCount = 0;
295 #endif
296
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))
300 return 0;
301
302 // Generate checksum of short filename
303 pSname = (uint8*)shortfilename;
304 checksum = 0;
305 for (i=11; i!=0; i--) checksum = ((checksum & 1) ? 0x80 : 0) + (checksum >> 1) + *pSname++;
306
307 // Start from current sector where space was found!
308 x = dirSector;
309
310 // Main cluster following loop
311 while (1)
312 {
313 // Read sector
314 if (fatfs_sector_reader(fs, dirCluster, x++, 0))
315 {
316 // Analyse Sector
317 for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
318 {
319 // Create the multiplier for sector access
320 recordoffset = FAT_DIR_ENTRY_SIZE * item;
321
322 // If the start position for the entry has been found
323 if (foundEnd==0)
324 if ( (dirSector==(x-1)) && (dirOffset==item) )
325 foundEnd = 1;
326
327 // Start adding filename
328 if (foundEnd)
329 {
330 if (entryCount==0)
331 {
332 // Short filename
333 fatfs_sfn_create_entry(shortfilename, size, startCluster, &shortEntry, dir);
334
335 #if FATFS_INC_TIME_DATE_SUPPORT
336 // Update create, access & modify time & date
337 fatfs_update_timestamps(&shortEntry, 1, 1, 1);
338 #endif
339
340 memcpy(&fs->currentsector.sector[recordoffset], &shortEntry, sizeof(shortEntry));
341
342 // Writeback
343 return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
344 }
345 #if FATFS_INC_LFN_SUPPORT
346 else
347 {
348 entryCount--;
349
350 // Copy entry to directory buffer
351 fatfs_filename_to_lfn(filename, &fs->currentsector.sector[recordoffset], entryCount, checksum);
352 dirtySector = 1;
353 }
354 #endif
355 }
356 } // End of if
357
358 // Write back to disk before loading another sector
359 if (dirtySector)
360 {
361 if (!fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1))
362 return 0;
363
364 dirtySector = 0;
365 }
366 }
367 else
368 return 0;
369 } // End of while loop
370
371 return 0;
372 }
373 #endif