1 /** @file 2 Helper functions for mangling file names in UDF/ECMA-167 file systems. 3 4 Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com> 5 6 SPDX-License-Identifier: BSD-2-Clause-Patent 7 **/ 8 9 #include "Udf.h" 10 11 /** 12 Trim the leading and trailing spaces for a give Unicode string. 13 14 @param[in] String The Unicode string to trim. 15 16 @return A pointer to the trimmed string. 17 18 **/ 19 CHAR16 * TrimString(IN CHAR16 * String)20TrimString ( 21 IN CHAR16 *String 22 ) 23 { 24 CHAR16 *TempString; 25 26 for ( ; *String != L'\0' && *String == L' '; String++) { 27 ; 28 } 29 30 TempString = String + StrLen (String) - 1; 31 while ((TempString >= String) && (*TempString == L' ')) { 32 TempString--; 33 } 34 35 *(TempString + 1) = L'\0'; 36 37 return String; 38 } 39 40 /** 41 Replace the content of a Unicode string with the content of another Unicode 42 string. 43 44 @param[in] Destination A pointer to a Unicode string. 45 @param[in] Source A pointer to a Unicode string. 46 47 **/ 48 VOID ReplaceLeft(IN CHAR16 * Destination,IN CONST CHAR16 * Source)49ReplaceLeft ( 50 IN CHAR16 *Destination, 51 IN CONST CHAR16 *Source 52 ) 53 { 54 CONST CHAR16 *EndString; 55 56 EndString = Source + StrLen (Source); 57 while (Source <= EndString) { 58 *Destination++ = *Source++; 59 } 60 } 61 62 /** 63 Remove one or more consecutive backslashes starting from the second character 64 of a given Unicode string. 65 66 @param[in] String A pointer to a Unicode string. 67 68 @return A pointer to the modified string. 69 70 **/ 71 CHAR16 * ExcludeTrailingBackslashes(IN CHAR16 * String)72ExcludeTrailingBackslashes ( 73 IN CHAR16 *String 74 ) 75 { 76 CHAR16 *TempString; 77 78 switch (*(String + 1)) { 79 case L'\\': 80 break; 81 case L'\0': 82 default: 83 String++; 84 goto Exit; 85 } 86 87 TempString = String; 88 while (*TempString != L'\0' && *TempString == L'\\') { 89 TempString++; 90 } 91 92 if (TempString - 1 > String) { 93 ReplaceLeft (String + 1, TempString); 94 } 95 96 String++; 97 98 Exit: 99 return String; 100 } 101 102 /** 103 Mangle a filename by cutting off trailing whitespaces, "\\", "." and "..". 104 105 @param[in] FileName Filename. 106 107 @retval The mangled Filename. 108 109 **/ 110 CHAR16 * MangleFileName(IN CHAR16 * FileName)111MangleFileName ( 112 IN CHAR16 *FileName 113 ) 114 { 115 CHAR16 *FileNameSavedPointer; 116 CHAR16 *TempFileName; 117 UINTN BackslashesNo; 118 119 if (FileName == NULL || *FileName == L'\0') { 120 FileName = NULL; 121 goto Exit; 122 } 123 124 FileName = TrimString (FileName); 125 if (*FileName == L'\0') { 126 goto Exit; 127 } 128 129 if ((StrLen (FileName) > 1) && (FileName[StrLen (FileName) - 1] == L'\\')) { 130 FileName[StrLen (FileName) - 1] = L'\0'; 131 } 132 133 FileNameSavedPointer = FileName; 134 135 if (FileName[0] == L'.') { 136 if (FileName[1] == L'.') { 137 if (FileName[2] == L'\0') { 138 goto Exit; 139 } else { 140 FileName += 2; 141 } 142 } else if (FileName[1] == L'\0') { 143 goto Exit; 144 } 145 } 146 147 while (*FileName != L'\0') { 148 if (*FileName == L'\\') { 149 FileName = ExcludeTrailingBackslashes (FileName); 150 } else if (*FileName == L'.') { 151 switch (*(FileName + 1)) { 152 case L'\0': 153 *FileName = L'\0'; 154 break; 155 case L'\\': 156 TempFileName = FileName + 1; 157 TempFileName = ExcludeTrailingBackslashes (TempFileName); 158 ReplaceLeft (FileName, TempFileName); 159 break; 160 case '.': 161 if ((*(FileName - 1) != L'\\') && ((*(FileName + 2) != L'\\') || 162 (*(FileName + 2) != L'\0'))) { 163 FileName++; 164 continue; 165 } 166 167 BackslashesNo = 0; 168 TempFileName = FileName - 1; 169 while (TempFileName >= FileNameSavedPointer) { 170 if (*TempFileName == L'\\') { 171 if (++BackslashesNo == 2) { 172 break; 173 } 174 } 175 176 TempFileName--; 177 } 178 179 TempFileName++; 180 181 if ((*TempFileName == L'.') && (*(TempFileName + 1) == L'.')) { 182 FileName += 2; 183 } else { 184 if (*(FileName + 2) != L'\0') { 185 ReplaceLeft (TempFileName, FileName + 3); 186 if (*(TempFileName - 1) == L'\\') { 187 FileName = TempFileName; 188 ExcludeTrailingBackslashes (TempFileName - 1); 189 TempFileName = FileName; 190 } 191 } else { 192 *TempFileName = L'\0'; 193 } 194 195 FileName = TempFileName; 196 } 197 198 break; 199 default: 200 FileName++; 201 } 202 } else { 203 FileName++; 204 } 205 } 206 207 FileName = FileNameSavedPointer; 208 if ((StrLen (FileName) > 1) && (FileName [StrLen (FileName) - 1] == L'\\')) { 209 FileName [StrLen (FileName) - 1] = L'\0'; 210 } 211 212 Exit: 213 return FileName; 214 } 215