sl@0: // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "cl_std.h" sl@0: #include "cl_scan.h" sl@0: sl@0: const TInt KDirStackGranularity=8; sl@0: sl@0: /** Replace long names in path and filename with their sohrter version (if exists). Optionally appends sl@0: filename to path name creating fully qualified file name. sl@0: @param aFs (connected) File system session sl@0: @param aCurrentPath on input contains current full path name, sl@0: upon return contains the shortest version (using either shor or long names) of the same path sl@0: @param aItem on input contains item with long name in the current path, sl@0: upon return contains shorter name of either long or short name sl@0: @param aAppend if ETrue aItem will be appended to aCurrentPath before successful return sl@0: @return KErrNone if successful, otherwise one of the other system-wide error codes. sl@0: */ sl@0: TInt ShrinkNames(RFs& aFs, TFileName& aCurrentPath, TFileName& aItem, TBool aAppend) sl@0: { sl@0: TInt ret = KErrNone; sl@0: TBuf<8+1+3> shortname; sl@0: TFileName* current = NULL; sl@0: TRAPD(r,current = new (ELeave) TFileName); sl@0: if (r) sl@0: return r; sl@0: sl@0: TInt pos = 0; sl@0: TInt lastslash = KErrNotFound; sl@0: TInt lastnewslash = KErrNotFound; sl@0: while(ret == KErrNone && pos < aCurrentPath.Length()) sl@0: { sl@0: if(aCurrentPath[pos] == KPathDelimiter) sl@0: { sl@0: if(lastslash != KErrNotFound) sl@0: { sl@0: ret = aFs.GetShortName(*current, shortname); sl@0: if(ret == KErrNone && pos-lastslash > shortname.Length()) sl@0: { sl@0: current->SetLength(lastnewslash); sl@0: current->Append(shortname); sl@0: } sl@0: } sl@0: lastslash = pos+1; sl@0: lastnewslash = current->Length()+1; sl@0: } sl@0: current->Append(aCurrentPath[pos++]); sl@0: } sl@0: if(ret == KErrNone && current->Length() + aItem.Length() <= KMaxFileName) sl@0: { sl@0: aCurrentPath = *current; sl@0: TInt lenBefore = aCurrentPath.Length(); sl@0: aCurrentPath.Append(aItem); sl@0: ret = aFs.GetShortName(aCurrentPath, shortname); sl@0: aCurrentPath.SetLength(lenBefore); sl@0: sl@0: if(ret == KErrNone && aItem.Length() > shortname.Length()) sl@0: { sl@0: aItem = shortname; sl@0: } sl@0: } sl@0: if(aAppend && ret == KErrNone && aCurrentPath.Length() + aItem.Length() <= KMaxFileName) sl@0: { sl@0: aCurrentPath.Append(aItem); sl@0: } sl@0: delete current; sl@0: return ret; sl@0: } sl@0: sl@0: LOCAL_C TPtrC LeafDir(const TDesC& aPath) sl@0: // sl@0: // Returns the leaf directory of a path sl@0: // sl@0: { sl@0: sl@0: TInt end=aPath.LocateReverse('\\'); sl@0: __ASSERT_DEBUG(end!=KErrNotFound,Panic(EDirListError)); sl@0: TPtrC ret(aPath.Ptr(),end); sl@0: TInt start=ret.LocateReverse('\\'); sl@0: if (start==KErrNotFound) sl@0: start=end-1; sl@0: return ret.Right(end-start-1); sl@0: } sl@0: sl@0: CDirScan::CDirScan(RFs& aFs) sl@0: // sl@0: // Constructor sl@0: // sl@0: : iFs(&aFs) sl@0: { sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C CDirScan* CDirScan::NewLC(RFs& aFs) sl@0: /** sl@0: Constructs and allocates memory for a new CDirScan object, putting a pointer sl@0: to the object onto the cleanup stack. sl@0: sl@0: @param aFs The file server session. sl@0: sl@0: @return A pointer to the new directory scan object. sl@0: */ sl@0: { sl@0: TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanNewLC, MODULEUID, aFs.Handle()); sl@0: sl@0: CDirScan* scan=new(ELeave) CDirScan(aFs); sl@0: CleanupStack::PushL(scan); sl@0: scan->iStack=CDirStack::NewL(); sl@0: sl@0: TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanNewLCReturn, MODULEUID, scan); sl@0: return scan; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C CDirScan* CDirScan::NewL(RFs& aFs) sl@0: /** sl@0: Constructs and allocates memory for a new CDirScan object. sl@0: sl@0: @param aFs The file server session. sl@0: sl@0: @return A pointer to the new directory scan object. sl@0: */ sl@0: { sl@0: TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanNewL, MODULEUID, aFs.Handle()); sl@0: sl@0: CDirScan* scan=CDirScan::NewLC(aFs); sl@0: CleanupStack::Pop(); sl@0: sl@0: TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanNewLReturn, MODULEUID, scan); sl@0: return scan; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C CDirScan::~CDirScan() sl@0: /** sl@0: Desctructor. sl@0: sl@0: Frees all resources owned by the object, prior to its destruction. sl@0: */ sl@0: { sl@0: TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanDestructor, MODULEUID, this); sl@0: sl@0: delete iStack; sl@0: sl@0: TRACE0(UTF::EBorder, UTraceModuleEfsrv::ECDirScanDestructorReturn, MODULEUID); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CDirScan::SetScanDataL(const TDesC& aMatchName,TUint anEntryAttMask,TUint anEntrySortKey,TScanDirection aScanDir) sl@0: /** sl@0: Initialises the scan. sl@0: sl@0: This involves specifying: sl@0: sl@0: 1. the directory at the top of the structure to be scanned sl@0: sl@0: 2. a filter for the entry types of interest sl@0: sl@0: 3. the order in which the entries in each directory in the structure are to be sorted sl@0: sl@0: 4. the scan direction. sl@0: sl@0: Whether the scan direction is upwards or downwards, the directories that are sl@0: scanned are those in the part of the hierarchy below the directory sl@0: specified in aMatchName. By default, the scan direction is downwards. sl@0: If the scan direction is set to CDirScan::EScanUpTree, then all branches of sl@0: the tree are explored starting at the lowest level directory in sl@0: the tree below aMatchName, and ending at aMatchName. sl@0: This option is provided for deleting a directory structure. sl@0: sl@0: @param aMatchName The top level directory for the scan. Any path components sl@0: that are not specified here are taken from the session path. sl@0: Note that the trailing backslash is required to specify the directory. sl@0: I.e. path x:\\dir1\\dir2\\ means that the scan will start from dir2, while sl@0: path x:\\dir1\\dir2 assumes scan starting from x:\\dir1\\ sl@0: sl@0: @param anEntryAttMask A bit mask that filters the entry types which should be returned by sl@0: NextL(). The mask works as follows: sl@0: To match files only, specify KEntryAttNormal. sl@0: To match both files and directories, sl@0: specify KEntryAttDir. sl@0: To match directories only, sl@0: specify KEntryAttDir|KEntryAttMatchExclusive. sl@0: To match files with a specific attribute, sl@0: then OR the attribute involved with sl@0: KEntryAttMatchExclusive. sl@0: For example, to match read-only files, sl@0: specify KEntryAttReadOnly|KEntryAttMatchExclusive. sl@0: For more information, sl@0: see KEntryAttNormal or sl@0: the other file/directory attributes. sl@0: @param anEntrySortKey The order in which the directories are scanned by sl@0: NextL(). This flag is defined in TEntryKey. sl@0: @param aScanDir The direction of the scan. The default is downwards. sl@0: */ sl@0: { sl@0: TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECDirScanSetScanDataL, MODULEUID, (TUint) sl@0: this, aMatchName, anEntryAttMask, anEntrySortKey, (TUint) aScanDir); sl@0: sl@0: TInt r = Fs().Parse(aMatchName,iFullPath); sl@0: if (r != KErrNone) sl@0: { sl@0: TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanSetScanDataLReturn, MODULEUID, r); sl@0: User::Leave(r); sl@0: } sl@0: sl@0: iScanning = ETrue; sl@0: iEntryAttMask=anEntryAttMask; sl@0: iEntrySortMask=anEntrySortKey; sl@0: iStack->ResetL(LeafDir(iFullPath.FullName())); sl@0: iAbbreviatedPathPos=iFullPath.DriveAndPath().Length()-1; sl@0: iAbbreviatedPath.Set(_L("\\")); sl@0: iScanDir=aScanDir; sl@0: if (aScanDir==EScanDownTree) sl@0: iFullPath.PopDir(); sl@0: sl@0: TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanSetScanDataLReturn, MODULEUID, KErrNone); sl@0: } sl@0: sl@0: void CDirScan::UpdateAbbreviatedPath() sl@0: // sl@0: // Set the abbreviated path based on the full path sl@0: // sl@0: { sl@0: sl@0: TInt length=iFullPath.DriveAndPath().Length(); sl@0: TPtrC fullName=iFullPath.FullName(); sl@0: if (length>iAbbreviatedPathPos) sl@0: iAbbreviatedPath.Set(&fullName[0]+iAbbreviatedPathPos,length-iAbbreviatedPathPos); sl@0: else sl@0: iAbbreviatedPath.Set(_L("\\")); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void CDirScan::NextL(CDir*& aDirEntries) sl@0: /** sl@0: Scans the next directory entry in the structure. sl@0: sl@0: The order in which the structure is scanned is determined by the scan sl@0: direction and the entry sort mask. These values are specified when setting up sl@0: the scan. The type of entries retrieved by this function is determined by the sl@0: entry attribute mask. This is also specified when setting up the scan. sl@0: sl@0: Notes: sl@0: sl@0: 1. The function first sets aDirEntries to NULL, and then allocates memory for sl@0: it before appending entries to it. Therefore, aDirEntries should have no sl@0: memory allocated to it before this function is called, otherwise this sl@0: memory will become orphaned. sl@0: sl@0: 2. The caller of this function is responsible for deleting aDirEntries after sl@0: the function has returned. sl@0: sl@0: @param aDirEntries On return, a pointer to an array containing filtered entries sl@0: from the next directory in the structure. NULL if there are sl@0: no more directories in the structure. sl@0: */ sl@0: { sl@0: TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanNextL, MODULEUID, this); sl@0: sl@0: if (iScanDir==EScanUpTree) sl@0: ScanUpTreeL(aDirEntries); sl@0: else sl@0: ScanDownTreeL(aDirEntries); sl@0: sl@0: TRACE2(UTF::EBorder, UTraceModuleEfsrv::ECDirScanNextLReturn, MODULEUID, sl@0: KErrNone, aDirEntries ? (*aDirEntries).Count() : 0); sl@0: } sl@0: sl@0: void CDirScan::ScanUpTreeL(CDir*& aDirEntries) sl@0: // sl@0: // Get the next directory starting from the bottom of the tree sl@0: // eg: for deleting a directory structure sl@0: // sl@0: { sl@0: TInt r; sl@0: iFullPath.PopDir(); sl@0: CDirList* list=iStack->Peek(); sl@0: if (!list->MoreEntries()) sl@0: { sl@0: iStack->Pop(); sl@0: if (iStack->IsEmpty()) sl@0: { sl@0: aDirEntries=NULL; sl@0: return; sl@0: } sl@0: UpdateAbbreviatedPath(); sl@0: GetDirEntriesL(aDirEntries); sl@0: return; sl@0: } sl@0: sl@0: TFileName* next = new (ELeave) TFileName; sl@0: CleanupStack::PushL(next); sl@0: TFileName* current = new (ELeave) TFileName; sl@0: CleanupStack::PushL(current); sl@0: sl@0: FOREVER sl@0: { sl@0: TPtrC dirName=list->Next().iName; sl@0: r = iFullPath.AddDir(dirName); sl@0: if (r==KErrGeneral) // adding dirName would make iFullPath > 256 characters sl@0: { sl@0: current->Copy(iFullPath.DriveAndPath()); sl@0: next->Copy(dirName); sl@0: sl@0: r = ShrinkNames(Fs(), *current, *next, EFalse); sl@0: if(r == KErrNone) sl@0: { sl@0: r = iFullPath.Set(*current, NULL, NULL); sl@0: if(r == KErrNone) sl@0: { sl@0: r = iFullPath.AddDir(*next); sl@0: } sl@0: } sl@0: } sl@0: if (r != KErrNone) sl@0: { sl@0: TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); sl@0: User::LeaveIfError(r); sl@0: } sl@0: sl@0: CDir* dirList; sl@0: // Start by searching for directories only from top to bottom sl@0: r = Fs().GetDir(iFullPath.DriveAndPath(), sl@0: KEntryAttDir|KEntryAttMatchExclusive|(iEntryAttMask&KEntryAttMatchMask), sl@0: iEntrySortMask, sl@0: dirList); sl@0: if (r == KErrPermissionDenied && !iScanning) sl@0: { sl@0: UpdateAbbreviatedPath(); sl@0: aDirEntries = CDirFactory::NewL(); sl@0: } sl@0: else if (r != KErrNone) sl@0: { sl@0: iScanning = EFalse; sl@0: TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); sl@0: User::Leave(r); sl@0: } sl@0: sl@0: iScanning= EFalse; sl@0: sl@0: // Permission denied case. No entry sl@0: if(!dirList) sl@0: break; sl@0: sl@0: if (dirList->Count()==0)// No more directory entries - bottom of tree reached sl@0: { sl@0: delete dirList; sl@0: break; sl@0: } sl@0: iStack->PushL(*dirList); sl@0: list=iStack->Peek(); sl@0: } //END OF FOREVER sl@0: sl@0: CleanupStack::PopAndDestroy(2); // current and next pointers sl@0: sl@0: UpdateAbbreviatedPath(); sl@0: // Now get all valid entries for the lowest level directory encountered sl@0: sl@0: if(r!=KErrPermissionDenied ) sl@0: { sl@0: GetDirEntriesL(aDirEntries); sl@0: } sl@0: } sl@0: sl@0: void CDirScan::GetDirEntriesL(CDir*& aDirEntries) sl@0: // sl@0: // Call GetDir. sl@0: // sl@0: { sl@0: TInt r = Fs().GetDir(iFullPath.FullName(),iEntryAttMask,iEntrySortMask,aDirEntries); sl@0: if (r != KErrNone) sl@0: { sl@0: TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); sl@0: User::Leave(r); sl@0: } sl@0: } sl@0: sl@0: void CDirScan::ScanDownTreeL(CDir*& aDirEntries) sl@0: // sl@0: // Get the next directory starting from the top of the tree sl@0: // eg: for copying a directory structure sl@0: // sl@0: { sl@0: CDir* dirEntries = NULL; sl@0: TInt r; sl@0: aDirEntries=NULL; sl@0: CDirList* list=iStack->Peek(); sl@0: while (!list->MoreEntries()) sl@0: { sl@0: iStack->Pop(); sl@0: if (iStack->IsEmpty()) sl@0: { sl@0: aDirEntries=NULL; sl@0: return; sl@0: } sl@0: iFullPath.PopDir(); sl@0: UpdateAbbreviatedPath(); sl@0: list=iStack->Peek(); sl@0: } sl@0: sl@0: TPtrC dirName=list->Next().iName; sl@0: r=iFullPath.AddDir(dirName); sl@0: if (r==KErrGeneral) // Adding dirName makes iFullPath>256 characters sl@0: { sl@0: TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, KErrTooBig); sl@0: User::Leave(KErrTooBig); sl@0: } sl@0: sl@0: // Get all valid entries in this directory sl@0: sl@0: // coverity[alloc_arg] sl@0: TRAP(r, GetDirEntriesL(dirEntries)); sl@0: sl@0: if (r == KErrNone) sl@0: { sl@0: iScanning = EFalse; sl@0: CleanupStack::PushL(dirEntries); sl@0: // Get all directories within this directory - the next level down in the tree sl@0: CDir* dirList; sl@0: sl@0: // coverity[alloc_fn] sl@0: r = Fs().GetDir(iFullPath.DriveAndPath(), sl@0: KEntryAttDir|KEntryAttMatchExclusive|(iEntryAttMask&KEntryAttMatchMask), sl@0: iEntrySortMask,dirList); sl@0: if (r != KErrNone) sl@0: { sl@0: TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); sl@0: User::Leave(r); sl@0: } sl@0: iStack->PushL(*dirList); sl@0: CleanupStack::Pop(); // dirEntries sl@0: UpdateAbbreviatedPath(); sl@0: aDirEntries=dirEntries; sl@0: } sl@0: else if (r == KErrPermissionDenied && !iScanning) sl@0: { sl@0: CDir* dirList = CDirFactory::NewL(); sl@0: iStack->PushL(*dirList); sl@0: aDirEntries = CDirFactory::NewL(); sl@0: } sl@0: else sl@0: { sl@0: iScanning = EFalse; sl@0: TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); sl@0: User::Leave(r); sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C TPtrC CDirScan::AbbreviatedPath() sl@0: /** sl@0: Gets the abbreviated path of the entry currently being scanned. sl@0: sl@0: The abbreviated path is the path relative to the top level directory sl@0: in the scan. sl@0: sl@0: @return A non modifiable pointer descriptor for the abbreviated path of sl@0: the entry currently being scanned. sl@0: */ sl@0: { sl@0: sl@0: return iAbbreviatedPath; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C TPtrC CDirScan::FullPath() sl@0: /** sl@0: Gets the full path of the entry currently being scanned. sl@0: sl@0: The full path includes the drive letter. sl@0: sl@0: @return A non modifiable pointer descriptor for the full path of the entry sl@0: currently being scanned. sl@0: */ sl@0: { sl@0: sl@0: return iFullPath.DriveAndPath(); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: CDirStack* CDirStack::NewL() sl@0: // sl@0: // Create new directory stack sl@0: // sl@0: { sl@0: sl@0: return new(ELeave) CDirStack; sl@0: } sl@0: sl@0: CDirStack::CDirStack() sl@0: // sl@0: // Constructor sl@0: // sl@0: : iDirStack(KDirStackGranularity) sl@0: { sl@0: } sl@0: sl@0: CDirStack::~CDirStack() sl@0: // sl@0: // Destructor sl@0: // sl@0: { sl@0: sl@0: sl@0: iDirStack.ResetAndDestroy(); sl@0: } sl@0: sl@0: TInt CDirStack::IsEmpty() sl@0: // sl@0: // Return number of directories stacked sl@0: // sl@0: { sl@0: sl@0: return (iDirStack.Count()==0); sl@0: } sl@0: sl@0: void CDirStack::ResetL(const TDesC& aStartDir) sl@0: // sl@0: // Reset stack to containing only aStartDir sl@0: // sl@0: { sl@0: sl@0: iDirStack.ResetAndDestroy(); sl@0: CDir* dir=CDirFactory::NewL(aStartDir); sl@0: PushL(*dir); sl@0: } sl@0: sl@0: void CDirStack::PushL(CDir& aDirContents) sl@0: // sl@0: // Push a list of directories onto the stack sl@0: // sl@0: { sl@0: sl@0: CleanupStack::PushL(&aDirContents); sl@0: CDirList* nextLevel=CDirList::NewL(aDirContents); sl@0: CleanupStack::Pop(); // aDirContents now owned by CDirList sl@0: sl@0: TInt r=iDirStack.Append(nextLevel); sl@0: if (r!=KErrNone) sl@0: { sl@0: delete nextLevel; sl@0: TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); sl@0: User::Leave(r); sl@0: } sl@0: } sl@0: sl@0: void CDirStack::Pop() sl@0: // sl@0: // Pop subdirectory list off the stack sl@0: // sl@0: { sl@0: sl@0: __ASSERT_DEBUG(iDirStack.Count(),Panic(EDirListError)); sl@0: TInt tos=iDirStack.Count()-1; sl@0: delete iDirStack[tos]; sl@0: iDirStack.Remove(tos); sl@0: } sl@0: sl@0: CDirList* CDirStack::Peek() sl@0: // sl@0: // Return current subdirectory sl@0: // sl@0: { sl@0: sl@0: __ASSERT_DEBUG(iDirStack.Count(),Panic(EDirListError)); sl@0: return iDirStack[iDirStack.Count()-1]; sl@0: } sl@0: sl@0: CDirList* CDirList::NewL(CDir& aDirList) sl@0: // sl@0: // Create a new directory list - takes ownership of aDirList sl@0: // sl@0: { sl@0: sl@0: CDirList* dirLevel=new(ELeave) CDirList; sl@0: dirLevel->iDirList=&aDirList; sl@0: return dirLevel; sl@0: } sl@0: sl@0: CDirList::CDirList() sl@0: // sl@0: // Construct directory list sl@0: // sl@0: { sl@0: } sl@0: sl@0: CDirList::~CDirList() sl@0: // sl@0: // Destroy directory list sl@0: // sl@0: { sl@0: sl@0: delete iDirList; sl@0: } sl@0: sl@0: const TEntry& CDirList::Next() sl@0: // sl@0: // Return next directory in list. sl@0: // sl@0: { sl@0: sl@0: __ASSERT_DEBUG(iCurrentPos>=0 && iCurrentPosCount(),Panic(EDirListError)); sl@0: const TEntry& entry=(*iDirList)[iCurrentPos]; sl@0: iCurrentPos++; sl@0: return entry; sl@0: } sl@0: sl@0: TBool CDirList::MoreEntries() const sl@0: // sl@0: // Return EFalse if the entire list has been read sl@0: // sl@0: { sl@0: sl@0: __ASSERT_DEBUG(iCurrentPos>=0 && iCurrentPos<=iDirList->Count(),Panic(EDirListError)); sl@0: return (iCurrentPos!=iDirList->Count()); sl@0: } sl@0: sl@0: CDir* CDirFactory::NewL(const TDesC& anEntryName) sl@0: // sl@0: // Create a CDir containing a single entry. Used to initialize the scanner sl@0: // sl@0: { sl@0: sl@0: CDirFactory* dir=(CDirFactory*)CDir::NewL(); sl@0: CleanupStack::PushL(dir); sl@0: TEntry entry; sl@0: entry.iName=anEntryName; sl@0: dir->AddL(entry); sl@0: CleanupStack::Pop(); sl@0: return dir; sl@0: } sl@0: sl@0: CDir* CDirFactory::NewL() sl@0: // sl@0: // Create a CDir with nothing in it sl@0: // sl@0: { sl@0: sl@0: CDirFactory* dir=(CDirFactory*)CDir::NewL(); sl@0: return dir; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C TOpenFileScan::TOpenFileScan(RFs& aFs) sl@0: /** sl@0: Constructs the object with the specified file server session. sl@0: sl@0: @param aFs The file server session. sl@0: */ sl@0: : iFs(&aFs), iScanPos(0), iEntryListPos(0) sl@0: {} sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C void TOpenFileScan::NextL(CFileList*& aFileList) sl@0: /** sl@0: Gets a list of entries for the open files in the file server session. sl@0: sl@0: @param aFileList On return, contains a list of entries for all open files sl@0: in the file server session. sl@0: */ sl@0: { sl@0: sl@0: sl@0: aFileList=NULL; sl@0: if (iScanPos==KErrNotFound) sl@0: return; sl@0: TEntryArray* pArray=new(ELeave) TEntryArray; sl@0: CleanupStack::PushL(pArray); sl@0: TEntryArray& array=*pArray; sl@0: FOREVER sl@0: { sl@0: TThreadId theId; sl@0: TInt r = iFs->GetOpenFileList(iScanPos,iEntryListPos,theId,array); sl@0: if (r != KErrNone) sl@0: { sl@0: TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECDirScanLeave, MODULEUID, r); sl@0: User::Leave(r); sl@0: } sl@0: TInt count=array.Count(); sl@0: if (count==0) sl@0: { sl@0: if (aFileList==NULL) sl@0: iScanPos=KErrNotFound; sl@0: else sl@0: CleanupStack::Pop(); // aFileList sl@0: iEntryListPos=0; sl@0: CleanupStack::PopAndDestroy(); // pArray sl@0: return; sl@0: } sl@0: iThreadId = theId; sl@0: if (aFileList==NULL) sl@0: { sl@0: aFileList=CFileList::NewL(); sl@0: CleanupStack::PushL(aFileList); sl@0: } sl@0: TInt i=0; sl@0: while (iAddL(array[i++]); sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: EXPORT_C TThreadId TOpenFileScan::ThreadId() const sl@0: /** sl@0: Gets the ID of the thread that opened the files retrieved by NextL(). sl@0: sl@0: @return The ID of the thread that opened the files in the file list. sl@0: */ sl@0: { sl@0: sl@0: return(iThreadId); sl@0: }