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