32 |
41 |
33 LOCAL_C TBool IsLegalChar(TChar aCharacter,TBool aAllowWildChars,TBool aUseExtendedChars=EFalse,TBool aInScanDrive=EFalse) |
42 LOCAL_C TBool IsLegalChar(TChar aCharacter,TBool aAllowWildChars,TBool aUseExtendedChars=EFalse,TBool aInScanDrive=EFalse) |
34 // |
43 // |
35 // Returns ETrue if aCharacter is legal inside a dos filename |
44 // Returns ETrue if aCharacter is legal inside a dos filename |
36 // |
45 // |
37 { |
46 { |
38 if ((aCharacter==KMatchOne) || (aCharacter==KMatchAny)) |
47 if ((aCharacter==KMatchOne) || (aCharacter==KMatchAny)) |
39 return(aAllowWildChars); |
48 return(aAllowWildChars); |
40 if ((TUint)aCharacter < 0x20) |
49 if ((TUint)aCharacter < 0x20) |
41 return EFalse; |
50 return EFalse; |
42 // Don't check illegal ascii char because some non-English char value may |
51 // Don't check illegal ascii char because some non-English char value may |
43 // fall in this area |
52 // fall in this area |
44 if (aInScanDrive) |
53 if (aInScanDrive) |
45 return ETrue; |
54 return ETrue; |
46 return LocaleUtils::IsLegalShortNameCharacter(aCharacter,aUseExtendedChars); |
55 return LocaleUtils::IsLegalShortNameCharacter(aCharacter,aUseExtendedChars); |
47 } |
56 } |
48 |
57 |
49 LOCAL_C void ReplaceFirstCharacterIfClashesWithE5L(TDes8& aShortName) |
58 LOCAL_C void ReplaceFirstCharacterIfClashesWithE5L(TDes8& aShortName) |
50 { |
59 { |
51 if (0 < aShortName.Length() && aShortName[0] == KEntryErasedMarker) |
60 if (0 < aShortName.Length() && aShortName[0] == KEntryErasedMarker) |
52 { |
61 { |
53 aShortName[0] = KLeadingE5Replacement; |
62 aShortName[0] = KLeadingE5Replacement; |
54 } |
63 } |
55 } |
64 } |
56 |
65 |
57 LOCAL_C void ReplaceIllegalCharactersL(TDes& aLongName, TUint aCharacterToReplaceWith) |
66 LOCAL_C void ReplaceIllegalCharactersL(TDes& aLongName, TUint aCharacterToReplaceWith) |
58 { |
67 { |
59 TBool alreadyFoundExtensionDelimiter=EFalse; |
68 TBool alreadyFoundExtensionDelimiter=EFalse; |
60 |
69 |
61 TInt LongNameLen = aLongName.Length(); |
70 TInt LongNameLen = aLongName.Length(); |
62 TInt extDelimiterIndex = aLongName.LocateReverse(KExtDelimiter); |
71 TInt extDelimiterIndex = aLongName.LocateReverse(KExtDelimiter); |
63 |
72 |
64 for (TInt i=LongNameLen-1; i>=0; --i) // iterate backwards as aLongName may change length during the loop, and also because we want to leave the *right-most* occurrence of KExtDelimiter unchanged |
73 for (TInt i=LongNameLen-1; i>=0; --i) // iterate backwards as aLongName may change length during the loop, and also because we want to leave the *right-most* occurrence of KExtDelimiter unchanged |
65 { |
74 { |
66 TUint character=aLongName[i]; |
75 TUint character=aLongName[i]; |
67 if (character==(TUint)KExtDelimiter) |
76 if (character==(TUint)KExtDelimiter) |
68 { |
77 { |
69 if (alreadyFoundExtensionDelimiter) |
78 if (alreadyFoundExtensionDelimiter) |
70 { |
79 { |
71 aLongName[i]=(TText)aCharacterToReplaceWith; // A.B.C becomes A_B.C |
80 aLongName[i]=(TText)aCharacterToReplaceWith; // A.B.C becomes A_B.C |
72 } |
81 } |
73 alreadyFoundExtensionDelimiter=ETrue; |
82 alreadyFoundExtensionDelimiter=ETrue; |
74 } |
83 } |
75 else |
84 else |
76 { |
85 { |
77 // the code below doesn't need any #if defined(_UNICODE) stuff as a narrow-build aLongName would not contain values above 0xff (which is well below the surrogates area in Unicode 0xd800-0xdfff) |
86 // the code below doesn't need any #if defined(_UNICODE) stuff as a narrow-build aLongName would not contain values above 0xff (which is well below the surrogates area in Unicode 0xd800-0xdfff) |
78 TBool isSurrogatePair=EFalse; |
87 TBool isSurrogatePair=EFalse; |
79 |
88 |
80 // LAST character in file name or file ext CAN NOT be HIGH surrogate |
89 // LAST character in file name or file ext CAN NOT be HIGH surrogate |
81 if (i==LongNameLen-1 || i==extDelimiterIndex-1) |
90 if (i==LongNameLen-1 || i==extDelimiterIndex-1) |
82 { |
91 { |
83 if (IsHighSurrogate((TText16)character)) |
92 if (IsHighSurrogate((TText16)character)) |
84 { |
93 { |
85 // Corrupt surrogate |
94 // Corrupt surrogate |
86 User::Leave(KErrBadName); |
95 User::Leave(KErrBadName); |
87 } |
96 } |
88 } |
97 } |
89 // FIRST character in file name or file ext CAN NOT be LOW surrogate |
98 // FIRST character in file name or file ext CAN NOT be LOW surrogate |
90 if (i==0 || i==extDelimiterIndex+1) |
99 if (i==0 || i==extDelimiterIndex+1) |
91 { |
100 { |
92 if (IsLowSurrogate((TText16)character)) |
101 if (IsLowSurrogate((TText16)character)) |
93 { |
102 { |
94 // Corrupt surrogate |
103 // Corrupt surrogate |
95 User::Leave(KErrBadName); |
104 User::Leave(KErrBadName); |
96 } |
105 } |
97 } |
106 } |
98 // if LOW Surrogate |
107 // if LOW Surrogate |
99 if (IsLowSurrogate((TText16)character)) |
108 if (IsLowSurrogate((TText16)character)) |
100 { |
109 { |
101 // check for HIGH surrogate |
110 // check for HIGH surrogate |
102 if (!IsHighSurrogate(aLongName[--i])) |
111 if (!IsHighSurrogate(aLongName[--i])) |
103 { |
112 { |
104 // Corrupt surrogate |
113 // Corrupt surrogate |
105 User::Leave(KErrBadName); |
114 User::Leave(KErrBadName); |
106 } |
115 } |
107 // surrogate pair found |
116 // surrogate pair found |
108 character&=~0xdc00; |
117 character&=~0xdc00; |
109 character|=((aLongName[i]&~0xd800)<<10); |
118 character|=((aLongName[i]&~0xd800)<<10); |
110 character+=0x00010000; // this must be added - it cannot be bitwise-"or"-ed |
119 character+=0x00010000; // this must be added - it cannot be bitwise-"or"-ed |
111 isSurrogatePair=ETrue; |
120 isSurrogatePair=ETrue; |
112 } |
121 } |
113 |
122 |
114 // if High Surrogate |
123 // if High Surrogate |
115 if (!isSurrogatePair && IsHighSurrogate((TText16)character)) |
124 if (!isSurrogatePair && IsHighSurrogate((TText16)character)) |
116 { |
125 { |
117 // Corrupt surrogate |
126 // Corrupt surrogate |
118 User::Leave(KErrBadName); |
127 User::Leave(KErrBadName); |
119 } |
128 } |
120 |
129 |
121 if (!IsLegalChar(character, EFalse)) |
130 if (!IsLegalChar(character, EFalse)) |
122 { |
131 { |
123 if (isSurrogatePair) |
132 if (isSurrogatePair) |
124 { |
133 { |
125 aLongName.Delete(i+1, 1); |
134 aLongName.Delete(i+1, 1); |
126 } |
135 } |
127 aLongName[i]=(TText)aCharacterToReplaceWith; |
136 aLongName[i]=(TText)aCharacterToReplaceWith; |
128 } |
137 } |
129 } |
138 } |
130 } |
139 } |
131 } |
140 } |
132 |
141 |
133 TShortName DoGenerateShortNameL(const TDesC& aLongName,TInt& aNum,TBool aUseTildeSelectively) |
142 TShortName DoGenerateShortNameL(const TDesC& aLongName,TInt& aNum,TBool aUseTildeSelectively) |
134 // |
143 // |
135 // Create a legal shortname from aLongName |
144 // Create a legal shortname from aLongName |
136 // |
145 // |
137 { |
146 { |
138 |
147 |
139 TFileName longName(aLongName); |
148 TFileName longName(aLongName); |
140 longName.UpperCase(); |
149 longName.UpperCase(); |
141 ReplaceIllegalCharactersL(longName, '_'); |
150 ReplaceIllegalCharactersL(longName, '_'); |
142 TPtrC longNameWithoutExtension(longName); |
151 TPtrC longNameWithoutExtension(longName); |
143 TPtrC longNameExtension(KNullDesC); |
152 TPtrC longNameExtension(KNullDesC); |
144 const TInt positionOfExtension=longName.LocateReverse(KExtDelimiter); |
153 const TInt positionOfExtension=longName.LocateReverse(KExtDelimiter); |
145 if (positionOfExtension==0) |
154 if (positionOfExtension==0) |
146 { |
155 { |
147 // No filename specified, so use the extension as the basis of the shortname. |
156 // No filename specified, so use the extension as the basis of the shortname. |
148 // Make sure we always append a tilde+number in this case to avoid generating the same |
157 // Make sure we always append a tilde+number in this case to avoid generating the same |
149 // short filename as one of the protected folders ("\SYS", "\RESOURCE","\PRIVATE") |
158 // short filename as one of the protected folders ("\SYS", "\RESOURCE","\PRIVATE") |
150 longNameWithoutExtension.Set(longName.Mid(positionOfExtension+1)); |
159 longNameWithoutExtension.Set(longName.Mid(positionOfExtension+1)); |
151 aUseTildeSelectively = EFalse; |
160 aUseTildeSelectively = EFalse; |
152 if (aNum < 0) |
161 if (aNum < 0) |
153 aNum = 1; |
162 aNum = 1; |
154 } |
163 } |
155 else if (positionOfExtension!=KErrNotFound) |
164 else if (positionOfExtension!=KErrNotFound) |
156 { |
165 { |
157 longNameWithoutExtension.Set(longName.Left(positionOfExtension)); |
166 longNameWithoutExtension.Set(longName.Left(positionOfExtension)); |
158 longNameExtension.Set(longName.Mid(positionOfExtension+1)); |
167 longNameExtension.Set(longName.Mid(positionOfExtension+1)); |
159 } |
168 } |
160 |
169 |
161 // Converts the original file name main part into 8-bit character string |
170 // Converts the original file name main part into 8-bit character string |
162 TShortName tempShortName(0); |
171 TShortName tempShortName(0); |
163 |
172 |
164 LocaleUtils::ConvertFromUnicodeL(tempShortName, longNameWithoutExtension); |
173 LocaleUtils::ConvertFromUnicodeL(tempShortName, longNameWithoutExtension); |
165 const TInt originalNameLength = tempShortName.Length(); |
174 const TInt originalNameLength = tempShortName.Length(); |
166 |
175 |
167 // Converts the original file name extension part into 8-bit character string |
176 // Converts the original file name extension part into 8-bit character string |
168 TShortName tempShortNameExt(0); |
177 TShortName tempShortNameExt(0); |
169 |
178 |
170 LocaleUtils::ConvertFromUnicodeL(tempShortNameExt, longNameExtension); |
179 LocaleUtils::ConvertFromUnicodeL(tempShortNameExt, longNameExtension); |
171 const TInt extensionNameLength = tempShortNameExt.Length(); |
180 const TInt extensionNameLength = tempShortNameExt.Length(); |
172 // // const TInt extensionNameLength = tempShortNameExt.Length(); |
181 // // const TInt extensionNameLength = tempShortNameExt.Length(); |
173 |
182 |
174 // Checks the length of both original file name main part and original file name extension part |
183 // Checks the length of both original file name main part and original file name extension part |
175 if(aUseTildeSelectively) |
184 if(aUseTildeSelectively) |
176 { |
185 { |
177 // don't append ~<aNum> |
186 // don't append ~<aNum> |
178 if(originalNameLength<=KMaxLengthWithoutTilde && extensionNameLength<=KMaxFatFileNameExt) |
187 if(originalNameLength<=KMaxLengthWithoutTilde && extensionNameLength<=KMaxFatFileNameExt) |
179 aNum=-1; |
188 aNum=-1; |
180 } |
189 } |
181 |
190 |
182 // Applies tilde and number if necessary |
191 // Applies tilde and number if necessary |
183 TBuf8<5> tildeAndNumber; |
192 TBuf8<5> tildeAndNumber; |
184 if (aNum>=0) |
193 if (aNum>=0) |
185 { |
194 { |
186 tildeAndNumber.Append('~'); |
195 tildeAndNumber.Append('~'); |
187 tildeAndNumber.AppendNumUC(aNum,EHex); |
196 tildeAndNumber.AppendNumUC(aNum,EHex); |
188 } |
197 } |
189 const TInt lengthOfTildeAndNumber=tildeAndNumber.Length(); |
198 const TInt lengthOfTildeAndNumber=tildeAndNumber.Length(); |
190 |
199 |
191 // Creates actual shortname from longname of the original file |
200 // Creates actual shortname from longname of the original file |
192 TShortName shortName(11); |
201 TShortName shortName(11); |
193 #if defined(_DEBUG) |
202 #if defined(_DEBUG) |
194 shortName.Fill(0x01); // fill shortName with garbage to ensure that every byte is written to by this function |
203 shortName.Fill(0x01); // fill shortName with garbage to ensure that every byte is written to by this function |
195 #endif |
204 #endif |
196 |
205 |
197 // Fills the main part of the shortname of the original file |
206 // Fills the main part of the shortname of the original file |
198 const TInt numberOfBytesFreeBeforeTilde=KMaxFatFileNameWithoutExt-lengthOfTildeAndNumber; |
207 const TInt numberOfBytesFreeBeforeTilde=KMaxFatFileNameWithoutExt-lengthOfTildeAndNumber; |
199 |
208 |
200 TPtr8 portionOfShortNameBeforeTilde((TUint8*)shortName.Ptr(), 0, numberOfBytesFreeBeforeTilde); |
209 TPtr8 portionOfShortNameBeforeTilde((TUint8*)shortName.Ptr(), 0, numberOfBytesFreeBeforeTilde); |
201 TInt lengthOfPortionOfShortNameBeforeTilde = |
210 TInt lengthOfPortionOfShortNameBeforeTilde = |
202 (originalNameLength < numberOfBytesFreeBeforeTilde) ? originalNameLength : numberOfBytesFreeBeforeTilde; |
211 (originalNameLength < numberOfBytesFreeBeforeTilde) ? originalNameLength : numberOfBytesFreeBeforeTilde; |
203 |
212 |
204 portionOfShortNameBeforeTilde.Copy((TUint8*)tempShortName.Ptr(), lengthOfPortionOfShortNameBeforeTilde); |
213 portionOfShortNameBeforeTilde.Copy((TUint8*)tempShortName.Ptr(), lengthOfPortionOfShortNameBeforeTilde); |
205 if( lengthOfPortionOfShortNameBeforeTilde != originalNameLength) |
214 if( lengthOfPortionOfShortNameBeforeTilde != originalNameLength) |
206 { |
215 { |
207 for( int i = 0; i<lengthOfPortionOfShortNameBeforeTilde; i++) |
216 for( int i = 0; i<lengthOfPortionOfShortNameBeforeTilde; i++) |
208 { |
217 { |
209 if(portionOfShortNameBeforeTilde[i] >= 0x80) //leading byte found |
218 if(portionOfShortNameBeforeTilde[i] >= 0x80) //leading byte found |
210 { |
219 { |
211 if( i == lengthOfPortionOfShortNameBeforeTilde - 1) //leading byte found on the edge |
220 if( i == lengthOfPortionOfShortNameBeforeTilde - 1) //leading byte found on the edge |
212 { |
221 { |
213 lengthOfPortionOfShortNameBeforeTilde -= 1; |
222 lengthOfPortionOfShortNameBeforeTilde -= 1; |
214 break; |
223 break; |
215 } |
224 } |
216 else |
225 else |
217 { |
226 { |
218 i++; |
227 i++; |
219 } |
228 } |
220 } |
229 } |
221 } |
230 } |
222 } |
231 } |
223 Mem::Copy(((TUint8*)shortName.Ptr())+lengthOfPortionOfShortNameBeforeTilde, tildeAndNumber.Ptr(), lengthOfTildeAndNumber); |
232 Mem::Copy(((TUint8*)shortName.Ptr())+lengthOfPortionOfShortNameBeforeTilde, tildeAndNumber.Ptr(), lengthOfTildeAndNumber); |
224 TInt i; |
233 TInt i; |
225 for (i=lengthOfPortionOfShortNameBeforeTilde+lengthOfTildeAndNumber; i<KMaxFatFileNameWithoutExt; ++i) |
234 for (i=lengthOfPortionOfShortNameBeforeTilde+lengthOfTildeAndNumber; i<KMaxFatFileNameWithoutExt; ++i) |
226 { |
235 { |
227 shortName[i]=' '; |
236 shortName[i]=' '; |
228 } |
237 } |
229 |
238 |
230 // Fills the extension part of the shortname of the original file |
239 // Fills the extension part of the shortname of the original file |
231 TInt lengthOfExt = |
240 TInt lengthOfExt = |
232 (extensionNameLength < KMaxFatFileNameExt) ? extensionNameLength : KMaxFatFileNameExt; |
241 (extensionNameLength < KMaxFatFileNameExt) ? extensionNameLength : KMaxFatFileNameExt; |
233 |
242 |
234 if( lengthOfExt != extensionNameLength) |
243 if( lengthOfExt != extensionNameLength) |
235 { |
244 { |
236 for( int i = 0; i<lengthOfExt; i++) |
245 for( int i = 0; i<lengthOfExt; i++) |
237 { |
246 { |
238 if(tempShortNameExt[i] >= 0x80) |
247 if(tempShortNameExt[i] >= 0x80) |
239 { |
248 { |
240 if( i == lengthOfExt - 1) |
249 if( i == lengthOfExt - 1) |
241 { |
250 { |
242 lengthOfExt -= 1; |
251 lengthOfExt -= 1; |
243 break; |
252 break; |
244 } |
253 } |
245 else |
254 else |
246 { |
255 { |
247 i++; |
256 i++; |
248 } |
257 } |
249 } |
258 } |
250 } |
259 } |
251 } |
260 } |
252 Mem::Copy(((TUint8*)shortName.Ptr()) + KMaxFatFileNameWithoutExt, tempShortNameExt.Ptr(), lengthOfExt); |
261 Mem::Copy(((TUint8*)shortName.Ptr()) + KMaxFatFileNameWithoutExt, tempShortNameExt.Ptr(), lengthOfExt); |
253 for (i = KMaxFatFileNameWithoutExt + lengthOfExt; i<KMaxFatFileNameWithoutExt+KMaxFatFileNameExt; ++i) |
262 for (i = KMaxFatFileNameWithoutExt + lengthOfExt; i<KMaxFatFileNameWithoutExt+KMaxFatFileNameExt; ++i) |
254 { |
263 { |
255 shortName[i]=' '; |
264 shortName[i]=' '; |
256 } |
265 } |
257 |
266 |
258 ReplaceFirstCharacterIfClashesWithE5L(shortName); |
267 ReplaceFirstCharacterIfClashesWithE5L(shortName); |
259 return shortName; |
268 return shortName; |
260 } |
269 } |
261 |
270 |
262 |
271 |
263 /** |
272 /** |
264 Check whether a Dos name is legal or not. |
273 Check whether a Dos name is legal or not. |
265 |
274 |
266 @param aName The entry name to be analysed (may be represented as TDes16& or TDes8&) |
275 @param aName The entry name to be analysed (may be represented as TDes16& or TDes8&) |
267 @param anAllowWildCards Flag to indicate whether to allow wildcards in name or not |
276 @param anAllowWildCards Flag to indicate whether to allow wildcards in name or not |
268 @param aUseExtendedChars Flag to indicate if extended characters are allowed |
277 @param aUseExtendedChars Flag to indicate if extended characters are allowed |
269 @param aInScanDrive Flag to indicate whether called when scanning drive |
278 @param aInScanDrive Flag to indicate whether called when scanning drive |
270 @param aAllowLowerCase ETrue to allow lower case in the analysed DOS name |
279 @param aAllowLowerCase ETrue to allow lower case in the analysed DOS name |
271 |
280 |
272 @return ETrue if the name is a legal DOS one. |
281 @return ETrue if the name is a legal DOS one. |
273 */ |
282 */ |
274 |
283 |
275 static TBool DoCheckLegalDosName(const TDesC& aName, TBool anAllowWildCards, TBool aUseExtendedChars, TBool aInScanDrive, TBool aAllowLowerCase, TBool aIsForFileCreation) |
284 static TBool DoCheckLegalDosName(const TDesC& aName, TBool anAllowWildCards, TBool aUseExtendedChars, TBool aInScanDrive, TBool aAllowLowerCase, TBool aIsForFileCreation) |
276 { |
285 { |
277 const TInt count=aName.Length(); |
286 const TInt count=aName.Length(); |
278 if (count==0) |
287 if (count==0) |
279 return EFalse; |
288 return EFalse; |
280 |
289 |
281 TInt valid=0; |
290 TInt valid=0; |
282 TInt i=0; |
291 TInt i=0; |
283 |
292 |
284 //-- check the entry name |
293 //-- check the entry name |
285 while (i<count) |
294 while (i<count) |
286 { |
295 { |
287 TChar c=aName[i++]; |
296 TChar c=aName[i++]; |
288 if (c==KExtDelimiter) |
297 if (c==KExtDelimiter) |
289 { |
298 { |
290 // DOS entry names must contain at least one valid character before the extension |
299 // DOS entry names must contain at least one valid character before the extension |
291 if (i == 1) |
300 if (i == 1) |
292 return EFalse; |
301 return EFalse; |
293 break; |
302 break; |
294 } |
303 } |
295 |
304 |
296 if(!aAllowLowerCase && c.IsLower()) |
305 if(!aAllowLowerCase && c.IsLower()) |
297 return EFalse; //-- low case is not allowed |
306 return EFalse; //-- low case is not allowed |
298 |
307 |
299 if (!IsLegalChar(c,anAllowWildCards,aUseExtendedChars,aInScanDrive)) |
308 if (!IsLegalChar(c,anAllowWildCards,aUseExtendedChars,aInScanDrive)) |
300 { |
309 { |
301 return EFalse; |
310 return EFalse; |
302 } |
311 } |
303 |
312 |
304 if (aIsForFileCreation) |
313 if (aIsForFileCreation) |
305 { |
314 { |
306 if ((aUseExtendedChars && (TUint) c > KExtendedCharEnd) || |
315 if ((aUseExtendedChars && (TUint) c > KExtendedCharEnd) || |
307 (!aUseExtendedChars && (TUint) c > KExtendedCharStart)) |
316 (!aUseExtendedChars && (TUint) c > KExtendedCharStart)) |
308 { |
317 { |
309 return EFalse; |
318 return EFalse; |
310 } |
319 } |
311 } |
320 } |
312 |
321 |
313 if (c!=KMatchAny) |
322 if (c!=KMatchAny) |
314 if (++valid>KMaxFatFileNameWithoutExt) |
323 if (++valid>KMaxFatFileNameWithoutExt) |
315 return EFalse; |
324 return EFalse; |
316 } |
325 } |
317 |
326 |
318 //-- check entry extension |
327 //-- check entry extension |
319 valid=0; |
328 valid=0; |
320 while (i<count) |
329 while (i<count) |
321 { |
330 { |
322 TChar c=aName[i++]; |
331 TChar c=aName[i++]; |
323 if (c==KExtDelimiter) |
332 if (c==KExtDelimiter) |
324 return EFalse; |
333 return EFalse; |
325 |
334 |
326 if(!aAllowLowerCase && c.IsLower()) |
335 if(!aAllowLowerCase && c.IsLower()) |
327 return EFalse; //-- low case is not allowed |
336 return EFalse; //-- low case is not allowed |
328 |
337 |
329 if (!IsLegalChar(c,anAllowWildCards,aUseExtendedChars,aInScanDrive)) |
338 if (!IsLegalChar(c,anAllowWildCards,aUseExtendedChars,aInScanDrive)) |
330 return EFalse; |
339 return EFalse; |
331 |
340 |
332 if (aIsForFileCreation) |
341 if (aIsForFileCreation) |
333 { |
342 { |
334 if ((aUseExtendedChars && (TUint) c > KExtendedCharEnd) || |
343 if ((aUseExtendedChars && (TUint) c > KExtendedCharEnd) || |
335 (!aUseExtendedChars && (TUint) c > KExtendedCharStart)) |
344 (!aUseExtendedChars && (TUint) c > KExtendedCharStart)) |
336 { |
345 { |
337 return EFalse; |
346 return EFalse; |
338 } |
347 } |
339 } |
348 } |
340 |
349 |
341 if (c!=KMatchAny) |
350 if (c!=KMatchAny) |
342 if (++valid>KMaxFatFileNameExt) |
351 if (++valid>KMaxFatFileNameExt) |
343 return EFalse; |
352 return EFalse; |
344 } |
353 } |
345 |
354 |
346 // Unicode file name checking for file opening. |
355 // Unicode file name checking for file opening. |
347 if (!aIsForFileCreation && GetFatUtilityFunctions()) |
356 if (!aIsForFileCreation && GetFatUtilityFunctions()) |
348 { |
357 { |
349 TBuf8<KMaxFileName*2> convertedName8; |
358 TBuf8<KMaxFileName*2> convertedName8; |
350 TRAPD(err, LocaleUtils::ConvertFromUnicodeL(convertedName8, aName, TFatUtilityFunctions::EOverflowActionLeave)); |
359 TRAPD(err, LocaleUtils::ConvertFromUnicodeL(convertedName8, aName, TFatUtilityFunctions::EOverflowActionLeave)); |
351 if (err != KErrNone) |
360 if (err != KErrNone) |
352 return EFalse; |
361 return EFalse; |
353 |
362 |
354 const TInt len8 = convertedName8.Length(); |
363 const TInt len8 = convertedName8.Length(); |
355 TInt j = 0; |
364 TInt j = 0; |
356 TInt nonWildChar = 0; |
365 TInt nonWildChar = 0; |
357 while (j < len8) |
366 while (j < len8) |
358 { |
367 { |
359 const TUint8 c8 = convertedName8[j++]; |
368 const TUint8 c8 = convertedName8[j++]; |
360 if (c8 == KExtDelimiter) |
369 if (c8 == KExtDelimiter) |
361 break; |
370 break; |
362 if (c8 == '*' && !anAllowWildCards) |
371 if (c8 == '*' && !anAllowWildCards) |
363 return EFalse; |
372 return EFalse; |
364 if (c8 == '*' && anAllowWildCards) |
373 if (c8 == '*' && anAllowWildCards) |
365 continue; |
374 continue; |
366 |
375 |
367 if (++nonWildChar > KMaxFatFileNameWithoutExt) |
376 if (++nonWildChar > KMaxFatFileNameWithoutExt) |
368 return EFalse; |
377 return EFalse; |
369 } |
378 } |
370 |
379 |
371 // check extension part |
380 // check extension part |
372 nonWildChar = 0; |
381 nonWildChar = 0; |
373 while (j < len8) |
382 while (j < len8) |
374 { |
383 { |
375 const TUint8 c8 = convertedName8[j++]; |
384 const TUint8 c8 = convertedName8[j++]; |
376 if (c8 == KExtDelimiter) |
385 if (c8 == KExtDelimiter) |
377 return EFalse; |
386 return EFalse; |
378 if (c8 == '*' && !anAllowWildCards) |
387 if (c8 == '*' && !anAllowWildCards) |
379 return EFalse; |
388 return EFalse; |
380 if (c8 == '*' && anAllowWildCards) |
389 if (c8 == '*' && anAllowWildCards) |
381 continue; |
390 continue; |
382 |
391 |
383 if (++nonWildChar > KMaxFatFileNameExt) |
392 if (++nonWildChar > KMaxFatFileNameExt) |
384 return EFalse; |
393 return EFalse; |
385 } |
394 } |
386 } |
395 } |
387 |
396 |
388 return ETrue; |
397 return ETrue; |
389 } |
398 } |
390 |
399 |
391 /** |
400 /** |
392 Check whether a Dos name is legal or not. Unicode version |
401 Check whether a Dos name is legal or not. Unicode version |
393 parameters and return value absolutely the same as in DoCheckLegalDosName() |
402 parameters and return value absolutely the same as in DoCheckLegalDosName() |
394 */ |
403 */ |
395 TBool IsLegalDosName(const TDesC16& aName, TBool anAllowWildCards, TBool aUseExtendedChars, TBool aInScanDrive, TBool aAllowLowerCase, TBool aIsForFileCreation) |
404 TBool IsLegalDosName(const TDesC16& aName, TBool anAllowWildCards, TBool aUseExtendedChars, TBool aInScanDrive, TBool aAllowLowerCase, TBool aIsForFileCreation) |
396 { |
405 { |
397 |
406 |
398 __PRINT(_L("IsLegalDosName 16")); |
407 __PRINT(_L("IsLegalDosName 16")); |
399 |
408 |
400 return DoCheckLegalDosName(aName, anAllowWildCards, aUseExtendedChars, aInScanDrive, aAllowLowerCase, aIsForFileCreation); |
409 return DoCheckLegalDosName(aName, anAllowWildCards, aUseExtendedChars, aInScanDrive, aAllowLowerCase, aIsForFileCreation); |
401 } |
410 } |
402 |
411 |
403 TBool CFatMountCB::FindShortNameL(const TShortName& aName,TEntryPos& anEntryPos) |
412 TBool CFatMountCB::FindShortNameL(const TShortName& aName,TEntryPos& anEntryPos) |
404 // |
413 // |
405 // Returns ETrue and the entryPos of aName if found or EFalse |
414 // Returns ETrue and the entryPos of aName if found or EFalse |
406 // |
415 // |
407 { |
416 { |
408 |
417 |
409 __PRINT(_L("VFAT::CFatMountCB::FindShortNameL")); |
418 __PRINT(_L("VFAT::CFatMountCB::FindShortNameL")); |
410 TFatDirEntry fatEntry; |
419 TFatDirEntry fatEntry; |
411 TInt count=0; |
420 TInt count=0; |
412 FOREVER |
421 FOREVER |
413 { |
422 { |
414 count++; |
423 count++; |
415 ReadDirEntryL(anEntryPos,fatEntry); |
424 ReadDirEntryL(anEntryPos,fatEntry); |
416 MoveToDosEntryL(anEntryPos,fatEntry); |
425 MoveToDosEntryL(anEntryPos,fatEntry); |
417 if (fatEntry.IsEndOfDirectory()) |
426 if (fatEntry.IsEndOfDirectory()) |
418 break; |
427 break; |
419 if (IsRootDir(anEntryPos)&&(anEntryPos.iPos+StartOfRootDirInBytes()==(RootDirEnd()-KSizeOfFatDirEntry))) |
428 if (IsRootDir(anEntryPos)&&(anEntryPos.iPos+StartOfRootDirInBytes()==(RootDirEnd()-KSizeOfFatDirEntry))) |
420 if (fatEntry.IsErased()) |
429 if (fatEntry.IsErased()) |
421 break;//Allows maximum number of entries in root directory |
430 break;//Allows maximum number of entries in root directory |
422 if (fatEntry.Name()==aName) |
431 if (fatEntry.Name()==aName) |
423 return ETrue; |
432 return ETrue; |
424 MoveToNextEntryL(anEntryPos); |
433 MoveToNextEntryL(anEntryPos); |
425 if (IsRootDir(anEntryPos)&&(StartOfRootDirInBytes()+anEntryPos.iPos==RootDirEnd())) |
434 if (IsRootDir(anEntryPos)&&(StartOfRootDirInBytes()+anEntryPos.iPos==RootDirEnd())) |
426 break;//Allows maximum number of entries in root directory |
435 break;//Allows maximum number of entries in root directory |
427 } |
436 } |
428 return EFalse; |
437 return EFalse; |
429 } |
438 } |
430 |
439 |
431 TBool CFatMountCB::IsUniqueNameL(const TShortName& aName,TInt aDirCluster) |
440 TBool CFatMountCB::IsUniqueNameL(const TShortName& aName,TInt aDirCluster) |
432 // |
441 // |
433 // Returns ETrue if aName is unique, EFalse if a matching name is found. |
442 // Returns ETrue if aName is unique, EFalse if a matching name is found. |
434 // |
443 // |
435 { |
444 { |
436 |
445 |
437 __PRINT(_L("VFAT::CFatMountCB::IsUniqueNameL")); |
446 __PRINT(_L("VFAT::CFatMountCB::IsUniqueNameL")); |
438 TEntryPos entryPos(aDirCluster,0); |
447 TEntryPos entryPos(aDirCluster,0); |
439 if (FindShortNameL(aName,entryPos)) |
448 if (FindShortNameL(aName,entryPos)) |
440 return(EFalse); |
449 return(EFalse); |
441 return(ETrue); |
450 return(ETrue); |
442 } |
451 } |
443 |
452 |
444 void CFatMountCB::ReplaceClashingNameL(const TShortName& aNewName,const TEntryPos& anEntryPos) |
453 void CFatMountCB::ReplaceClashingNameL(const TShortName& aNewName,const TEntryPos& anEntryPos) |
445 // |
454 // |
446 // A legal dos name has been typed that clashes with a computer generated shortname |
455 // A legal dos name has been typed that clashes with a computer generated shortname |
447 // Change the shortname to something else. |
456 // Change the shortname to something else. |
448 // |
457 // |
449 { |
458 { |
450 |
459 |
451 __PRINT(_L("VFAT::CFatMountCB::ReplaceClashingNameL")); |
460 __PRINT(_L("VFAT::CFatMountCB::ReplaceClashingNameL")); |
452 TFatDirEntry entry; |
461 TFatDirEntry entry; |
453 ReadDirEntryL(anEntryPos,entry); |
462 ReadDirEntryL(anEntryPos,entry); |
454 __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt)); |
463 __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt)); |
455 entry.SetName(aNewName); |
464 entry.SetName(aNewName); |
456 WriteDirEntryL(anEntryPos,entry); |
465 WriteDirEntryL(anEntryPos,entry); |
457 // We now need to fix up VFAT entries with a new checksum reflecting new shortname |
466 // We now need to fix up VFAT entries with a new checksum reflecting new shortname |
458 // Calculate new checksum |
467 // Calculate new checksum |
459 TUint8 checksum=CalculateShortNameCheckSum(aNewName); |
468 TUint8 checksum=CalculateShortNameCheckSum(aNewName); |
460 // Now go back and adjust all VFAT entries corresponding to this shortname |
469 // Now go back and adjust all VFAT entries corresponding to this shortname |
461 TEntryPos entryPos=anEntryPos; |
470 TEntryPos entryPos=anEntryPos; |
462 FOREVER |
471 FOREVER |
463 { |
472 { |
464 entryPos.iPos-=KSizeOfFatDirEntry; |
473 entryPos.iPos-=KSizeOfFatDirEntry; |
465 ReadDirEntryL(entryPos,entry); |
474 ReadDirEntryL(entryPos,entry); |
466 entry.iData[0x0D]=checksum; |
475 entry.iData[0x0D]=checksum; |
467 if (entry.iData[0]&0x40) |
476 if (entry.iData[0]&0x40) |
468 break; |
477 break; |
469 } |
478 } |
470 } |
479 } |
471 |
480 |
472 TBool CFatMountCB::GenerateShortNameL(TInt aDirCluster,const TDesC& aName,TShortName& aGeneratedName, TBool aForceRandomize) |
481 TBool CFatMountCB::GenerateShortNameL(TInt aDirCluster,const TDesC& aName,TShortName& aGeneratedName, TBool aForceRandomize) |
473 // |
482 // |
474 // Generate a legal dos filename as an alias for aName. |
483 // Generate a legal dos filename as an alias for aName. |
475 // Returns ETrue if aName is a legal dos name. |
484 // Returns ETrue if aName is a legal dos name. |
476 // |
485 // |
477 { |
486 { |
478 |
487 |
479 __PRINT(_L("VFAT::CFatMountCB::GenerateShortNameL")); |
488 __PRINT(_L("VFAT::CFatMountCB::GenerateShortNameL")); |
480 // Given the long file-name "ABCDEFGHI.TXT", EPOC used to generate short |
489 // Given the long file-name "ABCDEFGHI.TXT", EPOC used to generate short |
481 // file-names in the following pecking order: |
490 // file-names in the following pecking order: |
482 // "ABCDEFGH.TXT", |
491 // "ABCDEFGH.TXT", |
483 // "ABCDEF~0.TXT", |
492 // "ABCDEF~0.TXT", |
484 // "ABCDEF~1.TXT", |
493 // "ABCDEF~1.TXT", |
485 // "ABCDEF~2.TXT", |
494 // "ABCDEF~2.TXT", |
486 // etc. |
495 // etc. |
487 // Now, however, EPOC behaves in a more Windows-like manner and |
496 // Now, however, EPOC behaves in a more Windows-like manner and |
488 // generates short file-names in this pecking order: |
497 // generates short file-names in this pecking order: |
489 // "ABCDEF~1.TXT", |
498 // "ABCDEF~1.TXT", |
490 // "ABCDEF~2.TXT", |
499 // "ABCDEF~2.TXT", |
491 // "ABCDEF~3.TXT", |
500 // "ABCDEF~3.TXT", |
492 // "ABCDEF~4.TXT", |
501 // "ABCDEF~4.TXT", |
493 // After failing to find an unused short name 4 times in a row, |
502 // After failing to find an unused short name 4 times in a row, |
494 // a random number is used to speed up the process. So subsequent |
503 // a random number is used to speed up the process. So subsequent |
495 // short-file names become |
504 // short-file names become |
496 // "ABC~nnnn.TXT" where nnnn is a random number |
505 // "ABC~nnnn.TXT" where nnnn is a random number |
497 // |
506 // |
498 TBool useTildeSelectively = ETrue; |
507 TBool useTildeSelectively = ETrue; |
499 TInt endNum = KMaxDuplicateShortName; // 0xFFFF |
508 TInt endNum = KMaxDuplicateShortName; // 0xFFFF |
500 const TInt KMaxNonRandomShortFileNames = 4; |
509 const TInt KMaxNonRandomShortFileNames = 4; |
501 |
510 |
502 TInt i = 1; |
511 TInt i = 1; |
503 |
512 |
504 TBool randomize = aForceRandomize; |
513 TBool randomize = aForceRandomize; |
505 if (randomize) |
514 if (randomize) |
506 { |
515 { |
507 i = (TInt) (Math::Random() & KMaxDuplicateShortName); |
516 i = (TInt) (Math::Random() & KMaxDuplicateShortName); |
508 endNum = (i - 1) & KMaxDuplicateShortName; |
517 endNum = (i - 1) & KMaxDuplicateShortName; |
509 } |
518 } |
510 |
519 |
511 while(i != endNum) |
520 while(i != endNum) |
512 { |
521 { |
513 aGeneratedName=DoGenerateShortNameL(aName,i,useTildeSelectively); |
522 aGeneratedName=DoGenerateShortNameL(aName,i,useTildeSelectively); |
514 |
523 |
515 if (IsUniqueNameL(aGeneratedName,aDirCluster)) |
524 if (IsUniqueNameL(aGeneratedName,aDirCluster)) |
516 break; |
525 break; |
517 |
526 |
518 if (i == KMaxNonRandomShortFileNames && !randomize) |
527 if (i == KMaxNonRandomShortFileNames && !randomize) |
519 { |
528 { |
520 randomize = ETrue; |
529 randomize = ETrue; |
521 i = (TInt) (Math::Random() & KMaxDuplicateShortName); |
530 i = (TInt) (Math::Random() & KMaxDuplicateShortName); |
522 endNum = (i - 1) & KMaxDuplicateShortName; |
531 endNum = (i - 1) & KMaxDuplicateShortName; |
523 } |
532 } |
524 else if (i == -1) |
533 else if (i == -1) |
525 { |
534 { |
526 useTildeSelectively=EFalse; |
535 useTildeSelectively=EFalse; |
527 i = 1; |
536 i = 1; |
528 } |
537 } |
529 else |
538 else |
530 i = (i + 1) & KMaxDuplicateShortName; |
539 i = (i + 1) & KMaxDuplicateShortName; |
531 } |
540 } |
532 |
541 |
533 if (i == endNum) |
542 if (i == endNum) |
534 User::Leave(KErrAlreadyExists); |
543 User::Leave(KErrAlreadyExists); |
535 |
544 |
536 if((i == -1) && IsLegalDosName(aName,EFalse,EFalse,EFalse,EFalse,ETrue)) |
545 if((i == -1) && IsLegalDosName(aName,EFalse,EFalse,EFalse,EFalse,ETrue)) |
537 { |
546 { |
538 // Original file name is a legal 8.3 name |
547 // Original file name is a legal 8.3 name |
539 return(ETrue); |
548 return(ETrue); |
540 } |
549 } |
541 else |
550 else |
542 { |
551 { |
543 return(EFalse); |
552 return(EFalse); |
544 } |
553 } |
545 |
554 |
546 |
555 |
547 } |
556 } |
548 |
557 |
549 void TFatDirEntry::InitializeAsVFat(TUint8 aCheckSum) |
558 void TFatDirEntry::InitializeAsVFat(TUint8 aCheckSum) |
550 // |
559 // |
551 // Initialize a FAT entry as a VFAT filename |
560 // Initialize a FAT entry as a VFAT filename |
552 // |
561 // |
553 { |
562 { |
554 |
563 |
555 Mem::Fill(this,sizeof(SFatDirEntry),0xFF); |
564 Mem::Fill(this,sizeof(SFatDirEntry),0xFF); |
556 iData[0x0B]=0x0F; |
565 iData[0x0B]=0x0F; |
557 iData[0x0C]=0x00; iData[0x0D]=aCheckSum; |
566 iData[0x0C]=0x00; iData[0x0D]=aCheckSum; |
558 iData[0x1A]=0x00; iData[0x1B]=0x00; |
567 iData[0x1A]=0x00; iData[0x1B]=0x00; |
559 } |
568 } |
560 |
569 |
561 void TFatDirEntry::SetVFatEntry(const TDesC& aName,TInt aLen) |
570 void TFatDirEntry::SetVFatEntry(const TDesC& aName,TInt aLen) |
562 // |
571 // |
563 // Write up to KMaxVFatEntryName unicode chars from aName to the entry |
572 // Write up to KMaxVFatEntryName unicode chars from aName to the entry |
564 // |
573 // |
565 { |
574 { |
566 |
575 |
567 TInt rem=aName.Length()-aLen; |
576 TInt rem=aName.Length()-aLen; |
568 TPtrC section(aName.Ptr()+aLen,Min(rem,KMaxVFatEntryName)); |
577 TPtrC section(aName.Ptr()+aLen,Min(rem,KMaxVFatEntryName)); |
569 TBuf16<KMaxVFatEntryName> buf16; |
578 TBuf16<KMaxVFatEntryName> buf16; |
570 buf16.Copy(section); |
579 buf16.Copy(section); |
571 if (rem<KMaxVFatEntryName) |
580 if (rem<KMaxVFatEntryName) |
572 { |
581 { |
573 rem++; |
582 rem++; |
574 buf16.ZeroTerminate(); |
583 buf16.ZeroTerminate(); |
575 buf16.SetLength(rem); // Zero termination doesn't increase the buf length |
584 buf16.SetLength(rem); // Zero termination doesn't increase the buf length |
576 } |
585 } |
577 TUint8 orderNo=(TUint8)(aLen/KMaxVFatEntryName+1); |
586 TUint8 orderNo=(TUint8)(aLen/KMaxVFatEntryName+1); |
578 TInt s=Min(rem,5); |
587 TInt s=Min(rem,5); |
579 Mem::Copy(&iData[0x01],buf16.Ptr(),s*2);//Copy up to 10 bytes of buf16 into iData |
588 Mem::Copy(&iData[0x01],buf16.Ptr(),s*2);//Copy up to 10 bytes of buf16 into iData |
580 TInt offset=s; |
589 TInt offset=s; |
581 rem-=s; |
590 rem-=s; |
582 s=Min(rem,6); |
591 s=Min(rem,6); |
583 Mem::Copy(&iData[0x0E],buf16.Ptr()+offset,s*2); |
592 Mem::Copy(&iData[0x0E],buf16.Ptr()+offset,s*2); |
584 offset+=s; |
593 offset+=s; |
585 rem-=s; |
594 rem-=s; |
586 s=Min(rem,2); |
595 s=Min(rem,2); |
587 Mem::Copy(&iData[0x1C],buf16.Ptr()+offset,s*2); |
596 Mem::Copy(&iData[0x1C],buf16.Ptr()+offset,s*2); |
588 rem-=s; |
597 rem-=s; |
589 if (rem==0) |
598 if (rem==0) |
590 orderNo|=0x40; |
599 orderNo|=0x40; |
591 iData[0]=orderNo; |
600 iData[0]=orderNo; |
592 } |
601 } |
593 |
602 |
594 void TFatDirEntry::ReadVFatEntry(TDes16& aBuf) const |
603 void TFatDirEntry::ReadVFatEntry(TDes16& aBuf) const |
595 // |
604 // |
596 // Read KMaxVFatEntryName unicode chars from the entry |
605 // Read KMaxVFatEntryName unicode chars from the entry |
597 // |
606 // |
598 { |
607 { |
599 |
608 |
600 aBuf.SetLength(KMaxVFatEntryName); |
609 aBuf.SetLength(KMaxVFatEntryName); |
601 Mem::Copy(&aBuf[0],&iData[0x01],5*2); |
610 Mem::Copy(&aBuf[0],&iData[0x01],5*2); |
602 Mem::Copy(&aBuf[5],&iData[0x0E],6*2); |
611 Mem::Copy(&aBuf[5],&iData[0x0E],6*2); |
603 Mem::Copy(&aBuf[11],&iData[0x1C],2*2); |
612 Mem::Copy(&aBuf[11],&iData[0x1C],2*2); |
604 } |
613 } |
605 |
614 |
606 void CFatMountCB::WriteDirEntryL(TEntryPos& aPos,const TFatDirEntry& aFatDirEntry,const TDesC& aLongName) |
615 void CFatMountCB::WriteDirEntryL(TEntryPos& aPos,const TFatDirEntry& aFatDirEntry,const TDesC& aLongName) |
607 // |
616 // |
608 // Write a VFAT directory entry to disk at position aPos - leave aPos refering to the dos entry |
617 // Write a VFAT directory entry to disk at position aPos - leave aPos refering to the dos entry |
609 // Assumes sufficient space has been created for it by AddDirEntry. |
618 // Assumes sufficient space has been created for it by AddDirEntry. |
610 // |
619 // |
611 { |
620 { |
612 |
621 |
613 __PRINT(_L("VFAT::CFatMountCB::WriteDirEntryL")); |
622 __PRINT(_L("VFAT::CFatMountCB::WriteDirEntryL")); |
614 __ASSERT_DEBUG(aLongName.Length(),Fault(EVFatNoLongName)); |
623 __ASSERT_DEBUG(aLongName.Length(),Fault(EVFatNoLongName)); |
615 TEntryPos startPos(aPos.iCluster,aPos.iPos); |
624 TEntryPos startPos(aPos.iCluster,aPos.iPos); |
616 TUint8 localBuf[KDefaultSectorSize]; |
625 TUint8 localBuf[KDefaultSectorSize]; |
617 TUint8 cksum=CalculateShortNameCheckSum(aFatDirEntry.Name()); |
626 TUint8 cksum=CalculateShortNameCheckSum(aFatDirEntry.Name()); |
618 TInt numEntries=NumberOfVFatEntries(aLongName.Length())-1; // Excluding dos entry |
627 TInt numEntries=NumberOfVFatEntries(aLongName.Length())-1; // Excluding dos entry |
619 // see if all entries written to one sector |
628 // see if all entries written to one sector |
620 // single sector writes not supported if sector size>default size |
629 // single sector writes not supported if sector size>default size |
621 TInt dosOffset=numEntries<<KSizeOfFatDirEntryLog2; |
630 TInt dosOffset=numEntries<<KSizeOfFatDirEntryLog2; |
622 TInt absolutePos=(aPos.iCluster<<ClusterSizeLog2())+ClusterRelativePos(aPos.iPos); |
631 TInt absolutePos=(aPos.iCluster<<ClusterSizeLog2())+ClusterRelativePos(aPos.iPos); |
623 TBool isSameSector=(((absolutePos^(absolutePos+dosOffset))>>SectorSizeLog2())==0 && ((TUint)(1<<SectorSizeLog2())<=KDefaultSectorSize)); |
632 TBool isSameSector=(((absolutePos^(absolutePos+dosOffset))>>SectorSizeLog2())==0 && ((TUint)(1<<SectorSizeLog2())<=KDefaultSectorSize)); |
624 TFatDirEntry vFatEntry; |
633 TFatDirEntry vFatEntry; |
625 vFatEntry.InitializeAsVFat(cksum); |
634 vFatEntry.InitializeAsVFat(cksum); |
626 TInt offset=0; |
635 TInt offset=0; |
627 while (numEntries--) |
636 while (numEntries--) |
628 { |
637 { |
629 vFatEntry.SetVFatEntry(aLongName,KMaxVFatEntryName*numEntries);// KMaxVFatEntryName=13 |
638 vFatEntry.SetVFatEntry(aLongName,KMaxVFatEntryName*numEntries);// KMaxVFatEntryName=13 |
630 if(isSameSector) |
639 if(isSameSector) |
631 { |
640 { |
632 Mem::Copy(&localBuf[offset],&vFatEntry,KSizeOfFatDirEntry); |
641 Mem::Copy(&localBuf[offset],&vFatEntry,KSizeOfFatDirEntry); |
633 offset+=KSizeOfFatDirEntry; |
642 offset+=KSizeOfFatDirEntry; |
634 MoveToNextEntryL(aPos); |
643 MoveToNextEntryL(aPos); |
635 } |
644 } |
636 else |
645 else |
637 { |
646 { |
638 WriteDirEntryL(aPos,vFatEntry); |
647 WriteDirEntryL(aPos,vFatEntry); |
639 MoveToNextEntryL(aPos); |
648 MoveToNextEntryL(aPos); |
640 } |
649 } |
641 } |
650 } |
642 if(isSameSector) |
651 if(isSameSector) |
643 { |
652 { |
644 Mem::Copy(&localBuf[offset],&aFatDirEntry,KSizeOfFatDirEntry); |
653 Mem::Copy(&localBuf[offset],&aFatDirEntry,KSizeOfFatDirEntry); |
645 |
654 |
646 //-- use special interface to access FAT directory file |
655 //-- use special interface to access FAT directory file |
647 DirWriteL(startPos,TPtrC8(&localBuf[0],dosOffset+KSizeOfFatDirEntry)); |
656 DirWriteL(startPos,TPtrC8(&localBuf[0],dosOffset+KSizeOfFatDirEntry)); |
648 } |
657 } |
649 else |
658 else |
650 WriteDirEntryL(aPos,aFatDirEntry); |
659 WriteDirEntryL(aPos,aFatDirEntry); |
651 } |
660 } |
652 |
661 |
653 void CFatMountCB::EraseDirEntryL(TEntryPos aPos,const TFatDirEntry& aFirstEntry) |
662 void CFatMountCB::EraseDirEntryL(TEntryPos aPos,const TFatDirEntry& aFirstEntry) |
654 // |
663 // |
655 // Mark all entries in a VFat directory entry as erased |
664 // Mark all entries in a VFat directory entry as erased |
656 // |
665 // |
657 { |
666 { |
658 __PRINT(_L("VFAT::CFatMountCB::EraseDirEntryL")); |
667 __PRINT(_L("VFAT::CFatMountCB::EraseDirEntryL")); |
659 TInt numEntries=0; |
668 TInt numEntries=0; |
660 if (aFirstEntry.IsVFatEntry()) |
669 if (aFirstEntry.IsVFatEntry()) |
661 numEntries=aFirstEntry.NumFollowing(); |
670 numEntries=aFirstEntry.NumFollowing(); |
662 if(IsRuggedFSys()&&numEntries) |
671 if(IsRuggedFSys()&&numEntries) |
663 { |
672 { |
664 TInt count=numEntries; |
673 TInt count=numEntries; |
665 TEntryPos pos=aPos; |
674 TEntryPos pos=aPos; |
666 while(count--) |
675 while(count--) |
667 MoveToNextEntryL(pos); |
676 MoveToNextEntryL(pos); |
668 EraseDirEntryL(pos); |
677 EraseDirEntryL(pos); |
669 numEntries--; |
678 numEntries--; |
670 } |
679 } |
671 FOREVER |
680 FOREVER |
672 { |
681 { |
673 EraseDirEntryL(aPos); |
682 EraseDirEntryL(aPos); |
674 if (!numEntries--) |
683 if (!numEntries--) |
675 break; |
684 break; |
676 MoveToNextEntryL(aPos); |
685 MoveToNextEntryL(aPos); |
677 } |
686 } |
678 } |
687 } |
679 |
688 |
680 |
689 |
681 void LocaleUtils::ConvertFromUnicodeL(TDes8& aForeign, const TDesC16& aUnicode, TFatUtilityFunctions::TOverflowAction aOverflowAction) |
690 void LocaleUtils::ConvertFromUnicodeL(TDes8& aForeign, const TDesC16& aUnicode, TFatUtilityFunctions::TOverflowAction aOverflowAction) |
682 // |
691 // |
683 // Convert the volume label using the algorithm specified in the current locale-DLL. |
692 // Convert the volume label using the algorithm specified in the current locale-DLL. |
684 // |
693 // |
685 { |
694 { |
686 if(aOverflowAction == TFatUtilityFunctions::EOverflowActionLeave) |
695 if(aOverflowAction == TFatUtilityFunctions::EOverflowActionLeave) |
687 { |
696 { |
688 GetCodePage().ConvertFromUnicodeL(aForeign, aUnicode, TCodePageUtils::EOverflowActionLeave); |
697 GetCodePage().ConvertFromUnicodeL(aForeign, aUnicode, TCodePageUtils::EOverflowActionLeave); |
689 } |
698 } |
690 else |
699 else |
691 { |
700 { |
692 GetCodePage().ConvertFromUnicodeL(aForeign, aUnicode, TCodePageUtils::EOverflowActionTruncate); |
701 GetCodePage().ConvertFromUnicodeL(aForeign, aUnicode, TCodePageUtils::EOverflowActionTruncate); |
693 } |
702 } |
694 } |
703 } |
695 |
704 |
696 void LocaleUtils::ConvertToUnicodeL(TDes16& aUnicode, const TDesC8& aForeign, TFatUtilityFunctions::TOverflowAction aOverflowAction) |
705 void LocaleUtils::ConvertToUnicodeL(TDes16& aUnicode, const TDesC8& aForeign, TFatUtilityFunctions::TOverflowAction aOverflowAction) |
697 // |
706 // |
698 // Convert the volume label using the algorithm specified in the current locale-DLL. |
707 // Convert the volume label using the algorithm specified in the current locale-DLL. |
699 // |
708 // |
700 { |
709 { |
701 if(aOverflowAction == TFatUtilityFunctions::EOverflowActionLeave) |
710 if(aOverflowAction == TFatUtilityFunctions::EOverflowActionLeave) |
702 { |
711 { |
703 GetCodePage().ConvertToUnicodeL(aUnicode, aForeign, TCodePageUtils::EOverflowActionLeave); |
712 GetCodePage().ConvertToUnicodeL(aUnicode, aForeign, TCodePageUtils::EOverflowActionLeave); |
704 } |
713 } |
705 else |
714 else |
706 { |
715 { |
707 GetCodePage().ConvertToUnicodeL(aUnicode, aForeign, TCodePageUtils::EOverflowActionTruncate); |
716 GetCodePage().ConvertToUnicodeL(aUnicode, aForeign, TCodePageUtils::EOverflowActionTruncate); |
708 } |
717 } |
709 } |
718 } |
710 |
719 |
711 TBool LocaleUtils::IsLegalShortNameCharacter(TUint aCharacter,TBool aUseExtendedChars) |
720 TBool LocaleUtils::IsLegalShortNameCharacter(TUint aCharacter,TBool aUseExtendedChars) |
712 // |
721 // |
713 // Convert the volume label using the algorithm specified in the current locale-DLL. |
722 // Convert the volume label using the algorithm specified in the current locale-DLL. |
714 // |
723 // |
715 { |
724 { |
716 return GetCodePage().IsLegalShortNameCharacter(aCharacter, aUseExtendedChars); |
725 return GetCodePage().IsLegalShortNameCharacter(aCharacter, aUseExtendedChars); |
717 } |
726 } |