os/kernelhwsrv/userlibandfileserver/fileserver/sfsrv/cl_scan.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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 	}