|
1 // file_utils.cpp |
|
2 // |
|
3 // Copyright (c) 2006 - 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 #include <e32base.h> |
|
14 #include <f32file.h> |
|
15 #include "ioutils.h" |
|
16 |
|
17 using namespace IoUtils; |
|
18 |
|
19 |
|
20 // |
|
21 // Constants. |
|
22 // |
|
23 |
|
24 _LIT(KSlash, "\\"); |
|
25 _LIT(KDoubleSlash, "\\\\"); |
|
26 _LIT(KDot, "."); |
|
27 _LIT(KDoubleDot, ".."); |
|
28 |
|
29 __ASSERT_COMPILE(sizeof(TFileName2) == sizeof(TFileName) + 4); |
|
30 |
|
31 // |
|
32 // TFileName2. |
|
33 // |
|
34 |
|
35 EXPORT_C TFileName2::TFileName2() |
|
36 { |
|
37 new(this) TFileName2(EFile); |
|
38 } |
|
39 |
|
40 EXPORT_C TFileName2::TFileName2(TType aType) |
|
41 { |
|
42 new(this) TFileName2(KNullDesC, aType); |
|
43 } |
|
44 |
|
45 EXPORT_C TFileName2::TFileName2(const TDesC& aName) |
|
46 : TBuf<256>(aName), iType(EFile) |
|
47 { |
|
48 new(this) TFileName2(aName, EFile); |
|
49 } |
|
50 |
|
51 EXPORT_C TFileName2::TFileName2(const TDesC& aName, TType aType) |
|
52 : TBuf<256>(aName), iType(aType) |
|
53 { |
|
54 // Remove any double slashes that may be present. |
|
55 TInt pos; |
|
56 while ((pos = Find(KDoubleSlash)) >= 0) |
|
57 { |
|
58 Delete(pos, 1); |
|
59 } |
|
60 } |
|
61 |
|
62 EXPORT_C TBool TFileName2::IsAbsolute() const |
|
63 { |
|
64 return ((Length() >= 3) && TChar((*this)[0]).IsAlpha() && ((*this)[1] == ':') && ((*this)[2] == '\\')); |
|
65 } |
|
66 |
|
67 EXPORT_C TBool TFileName2::IsDriveLetter() const |
|
68 { |
|
69 return (Length() == 2) && TChar((*this)[0]).IsAlpha() && ((*this)[1] == ':'); |
|
70 } |
|
71 |
|
72 EXPORT_C TBool TFileName2::IsDriveRoot() const |
|
73 { |
|
74 return ((Length() == 3) && TChar((*this)[0]).IsAlpha() && ((*this)[1] == ':') && ((*this)[2] == '\\')); |
|
75 } |
|
76 |
|
77 EXPORT_C TBool TFileName2::IsWild() const |
|
78 { |
|
79 return TParsePtrC(*this).IsWild(); |
|
80 } |
|
81 |
|
82 EXPORT_C TBool TFileName2::IsFile() const |
|
83 { |
|
84 TBool ret = (iType == EFile); |
|
85 ASSERT((ret && !HasTrailingSlash()) || (!ret && HasTrailingSlash())); |
|
86 return ret; |
|
87 } |
|
88 |
|
89 EXPORT_C TBool TFileName2::IsDir() const |
|
90 { |
|
91 TBool ret = (iType == EDirectory); |
|
92 ASSERT((ret && HasTrailingSlash()) || (!ret && !HasTrailingSlash())); |
|
93 return ret; |
|
94 } |
|
95 |
|
96 EXPORT_C TBool TFileName2::HasDriveLetter() const |
|
97 { |
|
98 return ((Length() >= 2) && TChar((*this)[0]).IsAlpha() && ((*this)[1] == ':')); |
|
99 } |
|
100 |
|
101 EXPORT_C TBool TFileName2::HasLeadingSlash() const |
|
102 { |
|
103 return ((Length() >= 1) && ((*this)[0] == '\\')); |
|
104 } |
|
105 |
|
106 EXPORT_C TBool TFileName2::HasTrailingSlash() const |
|
107 { |
|
108 return ((Length() >= 1) && ((*this)[Length() - 1] == '\\')); |
|
109 } |
|
110 |
|
111 EXPORT_C TPtrC TFileName2::Drive() const |
|
112 { |
|
113 return TParsePtrC(*this).Drive(); |
|
114 } |
|
115 |
|
116 EXPORT_C TPtrC TFileName2::Path() const |
|
117 { |
|
118 return TParsePtrC(*this).Path(); |
|
119 } |
|
120 |
|
121 EXPORT_C TPtrC TFileName2::DriveAndPath() const |
|
122 { |
|
123 return TParsePtrC(*this).DriveAndPath(); |
|
124 } |
|
125 |
|
126 EXPORT_C TPtrC TFileName2::Name() const |
|
127 { |
|
128 return TParsePtrC(*this).Name(); |
|
129 } |
|
130 |
|
131 EXPORT_C TPtrC TFileName2::Ext() const |
|
132 { |
|
133 return TParsePtrC(*this).Ext(); |
|
134 } |
|
135 |
|
136 EXPORT_C TPtrC TFileName2::NameAndExt() const |
|
137 { |
|
138 return TParsePtrC(*this).NameAndExt(); |
|
139 } |
|
140 |
|
141 EXPORT_C void TFileName2::SetL(const TFileName2& aName) |
|
142 { |
|
143 Zero(); |
|
144 AppendComponentL(aName); |
|
145 } |
|
146 |
|
147 EXPORT_C void TFileName2::SetTypeL(TType aType) |
|
148 { |
|
149 switch (aType) |
|
150 { |
|
151 case EFile: |
|
152 { |
|
153 if (HasTrailingSlash() && ((HasDriveLetter() && (Length() > 3)) || (!HasDriveLetter() && (Length() > 1)))) |
|
154 { |
|
155 Delete(Length() - 1, 1); |
|
156 } |
|
157 iType = EFile; |
|
158 break; |
|
159 } |
|
160 case EDirectory: |
|
161 { |
|
162 if (!HasTrailingSlash()) |
|
163 { |
|
164 AppendComponentL(KNullDesC()); |
|
165 } |
|
166 iType = EDirectory; |
|
167 break; |
|
168 } |
|
169 default: |
|
170 { |
|
171 ASSERT(EFalse); |
|
172 } |
|
173 } |
|
174 } |
|
175 |
|
176 EXPORT_C void TFileName2::SetTypeL(RFs& aFs) |
|
177 { |
|
178 if (IsDirL(aFs)) |
|
179 { |
|
180 SetTypeL(EDirectory); |
|
181 } |
|
182 else |
|
183 { |
|
184 SetTypeL(EFile); |
|
185 } |
|
186 } |
|
187 |
|
188 EXPORT_C void TFileName2::SetDriveL(const TDesC& aDrive) |
|
189 { |
|
190 if (Drive().Length() > 0) |
|
191 { |
|
192 (*this)[0] = aDrive[0]; |
|
193 } |
|
194 else |
|
195 { |
|
196 PrependL(aDrive); |
|
197 } |
|
198 } |
|
199 |
|
200 EXPORT_C void TFileName2::SetPathL(const TDesC& aPath) |
|
201 { |
|
202 TFileName2 temp; |
|
203 temp.SetDriveL(Drive()); |
|
204 temp.AppendComponentL(aPath); |
|
205 temp.SetNameAndExtL(NameAndExt()); |
|
206 Copy(temp); |
|
207 } |
|
208 |
|
209 EXPORT_C void TFileName2::SetNameL(const TDesC& aName) |
|
210 { |
|
211 TPtrC namePtrC(Name()); |
|
212 if (namePtrC.Length() > 0) |
|
213 { |
|
214 CheckSpaceL(aName.Length() - namePtrC.Length()); |
|
215 TInt namePos = namePtrC.Ptr() - Ptr(); |
|
216 Delete(namePos, namePtrC.Length()); |
|
217 Insert(namePos, aName); |
|
218 } |
|
219 else |
|
220 { |
|
221 AppendComponentL(aName); |
|
222 } |
|
223 } |
|
224 |
|
225 EXPORT_C void TFileName2::SetExtL(const TDesC& aExt) |
|
226 { |
|
227 TPtrC extPtrC(Ext()); |
|
228 if (extPtrC.Length() > 0) |
|
229 { |
|
230 CheckSpaceL(aExt.Length() + ((aExt[0] == '.') ? 0 : 1) - extPtrC.Length()); |
|
231 Delete(extPtrC.Ptr() - Ptr(), extPtrC.Length()); |
|
232 } |
|
233 else |
|
234 { |
|
235 CheckSpaceL(aExt.Length() + ((aExt[0] == '.') ? 0 : 1)); |
|
236 } |
|
237 |
|
238 if (aExt[0] != '.') |
|
239 { |
|
240 Append('.'); |
|
241 } |
|
242 Append(aExt); |
|
243 } |
|
244 |
|
245 EXPORT_C void TFileName2::SetNameAndExtL(const TDesC& aNameAndExt) |
|
246 { |
|
247 TPtrC nameAndExtPtrC(NameAndExt()); |
|
248 if (nameAndExtPtrC.Length() > 0) |
|
249 { |
|
250 CheckSpaceL(aNameAndExt.Length() - nameAndExtPtrC.Length()); |
|
251 TInt nameAndExtPos = nameAndExtPtrC.Ptr() - Ptr(); |
|
252 Delete(nameAndExtPos, nameAndExtPtrC.Length()); |
|
253 Insert(nameAndExtPos, aNameAndExt); |
|
254 } |
|
255 else |
|
256 { |
|
257 AppendComponentL(aNameAndExt); |
|
258 } |
|
259 } |
|
260 |
|
261 EXPORT_C void TFileName2::PrependL(const TFileName2& aName) |
|
262 { |
|
263 if (Length() == 0) |
|
264 { |
|
265 CheckSpaceL(aName.Length() + (((iType == EDirectory) && !HasTrailingSlash()) ? 1 : 0)); |
|
266 Append(aName); |
|
267 } |
|
268 else if (aName.HasTrailingSlash() && HasLeadingSlash()) |
|
269 { |
|
270 CheckSpaceL(aName.Length() - 1 + (((iType == EDirectory) && !HasTrailingSlash()) ? 1 : 0)); |
|
271 Insert(0, aName.Mid(1)); |
|
272 } |
|
273 else if (!aName.HasTrailingSlash() && !HasLeadingSlash()) |
|
274 { |
|
275 CheckSpaceL(aName.Length() + 1 + (((iType == EDirectory) && !HasTrailingSlash()) ? 1 : 0)); |
|
276 Insert(0, KSlash); |
|
277 Insert(0, aName); |
|
278 } |
|
279 else |
|
280 { |
|
281 CheckSpaceL(aName.Length() + (((iType == EDirectory) && !HasTrailingSlash()) ? 1 : 0)); |
|
282 Insert(0, aName); |
|
283 } |
|
284 |
|
285 if ((iType == EDirectory) && (!HasTrailingSlash())) |
|
286 { |
|
287 Append(KSlash); |
|
288 } |
|
289 } |
|
290 |
|
291 EXPORT_C void TFileName2::AppendComponentL(const TFileName2& aName) |
|
292 { |
|
293 AppendComponentL(aName, iType); |
|
294 } |
|
295 |
|
296 EXPORT_C void TFileName2::AppendComponentL(const TDesC& aPathComponent, TFileName2::TType aType) |
|
297 { |
|
298 // This function doesn't use iType, therefore you can call it and get the same results regardless of whether the type has been set - you will only get a trailing slash if (a) aPathComponent ends in a slash, or (b) aType is EDirectory. |
|
299 TPtrC pathWithoutLeadingSlash(aPathComponent); |
|
300 if (aPathComponent.Length() && aPathComponent[0] == '\\') pathWithoutLeadingSlash.Set(aPathComponent.Mid(1)); |
|
301 TInt pathLen = pathWithoutLeadingSlash.Length(); |
|
302 const TDesC* middle = &KNullDesC; |
|
303 if (Length() && !HasTrailingSlash()) middle = &KSlash; |
|
304 const TDesC* end = &KNullDesC; |
|
305 if (aType == EDirectory && pathLen && pathWithoutLeadingSlash[pathLen-1] != '\\') end = &KSlash; |
|
306 CheckSpaceL(pathLen + middle->Length() + end->Length()); |
|
307 |
|
308 Append(*middle); |
|
309 Append(pathWithoutLeadingSlash); |
|
310 Append(*end); |
|
311 } |
|
312 |
|
313 EXPORT_C void TFileName2::AppendComponentL(const TEntry& aEntry) |
|
314 { |
|
315 AppendComponentL(aEntry.iName, aEntry.IsDir() ? EDirectory : EFile); |
|
316 } |
|
317 |
|
318 EXPORT_C void TFileName2::SetIsDirectoryL() |
|
319 { |
|
320 // This is the more complicated way to do it, the other would be: if (!HasTrailingSlash()) AppendL(KSlash); |
|
321 // Or indeed, AppendComponentL(KNullDesC, EDirectory) since the type is irrelevant if the component is empty |
|
322 AppendComponentL(KNullDesC, EFile); |
|
323 } |
|
324 |
|
325 void TFileName2::CheckSpaceL(TInt aLengthToAdd) const |
|
326 { |
|
327 if ((MaxLength() - Length()) < aLengthToAdd) |
|
328 { |
|
329 User::Leave(KErrTooBig); |
|
330 } |
|
331 } |
|
332 |
|
333 EXPORT_C void TFileName2::SplitL(RArray<TFileName2>& aOutput) |
|
334 { |
|
335 TLex lex(*this); |
|
336 while (!lex.Eos()) |
|
337 { |
|
338 lex.Mark(); |
|
339 while (!lex.Eos() && (lex.Peek() != '\\')) |
|
340 { |
|
341 lex.Get(); |
|
342 } |
|
343 User::LeaveIfError(aOutput.Append(TFileName2(lex.MarkedToken()))); |
|
344 if (!lex.Eos()) |
|
345 { |
|
346 // Skip over the slash |
|
347 lex.Get(); |
|
348 if (lex.Eos()) |
|
349 { |
|
350 // ended with slash - insert empty path component |
|
351 User::LeaveIfError(aOutput.Append(TFileName2())); |
|
352 } |
|
353 } |
|
354 } |
|
355 } |
|
356 |
|
357 EXPORT_C void TFileName2::MakeAbsoluteL(const TFileName2& aAbsoluteTo) |
|
358 { |
|
359 ASSERT(aAbsoluteTo.IsAbsolute()); |
|
360 |
|
361 if (IsAbsolute()) |
|
362 { |
|
363 return; |
|
364 } |
|
365 |
|
366 if (HasLeadingSlash()) |
|
367 { |
|
368 // Just prepend drive letter. |
|
369 PrependL(aAbsoluteTo.Left(2)); |
|
370 return; |
|
371 } |
|
372 |
|
373 PrependL(aAbsoluteTo); |
|
374 RArray<TFileName2> splitName; |
|
375 CleanupClosePushL(splitName); |
|
376 SplitL(splitName); |
|
377 TInt i = 0; |
|
378 while (i < splitName.Count()) |
|
379 { |
|
380 const TFileName2& piece = splitName[i]; |
|
381 if (piece == KDot) |
|
382 { |
|
383 splitName.Remove(i); |
|
384 } |
|
385 else if (piece == KDoubleDot) |
|
386 { |
|
387 if ((i == 0) || ((i == 1) && splitName[0].IsDriveLetter())) |
|
388 { |
|
389 User::Leave(KErrBadName); |
|
390 } |
|
391 splitName.Remove(i); |
|
392 splitName.Remove(i - 1); |
|
393 --i; |
|
394 } |
|
395 else if ((piece == KNullDesC) && (i != 0) && (i != splitName.Count()-1)) |
|
396 { |
|
397 // Allow empty piece in first or last slot to support leading/trailing slashes. |
|
398 splitName.Remove(i); |
|
399 } |
|
400 else |
|
401 { |
|
402 ++i; |
|
403 } |
|
404 } |
|
405 |
|
406 UnsplitL(splitName); |
|
407 CleanupStack::PopAndDestroy(&splitName); |
|
408 } |
|
409 |
|
410 EXPORT_C void TFileName2::MakeAbsoluteL(RFs& aFs) |
|
411 { |
|
412 TFileName2 sessionPath; |
|
413 User::LeaveIfError(aFs.SessionPath(sessionPath)); |
|
414 MakeAbsoluteL(sessionPath); |
|
415 } |
|
416 |
|
417 EXPORT_C void TFileName2::UnsplitL(const RArray<TFileName2>& aInput) |
|
418 { |
|
419 Zero(); |
|
420 const TInt count = aInput.Count(); |
|
421 for (TInt i = 0; i < count; ++i) |
|
422 { |
|
423 AppendComponentL(aInput[i]); |
|
424 } |
|
425 if ((count == 1) && (aInput[0].Match(_L("?:")) == 0)) |
|
426 { |
|
427 Append(KSlash); |
|
428 } |
|
429 } |
|
430 |
|
431 EXPORT_C TBool TFileName2::Exists(RFs& aFs) const |
|
432 { |
|
433 TInt err; |
|
434 if (IsDriveRoot()) |
|
435 { |
|
436 TInt driveNumber; |
|
437 err = RFs::CharToDrive(Drive()[0], driveNumber); |
|
438 if (err == KErrNone) |
|
439 { |
|
440 TDriveInfo driveInfo; |
|
441 err = aFs.Drive(driveInfo, driveNumber); |
|
442 } |
|
443 } |
|
444 else |
|
445 { |
|
446 TUint att; |
|
447 err = aFs.Att(*this, att); |
|
448 } |
|
449 return (err == KErrNone); |
|
450 } |
|
451 |
|
452 EXPORT_C TBool TFileName2::IsReadOnlyL(RFs& aFs) const |
|
453 { |
|
454 TEntry entry; |
|
455 User::LeaveIfError(aFs.Entry(*this, entry)); |
|
456 return entry.IsReadOnly(); |
|
457 } |
|
458 |
|
459 EXPORT_C TBool TFileName2::IsHiddenL(RFs& aFs) const |
|
460 { |
|
461 TEntry entry; |
|
462 User::LeaveIfError(aFs.Entry(*this, entry)); |
|
463 return entry.IsHidden(); |
|
464 } |
|
465 |
|
466 EXPORT_C TBool TFileName2::IsSystemL(RFs& aFs) const |
|
467 { |
|
468 TEntry entry; |
|
469 User::LeaveIfError(aFs.Entry(*this, entry)); |
|
470 return entry.IsSystem(); |
|
471 } |
|
472 |
|
473 EXPORT_C TBool TFileName2::IsDirL(RFs& aFs) const |
|
474 { |
|
475 if (IsDriveRoot()) |
|
476 { |
|
477 if (!Exists(aFs)) |
|
478 { |
|
479 User::Leave(KErrNotFound); |
|
480 } |
|
481 return ETrue; |
|
482 } |
|
483 else |
|
484 { |
|
485 TEntry entry; |
|
486 User::LeaveIfError(aFs.Entry(*this, entry)); |
|
487 return entry.IsDir(); |
|
488 } |
|
489 } |
|
490 |
|
491 EXPORT_C TBool TFileName2::IsArchiveL(RFs& aFs) const |
|
492 { |
|
493 TEntry entry; |
|
494 User::LeaveIfError(aFs.Entry(*this, entry)); |
|
495 return entry.IsArchive(); |
|
496 } |
|
497 |
|
498 EXPORT_C TInt TFileName2::FindFile(RFs& aFs) |
|
499 { |
|
500 TFindFile ff(aFs); |
|
501 TInt err = ff.FindByDir(*this, KNullDesC); |
|
502 if (err==KErrNone) |
|
503 { |
|
504 *this = ff.File(); |
|
505 } |
|
506 return err; |
|
507 } |
|
508 |
|
509 EXPORT_C void TFileName2::FindFileL(RFs& aFs) |
|
510 { |
|
511 User::LeaveIfError(FindFile(aFs)); |
|
512 } |
|
513 |