]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - LinuxGUI/Ventoy2Disk/Lib/fat_io_lib/fat_misc.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 //-----------------------------------------------------------------------------
36 //-----------------------------------------------------------------------------
37 // fatfs_lfn_cache_init: Clear long file name cache
38 //-----------------------------------------------------------------------------
39 void fatfs_lfn_cache_init(struct lfn_cache
*lfn
, int wipeTable
)
43 lfn
->no_of_strings
= 0;
45 #if FATFS_INC_LFN_SUPPORT
47 // Zero out buffer also
49 for (i
=0;i
<MAX_LONGFILENAME_ENTRIES
;i
++)
50 memset(lfn
->String
[i
], 0x00, MAX_LFN_ENTRY_LENGTH
);
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
)
61 LFNIndex
= entryBuffer
[0] & 0x1F;
63 // Limit file name to cache size!
64 if (LFNIndex
> MAX_LONGFILENAME_ENTRIES
)
67 // This is an error condition
71 if (lfn
->no_of_strings
== 0)
72 lfn
->no_of_strings
= LFNIndex
;
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];
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
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
)
99 // Null terminate long filename
100 if (lfn
->no_of_strings
== MAX_LONGFILENAME_ENTRIES
)
102 else if (lfn
->no_of_strings
)
103 lfn
->String
[lfn
->no_of_strings
][0] = '\0';
105 lfn
->String
[0][0] = '\0';
107 return (char*)&lfn
->String
[0][0];
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
)
116 if ((entry
->Attr
& FILE_ATTR_LFN_TEXT
) == FILE_ATTR_LFN_TEXT
)
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
)
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
) )
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
)
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
) )
154 //-----------------------------------------------------------------------------
155 // fatfs_entry_sfn_only: If SFN only exists
156 //-----------------------------------------------------------------------------
157 int fatfs_entry_sfn_only(struct fat_dir_entry
*entry
)
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
)) )
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
)
174 if (entry
->Attr
& FILE_TYPE_DIR
)
179 //-----------------------------------------------------------------------------
180 // fatfs_entry_is_file: Returns 1 is a file entry
181 //-----------------------------------------------------------------------------
182 int fatfs_entry_is_file(struct fat_dir_entry
*entry
)
184 if (entry
->Attr
& FILE_TYPE_FILE
)
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
)
195 int length
= (int)strlen(filename
);
198 return (length
+ MAX_LFN_ENTRY_LENGTH
- 1) / MAX_LFN_ENTRY_LENGTH
;
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
)
210 int nameIndexes
[MAX_LFN_ENTRY_LENGTH
] = {1,3,5,7,9,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E};
212 // 13 characters entries
213 int length
= (int)strlen(filename
);
214 int entriesRequired
= fatfs_lfn_entries_required(filename
);
217 int start
= entry
* MAX_LFN_ENTRY_LENGTH
;
219 // Initialise to zeros
220 memset(buffer
, 0x00, FAT_DIR_ENTRY_SIZE
);
223 buffer
[0] = (uint8
)(((entriesRequired
-1)==entry
)?(0x40|(entry
+1)):(entry
+1));
228 // Checksum of short filename
232 for (i
=0;i
<MAX_LFN_ENTRY_LENGTH
;i
++)
234 if ( (start
+i
) < length
)
235 buffer
[nameIndexes
[i
]] = filename
[start
+i
];
236 else if ( (start
+i
) == length
)
237 buffer
[nameIndexes
[i
]] = 0x00;
240 buffer
[nameIndexes
[i
]] = 0xFF;
241 buffer
[nameIndexes
[i
]+1] = 0xFF;
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
)
254 // Copy short filename
255 for (i
=0;i
<FAT_SFN_SIZE_FULL
;i
++)
256 entry
->Name
[i
] = shortfilename
[i
];
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;
270 entry
->Attr
= FILE_TYPE_FILE
;
272 entry
->Attr
= FILE_TYPE_DIR
;
276 entry
->FstClusHI
= FAT_HTONS((uint16
)((startCluster
>>16) & 0xFFFF));
277 entry
->FstClusLO
= FAT_HTONS((uint16
)((startCluster
>>0) & 0xFFFF));
278 entry
->FileSize
= FAT_HTONL(size
);
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
)
291 int len
= (int)strlen(filename
);
293 // Invalid to start with .
294 if (filename
[0]=='.')
297 memset(sfn_output
, ' ', FAT_SFN_SIZE_FULL
);
300 // Find dot seperator
301 for (i
= 0; i
< len
; i
++)
303 if (filename
[i
]=='.')
307 // Extract extensions
310 // Copy first three chars of extension
311 for (i
= (dotPos
+1); i
< (dotPos
+1+3); i
++)
313 ext
[i
-(dotPos
+1)] = filename
[i
];
315 // Shorten the length to the dot position
323 if ( (filename
[i
]!=' ') && (filename
[i
]!='.') )
325 if (filename
[i
] >= 'a' && filename
[i
] <= 'z')
326 sfn_output
[pos
++] = filename
[i
] - 'a' + 'A';
328 sfn_output
[pos
++] = filename
[i
];
331 // Fill upto 8 characters
332 if (pos
==FAT_SFN_SIZE_PARTIAL
)
336 // Add extension part
337 for (i
=FAT_SFN_SIZE_PARTIAL
;i
<FAT_SFN_SIZE_FULL
;i
++)
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';
342 sfn_output
[i
] = ext
[i
-FAT_SFN_SIZE_PARTIAL
];
347 //-----------------------------------------------------------------------------
349 //-----------------------------------------------------------------------------
350 static void fatfs_itoa(uint32 num
, char *s
)
354 const char digits
[] = "0123456789ABCDEF";
356 // Build string backwards
360 *cp
++ = digits
[(int)(num
% 10)];
362 while ((num
/= 10) > 0);
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
)
389 memset(tail_str
, 0x00, sizeof(tail_str
));
391 fatfs_itoa(tailNum
, tail_str
+1);
393 // Copy in base filename
394 memcpy(sfn_output
, sfn_input
, FAT_SFN_SIZE_FULL
);
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
);
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
)
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
;
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
)
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
;
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
)
432 // Most FAT times are to a resolution of 2 seconds
433 seconds
/= FAT_TIME_SECONDS_SCALE
;
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
;
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
)
448 // FAT dates are relative to 1980
449 if (year
>= FAT_DATE_YEAR_OFFSET
)
450 year
-= FAT_DATE_YEAR_OFFSET
;
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
;
459 //-----------------------------------------------------------------------------
460 // fatfs_print_sector:
461 //-----------------------------------------------------------------------------
463 void fatfs_print_sector(uint32 sector
, uint8
*data
)
468 FAT_PRINTF(("Sector %d:\n", sector
));
470 for (i
=0;i
<FAT_SECTOR_SIZE
;i
++)
474 FAT_PRINTF((" %04d: ", i
));
477 FAT_PRINTF(("%02x", data
[i
]));
488 char ch
= data
[i
-15+j
];
491 if (ch
> 31 && ch
< 127)
493 FAT_PRINTF(("%c", ch
));