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 |
}
|