|
1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "cl_std.h" |
|
17 #include "cl_scan.h" |
|
18 |
|
19 const TInt KDirStackGranularity=8; |
|
20 |
|
21 /** Replace long names in path and filename with their sohrter version (if exists). Optionally appends |
|
22 filename to path name creating fully qualified file name. |
|
23 @param aFs (connected) File system session |
|
24 @param aCurrentPath on input contains current full path name, |
|
25 upon return contains the shortest version (using either shor or long names) of the same path |
|
26 @param aItem on input contains item with long name in the current path, |
|
27 upon return contains shorter name of either long or short name |
|
28 @param aAppend if ETrue aItem will be appended to aCurrentPath before successful return |
|
29 @return KErrNone if successful, otherwise one of the other system-wide error codes. |
|
30 */ |
|
31 TInt ShrinkNames(RFs& aFs, TFileName& aCurrentPath, TFileName& aItem, TBool aAppend) |
|
32 { |
|
33 TInt ret = KErrNone; |
|
34 TBuf<8+1+3> shortname; |
|
35 TFileName* current = NULL; |
|
36 TRAPD(r,current = new (ELeave) TFileName); |
|
37 if (r) |
|
38 return r; |
|
39 |
|
40 TInt pos = 0; |
|
41 TInt lastslash = KErrNotFound; |
|
42 TInt lastnewslash = KErrNotFound; |
|
43 while(ret == KErrNone && pos < aCurrentPath.Length()) |
|
44 { |
|
45 if(aCurrentPath[pos] == KPathDelimiter) |
|
46 { |
|
47 if(lastslash != KErrNotFound) |
|
48 { |
|
49 ret = aFs.GetShortName(*current, shortname); |
|
50 if(ret == KErrNone && pos-lastslash > shortname.Length()) |
|
51 { |
|
52 current->SetLength(lastnewslash); |
|
53 current->Append(shortname); |
|
54 } |
|
55 } |
|
56 lastslash = pos+1; |
|
57 lastnewslash = current->Length()+1; |
|
58 } |
|
59 current->Append(aCurrentPath[pos++]); |
|
60 } |
|
61 if(ret == KErrNone && current->Length() + aItem.Length() <= KMaxFileName) |
|
62 { |
|
63 aCurrentPath = *current; |
|
64 TInt lenBefore = aCurrentPath.Length(); |
|
65 aCurrentPath.Append(aItem); |
|
66 ret = aFs.GetShortName(aCurrentPath, shortname); |
|
67 aCurrentPath.SetLength(lenBefore); |
|
68 |
|
69 if(ret == KErrNone && aItem.Length() > shortname.Length()) |
|
70 { |
|
71 aItem = shortname; |
|
72 } |
|
73 } |
|
74 if(aAppend && ret == KErrNone && aCurrentPath.Length() + aItem.Length() <= KMaxFileName) |
|
75 { |
|
76 aCurrentPath.Append(aItem); |
|
77 } |
|
78 delete current; |
|
79 return ret; |
|
80 } |
|
81 |
|
82 LOCAL_C TPtrC LeafDir(const TDesC& aPath) |
|
83 // |
|
84 // Returns the leaf directory of a path |
|
85 // |
|
86 { |
|
87 |
|
88 TInt end=aPath.LocateReverse('\\'); |
|
89 __ASSERT_DEBUG(end!=KErrNotFound,Panic(EDirListError)); |
|
90 TPtrC ret(aPath.Ptr(),end); |
|
91 TInt start=ret.LocateReverse('\\'); |
|
92 if (start==KErrNotFound) |
|
93 start=end-1; |
|
94 return ret.Right(end-start-1); |
|
95 } |
|
96 |
|
97 CDirScan::CDirScan(RFs& aFs) |
|
98 // |
|
99 // Constructor |
|
100 // |
|
101 : iFs(&aFs) |
|
102 { |
|
103 } |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 EXPORT_C CDirScan* CDirScan::NewLC(RFs& aFs) |
|
109 /** |
|
110 Constructs and allocates memory for a new CDirScan object, putting a pointer |
|
111 to the object onto the cleanup stack. |
|
112 |
|
113 @param aFs The file server session. |
|
114 |
|
115 @return A pointer to the new directory scan object. |
|
116 */ |
|
117 { |
|
118 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanNewLC, MODULEUID, aFs.Handle()); |
|
119 |
|
120 CDirScan* scan=new(ELeave) CDirScan(aFs); |
|
121 CleanupStack::PushL(scan); |
|
122 scan->iStack=CDirStack::NewL(); |
|
123 |
|
124 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanNewLCReturn, MODULEUID, scan); |
|
125 return scan; |
|
126 } |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 EXPORT_C CDirScan* CDirScan::NewL(RFs& aFs) |
|
132 /** |
|
133 Constructs and allocates memory for a new CDirScan object. |
|
134 |
|
135 @param aFs The file server session. |
|
136 |
|
137 @return A pointer to the new directory scan object. |
|
138 */ |
|
139 { |
|
140 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanNewL, MODULEUID, aFs.Handle()); |
|
141 |
|
142 CDirScan* scan=CDirScan::NewLC(aFs); |
|
143 CleanupStack::Pop(); |
|
144 |
|
145 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanNewLReturn, MODULEUID, scan); |
|
146 return scan; |
|
147 } |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 EXPORT_C CDirScan::~CDirScan() |
|
153 /** |
|
154 Desctructor. |
|
155 |
|
156 Frees all resources owned by the object, prior to its destruction. |
|
157 */ |
|
158 { |
|
159 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanDestructor, MODULEUID, this); |
|
160 |
|
161 delete iStack; |
|
162 |
|
163 TRACE0(UTF::EBorder, UTraceModuleEfsrv::ECDirScanDestructorReturn, MODULEUID); |
|
164 } |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 EXPORT_C void CDirScan::SetScanDataL(const TDesC& aMatchName,TUint anEntryAttMask,TUint anEntrySortKey,TScanDirection aScanDir) |
|
170 /** |
|
171 Initialises the scan. |
|
172 |
|
173 This involves specifying: |
|
174 |
|
175 1. the directory at the top of the structure to be scanned |
|
176 |
|
177 2. a filter for the entry types of interest |
|
178 |
|
179 3. the order in which the entries in each directory in the structure are to be sorted |
|
180 |
|
181 4. the scan direction. |
|
182 |
|
183 Whether the scan direction is upwards or downwards, the directories that are |
|
184 scanned are those in the part of the hierarchy below the directory |
|
185 specified in aMatchName. By default, the scan direction is downwards. |
|
186 If the scan direction is set to CDirScan::EScanUpTree, then all branches of |
|
187 the tree are explored starting at the lowest level directory in |
|
188 the tree below aMatchName, and ending at aMatchName. |
|
189 This option is provided for deleting a directory structure. |
|
190 |
|
191 @param aMatchName The top level directory for the scan. Any path components |
|
192 that are not specified here are taken from the session path. |
|
193 Note that the trailing backslash is required to specify the directory. |
|
194 I.e. path x:\\dir1\\dir2\\ means that the scan will start from dir2, while |
|
195 path x:\\dir1\\dir2 assumes scan starting from x:\\dir1\\ |
|
196 |
|
197 @param anEntryAttMask A bit mask that filters the entry types which should be returned by |
|
198 NextL(). The mask works as follows: |
|
199 To match files only, specify KEntryAttNormal. |
|
200 To match both files and directories, |
|
201 specify KEntryAttDir. |
|
202 To match directories only, |
|
203 specify KEntryAttDir|KEntryAttMatchExclusive. |
|
204 To match files with a specific attribute, |
|
205 then OR the attribute involved with |
|
206 KEntryAttMatchExclusive. |
|
207 For example, to match read-only files, |
|
208 specify KEntryAttReadOnly|KEntryAttMatchExclusive. |
|
209 For more information, |
|
210 see KEntryAttNormal or |
|
211 the other file/directory attributes. |
|
212 @param anEntrySortKey The order in which the directories are scanned by |
|
213 NextL(). This flag is defined in TEntryKey. |
|
214 @param aScanDir The direction of the scan. The default is downwards. |
|
215 */ |
|
216 { |
|
217 TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECDirScanSetScanDataL, MODULEUID, (TUint) |
|
218 this, aMatchName, anEntryAttMask, anEntrySortKey, (TUint) aScanDir); |
|
219 |
|
220 TInt r = Fs().Parse(aMatchName,iFullPath); |
|
221 if (r != KErrNone) |
|
222 { |
|
223 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanSetScanDataLReturn, MODULEUID, r); |
|
224 User::Leave(r); |
|
225 } |
|
226 |
|
227 iScanning = ETrue; |
|
228 iEntryAttMask=anEntryAttMask; |
|
229 iEntrySortMask=anEntrySortKey; |
|
230 iStack->ResetL(LeafDir(iFullPath.FullName())); |
|
231 iAbbreviatedPathPos=iFullPath.DriveAndPath().Length()-1; |
|
232 iAbbreviatedPath.Set(_L("\\")); |
|
233 iScanDir=aScanDir; |
|
234 if (aScanDir==EScanDownTree) |
|
235 iFullPath.PopDir(); |
|
236 |
|
237 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanSetScanDataLReturn, MODULEUID, KErrNone); |
|
238 } |
|
239 |
|
240 void CDirScan::UpdateAbbreviatedPath() |
|
241 // |
|
242 // Set the abbreviated path based on the full path |
|
243 // |
|
244 { |
|
245 |
|
246 TInt length=iFullPath.DriveAndPath().Length(); |
|
247 TPtrC fullName=iFullPath.FullName(); |
|
248 if (length>iAbbreviatedPathPos) |
|
249 iAbbreviatedPath.Set(&fullName[0]+iAbbreviatedPathPos,length-iAbbreviatedPathPos); |
|
250 else |
|
251 iAbbreviatedPath.Set(_L("\\")); |
|
252 } |
|
253 |
|
254 |
|
255 |
|
256 |
|
257 EXPORT_C void CDirScan::NextL(CDir*& aDirEntries) |
|
258 /** |
|
259 Scans the next directory entry in the structure. |
|
260 |
|
261 The order in which the structure is scanned is determined by the scan |
|
262 direction and the entry sort mask. These values are specified when setting up |
|
263 the scan. The type of entries retrieved by this function is determined by the |
|
264 entry attribute mask. This is also specified when setting up the scan. |
|
265 |
|
266 Notes: |
|
267 |
|
268 1. The function first sets aDirEntries to NULL, and then allocates memory for |
|
269 it before appending entries to it. Therefore, aDirEntries should have no |
|
270 memory allocated to it before this function is called, otherwise this |
|
271 memory will become orphaned. |
|
272 |
|
273 2. The caller of this function is responsible for deleting aDirEntries after |
|
274 the function has returned. |
|
275 |
|
276 @param aDirEntries On return, a pointer to an array containing filtered entries |
|
277 from the next directory in the structure. NULL if there are |
|
278 no more directories in the structure. |
|
279 */ |
|
280 { |
|
281 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanNextL, MODULEUID, this); |
|
282 |
|
283 if (iScanDir==EScanUpTree) |
|
284 ScanUpTreeL(aDirEntries); |
|
285 else |
|
286 ScanDownTreeL(aDirEntries); |
|
287 |
|
288 TRACE2(UTF::EBorder, UTraceModuleEfsrv::ECDirScanNextLReturn, MODULEUID, |
|
289 KErrNone, aDirEntries ? (*aDirEntries).Count() : 0); |
|
290 } |
|
291 |
|
292 void CDirScan::ScanUpTreeL(CDir*& aDirEntries) |
|
293 // |
|
294 // Get the next directory starting from the bottom of the tree |
|
295 // eg: for deleting a directory structure |
|
296 // |
|
297 { |
|
298 TInt r; |
|
299 iFullPath.PopDir(); |
|
300 CDirList* list=iStack->Peek(); |
|
301 if (!list->MoreEntries()) |
|
302 { |
|
303 iStack->Pop(); |
|
304 if (iStack->IsEmpty()) |
|
305 { |
|
306 aDirEntries=NULL; |
|
307 return; |
|
308 } |
|
309 UpdateAbbreviatedPath(); |
|
310 GetDirEntriesL(aDirEntries); |
|
311 return; |
|
312 } |
|
313 |
|
314 TFileName* next = new (ELeave) TFileName; |
|
315 CleanupStack::PushL(next); |
|
316 TFileName* current = new (ELeave) TFileName; |
|
317 CleanupStack::PushL(current); |
|
318 |
|
319 FOREVER |
|
320 { |
|
321 TPtrC dirName=list->Next().iName; |
|
322 r = iFullPath.AddDir(dirName); |
|
323 if (r==KErrGeneral) // adding dirName would make iFullPath > 256 characters |
|
324 { |
|
325 current->Copy(iFullPath.DriveAndPath()); |
|
326 next->Copy(dirName); |
|
327 |
|
328 r = ShrinkNames(Fs(), *current, *next, EFalse); |
|
329 if(r == KErrNone) |
|
330 { |
|
331 r = iFullPath.Set(*current, NULL, NULL); |
|
332 if(r == KErrNone) |
|
333 { |
|
334 r = iFullPath.AddDir(*next); |
|
335 } |
|
336 } |
|
337 } |
|
338 if (r != KErrNone) |
|
339 { |
|
340 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); |
|
341 User::LeaveIfError(r); |
|
342 } |
|
343 |
|
344 CDir* dirList; |
|
345 // Start by searching for directories only from top to bottom |
|
346 r = Fs().GetDir(iFullPath.DriveAndPath(), |
|
347 KEntryAttDir|KEntryAttMatchExclusive|(iEntryAttMask&KEntryAttMatchMask), |
|
348 iEntrySortMask, |
|
349 dirList); |
|
350 if (r == KErrPermissionDenied && !iScanning) |
|
351 { |
|
352 UpdateAbbreviatedPath(); |
|
353 aDirEntries = CDirFactory::NewL(); |
|
354 } |
|
355 else if (r != KErrNone) |
|
356 { |
|
357 iScanning = EFalse; |
|
358 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); |
|
359 User::Leave(r); |
|
360 } |
|
361 |
|
362 iScanning= EFalse; |
|
363 |
|
364 // Permission denied case. No entry |
|
365 if(!dirList) |
|
366 break; |
|
367 |
|
368 if (dirList->Count()==0)// No more directory entries - bottom of tree reached |
|
369 { |
|
370 delete dirList; |
|
371 break; |
|
372 } |
|
373 iStack->PushL(*dirList); |
|
374 list=iStack->Peek(); |
|
375 } //END OF FOREVER |
|
376 |
|
377 CleanupStack::PopAndDestroy(2); // current and next pointers |
|
378 |
|
379 UpdateAbbreviatedPath(); |
|
380 // Now get all valid entries for the lowest level directory encountered |
|
381 |
|
382 if(r!=KErrPermissionDenied ) |
|
383 { |
|
384 GetDirEntriesL(aDirEntries); |
|
385 } |
|
386 } |
|
387 |
|
388 void CDirScan::GetDirEntriesL(CDir*& aDirEntries) |
|
389 // |
|
390 // Call GetDir. |
|
391 // |
|
392 { |
|
393 TInt r = Fs().GetDir(iFullPath.FullName(),iEntryAttMask,iEntrySortMask,aDirEntries); |
|
394 if (r != KErrNone) |
|
395 { |
|
396 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); |
|
397 User::Leave(r); |
|
398 } |
|
399 } |
|
400 |
|
401 void CDirScan::ScanDownTreeL(CDir*& aDirEntries) |
|
402 // |
|
403 // Get the next directory starting from the top of the tree |
|
404 // eg: for copying a directory structure |
|
405 // |
|
406 { |
|
407 CDir* dirEntries = NULL; |
|
408 TInt r; |
|
409 aDirEntries=NULL; |
|
410 CDirList* list=iStack->Peek(); |
|
411 while (!list->MoreEntries()) |
|
412 { |
|
413 iStack->Pop(); |
|
414 if (iStack->IsEmpty()) |
|
415 { |
|
416 aDirEntries=NULL; |
|
417 return; |
|
418 } |
|
419 iFullPath.PopDir(); |
|
420 UpdateAbbreviatedPath(); |
|
421 list=iStack->Peek(); |
|
422 } |
|
423 |
|
424 TPtrC dirName=list->Next().iName; |
|
425 r=iFullPath.AddDir(dirName); |
|
426 if (r==KErrGeneral) // Adding dirName makes iFullPath>256 characters |
|
427 { |
|
428 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, KErrTooBig); |
|
429 User::Leave(KErrTooBig); |
|
430 } |
|
431 |
|
432 // Get all valid entries in this directory |
|
433 |
|
434 // coverity[alloc_arg] |
|
435 TRAP(r, GetDirEntriesL(dirEntries)); |
|
436 |
|
437 if (r == KErrNone) |
|
438 { |
|
439 iScanning = EFalse; |
|
440 CleanupStack::PushL(dirEntries); |
|
441 // Get all directories within this directory - the next level down in the tree |
|
442 CDir* dirList; |
|
443 |
|
444 // coverity[alloc_fn] |
|
445 r = Fs().GetDir(iFullPath.DriveAndPath(), |
|
446 KEntryAttDir|KEntryAttMatchExclusive|(iEntryAttMask&KEntryAttMatchMask), |
|
447 iEntrySortMask,dirList); |
|
448 if (r != KErrNone) |
|
449 { |
|
450 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); |
|
451 User::Leave(r); |
|
452 } |
|
453 iStack->PushL(*dirList); |
|
454 CleanupStack::Pop(); // dirEntries |
|
455 UpdateAbbreviatedPath(); |
|
456 aDirEntries=dirEntries; |
|
457 } |
|
458 else if (r == KErrPermissionDenied && !iScanning) |
|
459 { |
|
460 CDir* dirList = CDirFactory::NewL(); |
|
461 iStack->PushL(*dirList); |
|
462 aDirEntries = CDirFactory::NewL(); |
|
463 } |
|
464 else |
|
465 { |
|
466 iScanning = EFalse; |
|
467 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); |
|
468 User::Leave(r); |
|
469 } |
|
470 } |
|
471 |
|
472 |
|
473 |
|
474 |
|
475 EXPORT_C TPtrC CDirScan::AbbreviatedPath() |
|
476 /** |
|
477 Gets the abbreviated path of the entry currently being scanned. |
|
478 |
|
479 The abbreviated path is the path relative to the top level directory |
|
480 in the scan. |
|
481 |
|
482 @return A non modifiable pointer descriptor for the abbreviated path of |
|
483 the entry currently being scanned. |
|
484 */ |
|
485 { |
|
486 |
|
487 return iAbbreviatedPath; |
|
488 } |
|
489 |
|
490 |
|
491 |
|
492 |
|
493 EXPORT_C TPtrC CDirScan::FullPath() |
|
494 /** |
|
495 Gets the full path of the entry currently being scanned. |
|
496 |
|
497 The full path includes the drive letter. |
|
498 |
|
499 @return A non modifiable pointer descriptor for the full path of the entry |
|
500 currently being scanned. |
|
501 */ |
|
502 { |
|
503 |
|
504 return iFullPath.DriveAndPath(); |
|
505 } |
|
506 |
|
507 |
|
508 |
|
509 |
|
510 CDirStack* CDirStack::NewL() |
|
511 // |
|
512 // Create new directory stack |
|
513 // |
|
514 { |
|
515 |
|
516 return new(ELeave) CDirStack; |
|
517 } |
|
518 |
|
519 CDirStack::CDirStack() |
|
520 // |
|
521 // Constructor |
|
522 // |
|
523 : iDirStack(KDirStackGranularity) |
|
524 { |
|
525 } |
|
526 |
|
527 CDirStack::~CDirStack() |
|
528 // |
|
529 // Destructor |
|
530 // |
|
531 { |
|
532 |
|
533 |
|
534 iDirStack.ResetAndDestroy(); |
|
535 } |
|
536 |
|
537 TInt CDirStack::IsEmpty() |
|
538 // |
|
539 // Return number of directories stacked |
|
540 // |
|
541 { |
|
542 |
|
543 return (iDirStack.Count()==0); |
|
544 } |
|
545 |
|
546 void CDirStack::ResetL(const TDesC& aStartDir) |
|
547 // |
|
548 // Reset stack to containing only aStartDir |
|
549 // |
|
550 { |
|
551 |
|
552 iDirStack.ResetAndDestroy(); |
|
553 CDir* dir=CDirFactory::NewL(aStartDir); |
|
554 PushL(*dir); |
|
555 } |
|
556 |
|
557 void CDirStack::PushL(CDir& aDirContents) |
|
558 // |
|
559 // Push a list of directories onto the stack |
|
560 // |
|
561 { |
|
562 |
|
563 CleanupStack::PushL(&aDirContents); |
|
564 CDirList* nextLevel=CDirList::NewL(aDirContents); |
|
565 CleanupStack::Pop(); // aDirContents now owned by CDirList |
|
566 |
|
567 TInt r=iDirStack.Append(nextLevel); |
|
568 if (r!=KErrNone) |
|
569 { |
|
570 delete nextLevel; |
|
571 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); |
|
572 User::Leave(r); |
|
573 } |
|
574 } |
|
575 |
|
576 void CDirStack::Pop() |
|
577 // |
|
578 // Pop subdirectory list off the stack |
|
579 // |
|
580 { |
|
581 |
|
582 __ASSERT_DEBUG(iDirStack.Count(),Panic(EDirListError)); |
|
583 TInt tos=iDirStack.Count()-1; |
|
584 delete iDirStack[tos]; |
|
585 iDirStack.Remove(tos); |
|
586 } |
|
587 |
|
588 CDirList* CDirStack::Peek() |
|
589 // |
|
590 // Return current subdirectory |
|
591 // |
|
592 { |
|
593 |
|
594 __ASSERT_DEBUG(iDirStack.Count(),Panic(EDirListError)); |
|
595 return iDirStack[iDirStack.Count()-1]; |
|
596 } |
|
597 |
|
598 CDirList* CDirList::NewL(CDir& aDirList) |
|
599 // |
|
600 // Create a new directory list - takes ownership of aDirList |
|
601 // |
|
602 { |
|
603 |
|
604 CDirList* dirLevel=new(ELeave) CDirList; |
|
605 dirLevel->iDirList=&aDirList; |
|
606 return dirLevel; |
|
607 } |
|
608 |
|
609 CDirList::CDirList() |
|
610 // |
|
611 // Construct directory list |
|
612 // |
|
613 { |
|
614 } |
|
615 |
|
616 CDirList::~CDirList() |
|
617 // |
|
618 // Destroy directory list |
|
619 // |
|
620 { |
|
621 |
|
622 delete iDirList; |
|
623 } |
|
624 |
|
625 const TEntry& CDirList::Next() |
|
626 // |
|
627 // Return next directory in list. |
|
628 // |
|
629 { |
|
630 |
|
631 __ASSERT_DEBUG(iCurrentPos>=0 && iCurrentPos<iDirList->Count(),Panic(EDirListError)); |
|
632 const TEntry& entry=(*iDirList)[iCurrentPos]; |
|
633 iCurrentPos++; |
|
634 return entry; |
|
635 } |
|
636 |
|
637 TBool CDirList::MoreEntries() const |
|
638 // |
|
639 // Return EFalse if the entire list has been read |
|
640 // |
|
641 { |
|
642 |
|
643 __ASSERT_DEBUG(iCurrentPos>=0 && iCurrentPos<=iDirList->Count(),Panic(EDirListError)); |
|
644 return (iCurrentPos!=iDirList->Count()); |
|
645 } |
|
646 |
|
647 CDir* CDirFactory::NewL(const TDesC& anEntryName) |
|
648 // |
|
649 // Create a CDir containing a single entry. Used to initialize the scanner |
|
650 // |
|
651 { |
|
652 |
|
653 CDirFactory* dir=(CDirFactory*)CDir::NewL(); |
|
654 CleanupStack::PushL(dir); |
|
655 TEntry entry; |
|
656 entry.iName=anEntryName; |
|
657 dir->AddL(entry); |
|
658 CleanupStack::Pop(); |
|
659 return dir; |
|
660 } |
|
661 |
|
662 CDir* CDirFactory::NewL() |
|
663 // |
|
664 // Create a CDir with nothing in it |
|
665 // |
|
666 { |
|
667 |
|
668 CDirFactory* dir=(CDirFactory*)CDir::NewL(); |
|
669 return dir; |
|
670 } |
|
671 |
|
672 |
|
673 |
|
674 |
|
675 EXPORT_C TOpenFileScan::TOpenFileScan(RFs& aFs) |
|
676 /** |
|
677 Constructs the object with the specified file server session. |
|
678 |
|
679 @param aFs The file server session. |
|
680 */ |
|
681 : iFs(&aFs), iScanPos(0), iEntryListPos(0) |
|
682 {} |
|
683 |
|
684 |
|
685 |
|
686 |
|
687 EXPORT_C void TOpenFileScan::NextL(CFileList*& aFileList) |
|
688 /** |
|
689 Gets a list of entries for the open files in the file server session. |
|
690 |
|
691 @param aFileList On return, contains a list of entries for all open files |
|
692 in the file server session. |
|
693 */ |
|
694 { |
|
695 |
|
696 |
|
697 aFileList=NULL; |
|
698 if (iScanPos==KErrNotFound) |
|
699 return; |
|
700 TEntryArray* pArray=new(ELeave) TEntryArray; |
|
701 CleanupStack::PushL(pArray); |
|
702 TEntryArray& array=*pArray; |
|
703 FOREVER |
|
704 { |
|
705 TThreadId theId; |
|
706 TInt r = iFs->GetOpenFileList(iScanPos,iEntryListPos,theId,array); |
|
707 if (r != KErrNone) |
|
708 { |
|
709 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); |
|
710 User::Leave(r); |
|
711 } |
|
712 TInt count=array.Count(); |
|
713 if (count==0) |
|
714 { |
|
715 if (aFileList==NULL) |
|
716 iScanPos=KErrNotFound; |
|
717 else |
|
718 CleanupStack::Pop(); // aFileList |
|
719 iEntryListPos=0; |
|
720 CleanupStack::PopAndDestroy(); // pArray |
|
721 return; |
|
722 } |
|
723 iThreadId = theId; |
|
724 if (aFileList==NULL) |
|
725 { |
|
726 aFileList=CFileList::NewL(); |
|
727 CleanupStack::PushL(aFileList); |
|
728 } |
|
729 TInt i=0; |
|
730 while (i<count) |
|
731 aFileList->AddL(array[i++]); |
|
732 } |
|
733 } |
|
734 |
|
735 |
|
736 |
|
737 |
|
738 EXPORT_C TThreadId TOpenFileScan::ThreadId() const |
|
739 /** |
|
740 Gets the ID of the thread that opened the files retrieved by NextL(). |
|
741 |
|
742 @return The ID of the thread that opened the files in the file list. |
|
743 */ |
|
744 { |
|
745 |
|
746 return(iThreadId); |
|
747 } |