userlibandfileserver/fileserver/sfsrv/cl_scan.cpp
changeset 0 a41df078684a
child 41 0ffb4e86fcc9
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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 	}