3 Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Functions for manipulating file names
30 OUT CHAR8
*File8Dot3Name
36 This function checks whether the input FileName is a valid 8.3 short name.
37 If the input FileName is a valid 8.3, the output is the 8.3 short name;
38 otherwise, the output is the base tag of 8.3 short name.
42 FileName - The input unicode filename.
43 File8Dot3Name - The output ascii 8.3 short name or base tag of 8.3 short name.
47 TRUE - The input unicode filename is a valid 8.3 short name.
48 FALSE - The input unicode filename is not a valid 8.3 short name.
52 BOOLEAN PossibleShortName
;
59 PossibleShortName
= TRUE
;
61 SetMem (File8Dot3Name
, FAT_NAME_LEN
, ' ');
62 for (TempName
= FileName
; *TempName
; TempName
++) {
63 if (*TempName
== L
'.') {
64 SeparateDot
= TempName
;
68 if (SeparateDot
== NULL
) {
70 // Extended filename is not detected
72 MainNameLen
= TempName
- FileName
;
73 ExtendName
= TempName
;
77 // Extended filename is detected
79 MainNameLen
= SeparateDot
- FileName
;
80 ExtendName
= SeparateDot
+ 1;
81 ExtendNameLen
= TempName
- ExtendName
;
84 // We scan the filename for the second time
85 // to check if there exists any extra blanks and dots
87 while (--TempName
>= FileName
) {
88 if ((*TempName
== L
'.' || *TempName
== L
' ') && (TempName
!= SeparateDot
)) {
90 // There exist extra blanks and dots
92 PossibleShortName
= FALSE
;
96 if (MainNameLen
== 0) {
97 PossibleShortName
= FALSE
;
100 if (MainNameLen
> FAT_MAIN_NAME_LEN
) {
101 PossibleShortName
= FALSE
;
102 MainNameLen
= FAT_MAIN_NAME_LEN
;
105 if (ExtendNameLen
> FAT_EXTEND_NAME_LEN
) {
106 PossibleShortName
= FALSE
;
107 ExtendNameLen
= FAT_EXTEND_NAME_LEN
;
110 if (FatStrToFat (FileName
, MainNameLen
, File8Dot3Name
)) {
111 PossibleShortName
= FALSE
;
114 if (FatStrToFat (ExtendName
, ExtendNameLen
, File8Dot3Name
+ FAT_MAIN_NAME_LEN
)) {
115 PossibleShortName
= FALSE
;
118 return PossibleShortName
;
123 FatTrimAsciiTrailingBlanks (
131 Trim the trailing blanks of fat name.
135 Name - The Char8 string needs to be trimed.
136 Len - The length of the fat name.
140 The real length of the fat name after the trailing blanks are trimmed.
144 while (Len
> 0 && Name
[Len
- 1] == ' ') {
162 Convert the ascii fat name to the unicode string and strip trailing spaces,
163 and if necessary, convert the unicode string to lower case.
167 FatName - The Char8 string needs to be converted.
168 Len - The length of the fat name.
169 LowerCase - Indicate whether to convert the string to lower case.
170 Str - The result of the convertion.
179 // First, trim the trailing blanks
181 Len
= FatTrimAsciiTrailingBlanks (FatName
, Len
);
183 // Convert fat string to unicode string
185 FatFatToStr (Len
, FatName
, Str
);
188 // If the name is to be lower cased, do it now
190 if (LowerCase
!= 0) {
197 IN FAT_OFILE
*Parent
,
198 IN FAT_DIRENT
*DirEnt
204 This function generates 8Dot3 name from user specified name for a newly created file.
208 Parent - The parent directory.
209 DirEnt - The directory entry whose 8Dot3Name needs to be generated.
218 CHAR8
*ShortNameChar
;
226 UINT8 Segment
: HASH_VALUE_TAG_LEN
;
227 } Hex
[HASH_VALUE_TAG_LEN
];
230 // Make sure the whole directory has been loaded
232 ASSERT (Parent
->ODir
->EndOfDir
);
233 ShortName
= DirEnt
->Entry
.FileName
;
236 // Trim trailing blanks of 8.3 name
238 BaseTagLen
= FatTrimAsciiTrailingBlanks (ShortName
, FAT_MAIN_NAME_LEN
);
239 if (BaseTagLen
> SPEC_BASE_TAG_LEN
) {
240 BaseTagLen
= SPEC_BASE_TAG_LEN
;
243 // We first use the algorithm described by spec.
245 ShortNameChar
= ShortName
+ BaseTagLen
;
246 *ShortNameChar
++ = '~';
247 *ShortNameChar
= '1';
249 while (*FatShortNameHashSearch (Parent
->ODir
, ShortName
) != NULL
) {
250 *ShortNameChar
= (CHAR8
)(*ShortNameChar
+ 1);
251 if (++Retry
== MAX_SPEC_RETRY
) {
253 // We use new algorithm to generate 8.3 name
255 ASSERT (DirEnt
->FileString
!= NULL
);
256 gBS
->CalculateCrc32 (DirEnt
->FileString
, StrSize (DirEnt
->FileString
), &HashValue
.Crc
);
258 if (BaseTagLen
> HASH_BASE_TAG_LEN
) {
259 BaseTagLen
= HASH_BASE_TAG_LEN
;
262 ShortNameChar
= ShortName
+ BaseTagLen
;
263 for (Index
= 0; Index
< HASH_VALUE_TAG_LEN
; Index
++) {
264 Segment
= HashValue
.Hex
[Index
].Segment
;
266 *ShortNameChar
++ = (CHAR8
)(Segment
- 10 + 'A');
268 *ShortNameChar
++ = (CHAR8
)(Segment
+ '0');
272 *ShortNameChar
++ = '~';
273 *ShortNameChar
= '1';
288 Check the string is lower case or upper case
289 and it is used by fatname to dir entry count
293 Str - The string which needs to be checked.
294 InCaseFlag - The input case flag which is returned when the string is lower case.
298 OutCaseFlag - The output case flag.
302 CHAR16 Buffer
[FAT_MAIN_NAME_LEN
+ 1 + FAT_EXTEND_NAME_LEN
+ 1];
306 // Assume the case of input string is mixed
308 OutCaseFlag
= FAT_CASE_MIXED
;
310 // Lower case a copy of the string, if it matches the
311 // original then the string is lower case
313 StrCpyS (Buffer
, ARRAY_SIZE (Buffer
), Str
);
315 if (StrCmp (Str
, Buffer
) == 0) {
316 OutCaseFlag
= InCaseFlag
;
319 // Upper case a copy of the string, if it matches the
320 // original then the string is upper case
322 StrCpyS (Buffer
, ARRAY_SIZE (Buffer
), Str
);
324 if (StrCmp (Str
, Buffer
) == 0) {
333 IN FAT_DIRENT
*DirEnt
339 Set the caseflag value for the directory entry.
343 DirEnt - The logical directory entry whose caseflag value is to be set.
351 CHAR16 LfnBuffer
[FAT_MAIN_NAME_LEN
+ 1 + FAT_EXTEND_NAME_LEN
+ 1];
354 CHAR16
*FileNameCharPtr
;
358 TempCharPtr
= LfnBuffer
;
359 FileNameCharPtr
= DirEnt
->FileString
;
360 ASSERT (StrSize (DirEnt
->FileString
) <= sizeof (LfnBuffer
));
361 while ((*TempCharPtr
= *FileNameCharPtr
) != 0) {
362 if (*TempCharPtr
== L
'.') {
363 ExtendName
= TempCharPtr
;
371 if (ExtendName
!= NULL
) {
374 CaseFlag
= (UINT8
)(CaseFlag
| FatCheckNameCase (ExtendName
, FAT_CASE_EXT_LOWER
));
377 CaseFlag
= (UINT8
)(CaseFlag
| FatCheckNameCase (LfnBuffer
, FAT_CASE_NAME_LOWER
));
378 if ((CaseFlag
& FAT_CASE_MIXED
) == 0) {
380 // We just need one directory entry to store this file name entry
382 DirEnt
->Entry
.CaseFlag
= CaseFlag
;
385 // We need one extra directory entry to store the mixed case entry
387 DirEnt
->Entry
.CaseFlag
= 0;
388 DirEnt
->EntryCount
++;
393 FatGetFileNameViaCaseFlag (
394 IN FAT_DIRENT
*DirEnt
,
395 IN OUT CHAR16
*FileString
,
396 IN UINTN FileStringMax
402 Convert the 8.3 ASCII fat name to cased Unicode string according to case flag.
406 DirEnt - The corresponding directory entry.
407 FileString - The output Unicode file name.
416 CHAR8
*File8Dot3Name
;
417 CHAR16 TempExt
[1 + FAT_EXTEND_NAME_LEN
+ 1];
419 // Store file extension like ".txt"
421 CaseFlag
= DirEnt
->Entry
.CaseFlag
;
422 File8Dot3Name
= DirEnt
->Entry
.FileName
;
424 FatNameToStr (File8Dot3Name
, FAT_MAIN_NAME_LEN
, CaseFlag
& FAT_CASE_NAME_LOWER
, FileString
);
425 FatNameToStr (File8Dot3Name
+ FAT_MAIN_NAME_LEN
, FAT_EXTEND_NAME_LEN
, CaseFlag
& FAT_CASE_EXT_LOWER
, &TempExt
[1]);
426 if (TempExt
[1] != 0) {
428 StrCatS (FileString
, FileStringMax
, TempExt
);
434 IN CHAR8
*ShortNameString
440 Get the Check sum for a short name.
444 ShortNameString - The short name for a file.
448 Sum - UINT8 checksum.
455 for (ShortNameLen
= FAT_NAME_LEN
; ShortNameLen
!= 0; ShortNameLen
--) {
456 Sum
= (UINT8
)(((Sum
& 1) ? 0x80 : 0) + (Sum
>> 1) + *ShortNameString
++);
463 FatGetNextNameComponent (
471 Takes Path as input, returns the next name component
472 in Name, and returns the position after Name (e.g., the
473 start of the next name component)
477 Path - The path of one file.
478 Name - The next name component in Path.
482 The position after Name in the Path
486 while (*Path
!= 0 && *Path
!= PATH_NAME_SEPARATOR
) {
491 // Get off of trailing path name separator
493 while (*Path
== PATH_NAME_SEPARATOR
) {
502 IN CHAR16
*InputFileName
,
503 OUT CHAR16
*OutputFileName
509 Check whether the IFileName is valid long file name. If the IFileName is a valid
510 long file name, then we trim the possible leading blanks and leading/trailing dots.
511 the trimmed filename is stored in OutputFileName
515 InputFileName - The input file name.
516 OutputFileName - The output file name.
521 TRUE - The InputFileName is a valid long file name.
522 FALSE - The InputFileName is not a valid long file name.
526 CHAR16
*TempNamePointer
;
529 // Trim Leading blanks
531 while (*InputFileName
== L
' ') {
535 TempNamePointer
= OutputFileName
;
536 while (*InputFileName
!= 0) {
537 *TempNamePointer
++ = *InputFileName
++;
540 // Trim Trailing blanks and dots
542 while (TempNamePointer
> OutputFileName
) {
543 TempChar
= *(TempNamePointer
- 1);
544 if (TempChar
!= L
' ' && TempChar
!= L
'.') {
551 *TempNamePointer
= 0;
554 // Per FAT Spec the file name should meet the following criteria:
555 // C1. Length (FileLongName) <= 255
556 // C2. Length (X:FileFullPath<NUL>) <= 260
559 if (TempNamePointer
- OutputFileName
> EFI_FILE_STRING_LENGTH
) {
563 // See if there is any illegal characters within the name
566 if (*OutputFileName
< 0x20 ||
567 *OutputFileName
== '\"' ||
568 *OutputFileName
== '*' ||
569 *OutputFileName
== '/' ||
570 *OutputFileName
== ':' ||
571 *OutputFileName
== '<' ||
572 *OutputFileName
== '>' ||
573 *OutputFileName
== '?' ||
574 *OutputFileName
== '\\' ||
575 *OutputFileName
== '|'
581 } while (*OutputFileName
!= 0);