]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - LinuxGUI/Ventoy2Disk/Lib/fat_io_lib/fat_misc.c
VentoyPlugson ---- A GUI ventoy.json configurator
[Ventoy.git] / LinuxGUI / Ventoy2Disk / Lib / fat_io_lib / fat_misc.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 <stdlib.h>
33 #include <string.h>
34 #include "fat_misc.h"
35
36 //-----------------------------------------------------------------------------
37 // fatfs_lfn_cache_init: Clear long file name cache
38 //-----------------------------------------------------------------------------
39 void fatfs_lfn_cache_init(struct lfn_cache *lfn, int wipeTable)
40 {
41 int i = 0;
42
43 lfn->no_of_strings = 0;
44
45 #if FATFS_INC_LFN_SUPPORT
46
47 // Zero out buffer also
48 if (wipeTable)
49 for (i=0;i<MAX_LONGFILENAME_ENTRIES;i++)
50 memset(lfn->String[i], 0x00, MAX_LFN_ENTRY_LENGTH);
51 #endif
52 }
53 //-----------------------------------------------------------------------------
54 // fatfs_lfn_cache_entry - Function extracts long file name text from sector
55 // at a specific offset
56 //-----------------------------------------------------------------------------
57 #if FATFS_INC_LFN_SUPPORT
58 void fatfs_lfn_cache_entry(struct lfn_cache *lfn, uint8 *entryBuffer)
59 {
60 uint8 LFNIndex, i;
61 LFNIndex = entryBuffer[0] & 0x1F;
62
63 // Limit file name to cache size!
64 if (LFNIndex > MAX_LONGFILENAME_ENTRIES)
65 return ;
66
67 // This is an error condition
68 if (LFNIndex == 0)
69 return ;
70
71 if (lfn->no_of_strings == 0)
72 lfn->no_of_strings = LFNIndex;
73
74 lfn->String[LFNIndex-1][0] = entryBuffer[1];
75 lfn->String[LFNIndex-1][1] = entryBuffer[3];
76 lfn->String[LFNIndex-1][2] = entryBuffer[5];
77 lfn->String[LFNIndex-1][3] = entryBuffer[7];
78 lfn->String[LFNIndex-1][4] = entryBuffer[9];
79 lfn->String[LFNIndex-1][5] = entryBuffer[0x0E];
80 lfn->String[LFNIndex-1][6] = entryBuffer[0x10];
81 lfn->String[LFNIndex-1][7] = entryBuffer[0x12];
82 lfn->String[LFNIndex-1][8] = entryBuffer[0x14];
83 lfn->String[LFNIndex-1][9] = entryBuffer[0x16];
84 lfn->String[LFNIndex-1][10] = entryBuffer[0x18];
85 lfn->String[LFNIndex-1][11] = entryBuffer[0x1C];
86 lfn->String[LFNIndex-1][12] = entryBuffer[0x1E];
87
88 for (i=0; i<MAX_LFN_ENTRY_LENGTH; i++)
89 if (lfn->String[LFNIndex-1][i]==0xFF)
90 lfn->String[LFNIndex-1][i] = 0x20; // Replace with spaces
91 }
92 #endif
93 //-----------------------------------------------------------------------------
94 // fatfs_lfn_cache_get: Get a reference to the long filename
95 //-----------------------------------------------------------------------------
96 #if FATFS_INC_LFN_SUPPORT
97 char* fatfs_lfn_cache_get(struct lfn_cache *lfn)
98 {
99 // Null terminate long filename
100 if (lfn->no_of_strings == MAX_LONGFILENAME_ENTRIES)
101 lfn->Null = '\0';
102 else if (lfn->no_of_strings)
103 lfn->String[lfn->no_of_strings][0] = '\0';
104 else
105 lfn->String[0][0] = '\0';
106
107 return (char*)&lfn->String[0][0];
108 }
109 #endif
110 //-----------------------------------------------------------------------------
111 // fatfs_entry_lfn_text: If LFN text entry found
112 //-----------------------------------------------------------------------------
113 #if FATFS_INC_LFN_SUPPORT
114 int fatfs_entry_lfn_text(struct fat_dir_entry *entry)
115 {
116 if ((entry->Attr & FILE_ATTR_LFN_TEXT) == FILE_ATTR_LFN_TEXT)
117 return 1;
118 else
119 return 0;
120 }
121 #endif
122 //-----------------------------------------------------------------------------
123 // fatfs_entry_lfn_invalid: If SFN found not relating to LFN
124 //-----------------------------------------------------------------------------
125 #if FATFS_INC_LFN_SUPPORT
126 int fatfs_entry_lfn_invalid(struct fat_dir_entry *entry)
127 {
128 if ( (entry->Name[0]==FILE_HEADER_BLANK) ||
129 (entry->Name[0]==FILE_HEADER_DELETED)||
130 (entry->Attr==FILE_ATTR_VOLUME_ID) ||
131 (entry->Attr & FILE_ATTR_SYSHID) )
132 return 1;
133 else
134 return 0;
135 }
136 #endif
137 //-----------------------------------------------------------------------------
138 // fatfs_entry_lfn_exists: If LFN exists and correlation SFN found
139 //-----------------------------------------------------------------------------
140 #if FATFS_INC_LFN_SUPPORT
141 int fatfs_entry_lfn_exists(struct lfn_cache *lfn, struct fat_dir_entry *entry)
142 {
143 if ( (entry->Attr!=FILE_ATTR_LFN_TEXT) &&
144 (entry->Name[0]!=FILE_HEADER_BLANK) &&
145 (entry->Name[0]!=FILE_HEADER_DELETED) &&
146 (entry->Attr!=FILE_ATTR_VOLUME_ID) &&
147 (!(entry->Attr&FILE_ATTR_SYSHID)) &&
148 (lfn->no_of_strings) )
149 return 1;
150 else
151 return 0;
152 }
153 #endif
154 //-----------------------------------------------------------------------------
155 // fatfs_entry_sfn_only: If SFN only exists
156 //-----------------------------------------------------------------------------
157 int fatfs_entry_sfn_only(struct fat_dir_entry *entry)
158 {
159 if ( (entry->Attr!=FILE_ATTR_LFN_TEXT) &&
160 (entry->Name[0]!=FILE_HEADER_BLANK) &&
161 (entry->Name[0]!=FILE_HEADER_DELETED) &&
162 (entry->Attr!=FILE_ATTR_VOLUME_ID) &&
163 (!(entry->Attr&FILE_ATTR_SYSHID)) )
164 return 1;
165 else
166 return 0;
167 }
168 // TODO: FILE_ATTR_SYSHID ?!?!??!
169 //-----------------------------------------------------------------------------
170 // fatfs_entry_is_dir: Returns 1 if a directory
171 //-----------------------------------------------------------------------------
172 int fatfs_entry_is_dir(struct fat_dir_entry *entry)
173 {
174 if (entry->Attr & FILE_TYPE_DIR)
175 return 1;
176 else
177 return 0;
178 }
179 //-----------------------------------------------------------------------------
180 // fatfs_entry_is_file: Returns 1 is a file entry
181 //-----------------------------------------------------------------------------
182 int fatfs_entry_is_file(struct fat_dir_entry *entry)
183 {
184 if (entry->Attr & FILE_TYPE_FILE)
185 return 1;
186 else
187 return 0;
188 }
189 //-----------------------------------------------------------------------------
190 // fatfs_lfn_entries_required: Calculate number of 13 characters entries
191 //-----------------------------------------------------------------------------
192 #if FATFS_INC_LFN_SUPPORT
193 int fatfs_lfn_entries_required(char *filename)
194 {
195 int length = (int)strlen(filename);
196
197 if (length)
198 return (length + MAX_LFN_ENTRY_LENGTH - 1) / MAX_LFN_ENTRY_LENGTH;
199 else
200 return 0;
201 }
202 #endif
203 //-----------------------------------------------------------------------------
204 // fatfs_filename_to_lfn:
205 //-----------------------------------------------------------------------------
206 #if FATFS_INC_LFN_SUPPORT
207 void fatfs_filename_to_lfn(char *filename, uint8 *buffer, int entry, uint8 sfnChk)
208 {
209 int i;
210 int nameIndexes[MAX_LFN_ENTRY_LENGTH] = {1,3,5,7,9,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E};
211
212 // 13 characters entries
213 int length = (int)strlen(filename);
214 int entriesRequired = fatfs_lfn_entries_required(filename);
215
216 // Filename offset
217 int start = entry * MAX_LFN_ENTRY_LENGTH;
218
219 // Initialise to zeros
220 memset(buffer, 0x00, FAT_DIR_ENTRY_SIZE);
221
222 // LFN entry number
223 buffer[0] = (uint8)(((entriesRequired-1)==entry)?(0x40|(entry+1)):(entry+1));
224
225 // LFN flag
226 buffer[11] = 0x0F;
227
228 // Checksum of short filename
229 buffer[13] = sfnChk;
230
231 // Copy to buffer
232 for (i=0;i<MAX_LFN_ENTRY_LENGTH;i++)
233 {
234 if ( (start+i) < length )
235 buffer[nameIndexes[i]] = filename[start+i];
236 else if ( (start+i) == length )
237 buffer[nameIndexes[i]] = 0x00;
238 else
239 {
240 buffer[nameIndexes[i]] = 0xFF;
241 buffer[nameIndexes[i]+1] = 0xFF;
242 }
243 }
244 }
245 #endif
246 //-----------------------------------------------------------------------------
247 // fatfs_sfn_create_entry: Create the short filename directory entry
248 //-----------------------------------------------------------------------------
249 #if FATFS_INC_WRITE_SUPPORT
250 void fatfs_sfn_create_entry(char *shortfilename, uint32 size, uint32 startCluster, struct fat_dir_entry *entry, int dir)
251 {
252 int i;
253
254 // Copy short filename
255 for (i=0;i<FAT_SFN_SIZE_FULL;i++)
256 entry->Name[i] = shortfilename[i];
257
258 // Unless we have a RTC we might as well set these to 1980
259 entry->CrtTimeTenth = 0x00;
260 entry->CrtTime[1] = entry->CrtTime[0] = 0x00;
261 entry->CrtDate[1] = 0x00;
262 entry->CrtDate[0] = 0x20;
263 entry->LstAccDate[1] = 0x00;
264 entry->LstAccDate[0] = 0x20;
265 entry->WrtTime[1] = entry->WrtTime[0] = 0x00;
266 entry->WrtDate[1] = 0x00;
267 entry->WrtDate[0] = 0x20;
268
269 if (!dir)
270 entry->Attr = FILE_TYPE_FILE;
271 else
272 entry->Attr = FILE_TYPE_DIR;
273
274 entry->NTRes = 0x00;
275
276 entry->FstClusHI = FAT_HTONS((uint16)((startCluster>>16) & 0xFFFF));
277 entry->FstClusLO = FAT_HTONS((uint16)((startCluster>>0) & 0xFFFF));
278 entry->FileSize = FAT_HTONL(size);
279 }
280 #endif
281 //-----------------------------------------------------------------------------
282 // fatfs_lfn_create_sfn: Create a padded SFN
283 //-----------------------------------------------------------------------------
284 #if FATFS_INC_WRITE_SUPPORT
285 int fatfs_lfn_create_sfn(char *sfn_output, char *filename)
286 {
287 int i;
288 int dotPos = -1;
289 char ext[3];
290 int pos;
291 int len = (int)strlen(filename);
292
293 // Invalid to start with .
294 if (filename[0]=='.')
295 return 0;
296
297 memset(sfn_output, ' ', FAT_SFN_SIZE_FULL);
298 memset(ext, ' ', 3);
299
300 // Find dot seperator
301 for (i = 0; i< len; i++)
302 {
303 if (filename[i]=='.')
304 dotPos = i;
305 }
306
307 // Extract extensions
308 if (dotPos!=-1)
309 {
310 // Copy first three chars of extension
311 for (i = (dotPos+1); i < (dotPos+1+3); i++)
312 if (i<len)
313 ext[i-(dotPos+1)] = filename[i];
314
315 // Shorten the length to the dot position
316 len = dotPos;
317 }
318
319 // Add filename part
320 pos = 0;
321 for (i=0;i<len;i++)
322 {
323 if ( (filename[i]!=' ') && (filename[i]!='.') )
324 {
325 if (filename[i] >= 'a' && filename[i] <= 'z')
326 sfn_output[pos++] = filename[i] - 'a' + 'A';
327 else
328 sfn_output[pos++] = filename[i];
329 }
330
331 // Fill upto 8 characters
332 if (pos==FAT_SFN_SIZE_PARTIAL)
333 break;
334 }
335
336 // Add extension part
337 for (i=FAT_SFN_SIZE_PARTIAL;i<FAT_SFN_SIZE_FULL;i++)
338 {
339 if (ext[i-FAT_SFN_SIZE_PARTIAL] >= 'a' && ext[i-FAT_SFN_SIZE_PARTIAL] <= 'z')
340 sfn_output[i] = ext[i-FAT_SFN_SIZE_PARTIAL] - 'a' + 'A';
341 else
342 sfn_output[i] = ext[i-FAT_SFN_SIZE_PARTIAL];
343 }
344
345 return 1;
346 }
347 //-----------------------------------------------------------------------------
348 // fatfs_itoa:
349 //-----------------------------------------------------------------------------
350 static void fatfs_itoa(uint32 num, char *s)
351 {
352 char* cp;
353 char outbuf[12];
354 const char digits[] = "0123456789ABCDEF";
355
356 // Build string backwards
357 cp = outbuf;
358 do
359 {
360 *cp++ = digits[(int)(num % 10)];
361 }
362 while ((num /= 10) > 0);
363
364 *cp-- = 0;
365
366 // Copy in forwards
367 while (cp >= outbuf)
368 *s++ = *cp--;
369
370 *s = 0;
371 }
372 #endif
373 //-----------------------------------------------------------------------------
374 // fatfs_lfn_generate_tail:
375 // sfn_input = Input short filename, spaced format & in upper case
376 // sfn_output = Output short filename with tail
377 //-----------------------------------------------------------------------------
378 #if FATFS_INC_LFN_SUPPORT
379 #if FATFS_INC_WRITE_SUPPORT
380 int fatfs_lfn_generate_tail(char *sfn_output, char *sfn_input, uint32 tailNum)
381 {
382 int tail_chars;
383 char tail_str[12];
384
385 if (tailNum > 99999)
386 return 0;
387
388 // Convert to number
389 memset(tail_str, 0x00, sizeof(tail_str));
390 tail_str[0] = '~';
391 fatfs_itoa(tailNum, tail_str+1);
392
393 // Copy in base filename
394 memcpy(sfn_output, sfn_input, FAT_SFN_SIZE_FULL);
395
396 // Overwrite with tail
397 tail_chars = (int)strlen(tail_str);
398 memcpy(sfn_output+(FAT_SFN_SIZE_PARTIAL-tail_chars), tail_str, tail_chars);
399
400 return 1;
401 }
402 #endif
403 #endif
404 //-----------------------------------------------------------------------------
405 // fatfs_convert_from_fat_time: Convert FAT time to h/m/s
406 //-----------------------------------------------------------------------------
407 #if FATFS_INC_TIME_DATE_SUPPORT
408 void fatfs_convert_from_fat_time(uint16 fat_time, int *hours, int *minutes, int *seconds)
409 {
410 *hours = (fat_time >> FAT_TIME_HOURS_SHIFT) & FAT_TIME_HOURS_MASK;
411 *minutes = (fat_time >> FAT_TIME_MINUTES_SHIFT) & FAT_TIME_MINUTES_MASK;
412 *seconds = (fat_time >> FAT_TIME_SECONDS_SHIFT) & FAT_TIME_SECONDS_MASK;
413 *seconds = *seconds * FAT_TIME_SECONDS_SCALE;
414 }
415 //-----------------------------------------------------------------------------
416 // fatfs_convert_from_fat_date: Convert FAT date to d/m/y
417 //-----------------------------------------------------------------------------
418 void fatfs_convert_from_fat_date(uint16 fat_date, int *day, int *month, int *year)
419 {
420 *day = (fat_date >> FAT_DATE_DAY_SHIFT) & FAT_DATE_DAY_MASK;
421 *month = (fat_date >> FAT_DATE_MONTH_SHIFT) & FAT_DATE_MONTH_MASK;
422 *year = (fat_date >> FAT_DATE_YEAR_SHIFT) & FAT_DATE_YEAR_MASK;
423 *year = *year + FAT_DATE_YEAR_OFFSET;
424 }
425 //-----------------------------------------------------------------------------
426 // fatfs_convert_to_fat_time: Convert h/m/s to FAT time
427 //-----------------------------------------------------------------------------
428 uint16 fatfs_convert_to_fat_time(int hours, int minutes, int seconds)
429 {
430 uint16 fat_time = 0;
431
432 // Most FAT times are to a resolution of 2 seconds
433 seconds /= FAT_TIME_SECONDS_SCALE;
434
435 fat_time = (hours & FAT_TIME_HOURS_MASK) << FAT_TIME_HOURS_SHIFT;
436 fat_time|= (minutes & FAT_TIME_MINUTES_MASK) << FAT_TIME_MINUTES_SHIFT;
437 fat_time|= (seconds & FAT_TIME_SECONDS_MASK) << FAT_TIME_SECONDS_SHIFT;
438
439 return fat_time;
440 }
441 //-----------------------------------------------------------------------------
442 // fatfs_convert_to_fat_date: Convert d/m/y to FAT date
443 //-----------------------------------------------------------------------------
444 uint16 fatfs_convert_to_fat_date(int day, int month, int year)
445 {
446 uint16 fat_date = 0;
447
448 // FAT dates are relative to 1980
449 if (year >= FAT_DATE_YEAR_OFFSET)
450 year -= FAT_DATE_YEAR_OFFSET;
451
452 fat_date = (day & FAT_DATE_DAY_MASK) << FAT_DATE_DAY_SHIFT;
453 fat_date|= (month & FAT_DATE_MONTH_MASK) << FAT_DATE_MONTH_SHIFT;
454 fat_date|= (year & FAT_DATE_YEAR_MASK) << FAT_DATE_YEAR_SHIFT;
455
456 return fat_date;
457 }
458 #endif
459 //-----------------------------------------------------------------------------
460 // fatfs_print_sector:
461 //-----------------------------------------------------------------------------
462 #ifdef FATFS_DEBUG
463 void fatfs_print_sector(uint32 sector, uint8 *data)
464 {
465 int i;
466 int j;
467
468 FAT_PRINTF(("Sector %d:\n", sector));
469
470 for (i=0;i<FAT_SECTOR_SIZE;i++)
471 {
472 if (!((i) % 16))
473 {
474 FAT_PRINTF((" %04d: ", i));
475 }
476
477 FAT_PRINTF(("%02x", data[i]));
478 if (!((i+1) % 4))
479 {
480 FAT_PRINTF((" "));
481 }
482
483 if (!((i+1) % 16))
484 {
485 FAT_PRINTF((" "));
486 for (j=0;j<16;j++)
487 {
488 char ch = data[i-15+j];
489
490 // Is printable?
491 if (ch > 31 && ch < 127)
492 {
493 FAT_PRINTF(("%c", ch));
494 }
495 else
496 {
497 FAT_PRINTF(("."));
498 }
499 }
500
501 FAT_PRINTF(("\n"));
502 }
503 }
504 }
505 #endif