0
|
1 |
// Copyright (c) 1998-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 |
@file
|
|
17 |
@internalTechnology
|
|
18 |
*/
|
|
19 |
|
|
20 |
#include <e32cmn.h>
|
|
21 |
#include <f32ver.h>
|
|
22 |
#include <u32std.h>
|
|
23 |
#include <f32file.h>
|
|
24 |
|
|
25 |
|
|
26 |
|
|
27 |
#include "filesystem_automounter.h"
|
|
28 |
#include "automounter.h"
|
|
29 |
|
|
30 |
|
|
31 |
//-----------------------------------------------------------------------------
|
|
32 |
|
|
33 |
void Fault(TFault aFault)
|
|
34 |
{
|
|
35 |
_LIT(KPanicName, "AutoMounter_fsy");
|
|
36 |
User::Panic(KPanicName, aFault);
|
|
37 |
}
|
|
38 |
|
|
39 |
|
|
40 |
//-----------------------------------------------------------------------------
|
|
41 |
|
|
42 |
/**
|
|
43 |
Factory function, Create a new object of this file system
|
|
44 |
*/
|
|
45 |
extern "C"
|
|
46 |
{
|
|
47 |
EXPORT_C CFileSystem* CreateFileSystem()
|
|
48 |
{
|
|
49 |
return CAutoMounterFileSystem::New();
|
|
50 |
}
|
|
51 |
}
|
|
52 |
|
|
53 |
|
|
54 |
//#######################################################################################################################################
|
|
55 |
//# CAutoMounterFileSystem class implementation
|
|
56 |
//#######################################################################################################################################
|
|
57 |
|
|
58 |
/**
|
|
59 |
Factory method
|
|
60 |
*/
|
|
61 |
CAutoMounterFileSystem* CAutoMounterFileSystem::New()
|
|
62 |
{
|
|
63 |
CAutoMounterFileSystem* pThis = new CAutoMounterFileSystem();
|
|
64 |
return pThis;
|
|
65 |
}
|
|
66 |
|
|
67 |
|
|
68 |
CAutoMounterFileSystem::CAutoMounterFileSystem()
|
|
69 |
{
|
|
70 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::CAutoMounterFileSystem() [0x%x]"), this);
|
|
71 |
|
271
|
72 |
iChildFsForDefFmt = KErrNotFound;
|
0
|
73 |
SetState(EInvalid);
|
|
74 |
}
|
|
75 |
|
|
76 |
CAutoMounterFileSystem::~CAutoMounterFileSystem()
|
|
77 |
{
|
|
78 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::~CAutoMounterFileSystem() [0x%x]"), this);
|
|
79 |
}
|
|
80 |
|
|
81 |
//-----------------------------------------------------------------------------
|
|
82 |
|
|
83 |
/**
|
|
84 |
Install iand initialise file system.
|
|
85 |
*/
|
|
86 |
TInt CAutoMounterFileSystem::Install()
|
|
87 |
{
|
|
88 |
|
|
89 |
SetState(ENotInitialised);
|
|
90 |
|
|
91 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::Install() [0x%x]"), this);
|
|
92 |
|
|
93 |
iVersion=TVersion(KF32MajorVersionNumber,KF32MinorVersionNumber,KF32BuildVersionNumber);
|
|
94 |
|
|
95 |
InitialiseFileSystem();
|
|
96 |
|
|
97 |
return SetName(&KFileSystemName_AutoMounter);
|
|
98 |
}
|
|
99 |
|
|
100 |
|
|
101 |
//-----------------------------------------------------------------------------
|
|
102 |
/**
|
|
103 |
Create a new mount control block.
|
|
104 |
This method migh be called by the file server in some unusual cases, when the actual mount is needed only temporarily to get access to the
|
|
105 |
corresponding media driver. E.g. TDrive::ForceRemountDrive()
|
|
106 |
Produce the _default_ file system mount
|
|
107 |
*/
|
|
108 |
CMountCB* CAutoMounterFileSystem::NewMountL() const
|
|
109 |
{
|
|
110 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::NewMountL() [0x%x]"), this);
|
|
111 |
ASSERT(State() == EInitialised);
|
|
112 |
|
|
113 |
__PRINT1(_L("#<<- producing the _default_ filesystem:%S"), &iFSNames[KDefaultFSNo]);
|
|
114 |
|
|
115 |
CFileSystem* pFS = GetChildFileSystem(KDefaultFSNo);
|
|
116 |
ASSERT(pFS);
|
|
117 |
|
|
118 |
return pFS->NewMountL();
|
|
119 |
}
|
|
120 |
|
|
121 |
//-----------------------------------------------------------------------------
|
|
122 |
/**
|
|
123 |
Create a new file.
|
|
124 |
*/
|
|
125 |
CFileCB* CAutoMounterFileSystem::NewFileL() const
|
|
126 |
{
|
|
127 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::NewFileL() [0x%x]"), this);
|
|
128 |
Fault(EMustNotBeCalled);
|
|
129 |
return NULL;
|
|
130 |
}
|
|
131 |
|
|
132 |
//-----------------------------------------------------------------------------
|
|
133 |
/**
|
|
134 |
Create a new directory object
|
|
135 |
*/
|
|
136 |
CDirCB* CAutoMounterFileSystem::NewDirL() const
|
|
137 |
{
|
|
138 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::NewDirL() [0x%x]"), this);
|
|
139 |
Fault(EMustNotBeCalled);
|
|
140 |
return NULL;
|
|
141 |
}
|
|
142 |
|
|
143 |
//-----------------------------------------------------------------------------
|
|
144 |
/**
|
|
145 |
Create a new media formatter
|
|
146 |
*/
|
|
147 |
CFormatCB* CAutoMounterFileSystem::NewFormatL() const
|
|
148 |
{
|
|
149 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::NewFormatL() [0x%x]"), this);
|
|
150 |
Fault(EMustNotBeCalled);
|
|
151 |
return NULL;
|
|
152 |
}
|
|
153 |
|
|
154 |
|
|
155 |
//-----------------------------------------------------------------------------
|
|
156 |
|
|
157 |
#ifdef _DEBUG
|
|
158 |
/**
|
|
159 |
Called by File Server before deleting File System object.
|
|
160 |
*/
|
|
161 |
TInt CAutoMounterFileSystem::Remove()
|
|
162 |
{
|
|
163 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::Remove() [0x%x]"), this);
|
|
164 |
return CFileSystem::Remove();
|
|
165 |
}
|
|
166 |
|
|
167 |
//-----------------------------------------------------------------------------
|
|
168 |
|
|
169 |
/**
|
|
170 |
*/
|
|
171 |
TBool CAutoMounterFileSystem::QueryVersionSupported(const TVersion& aVer) const
|
|
172 |
{
|
|
173 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::QueryVersionSupported() [0x%x]"), this);
|
|
174 |
return CFileSystem::QueryVersionSupported(aVer);
|
|
175 |
}
|
|
176 |
|
|
177 |
#endif
|
|
178 |
|
|
179 |
//-----------------------------------------------------------------------------
|
|
180 |
|
|
181 |
/**
|
|
182 |
Find out if drive extensions are supported. In order to have consistent behaviour, _all_ child
|
|
183 |
file systems shall behave the same way.
|
|
184 |
|
|
185 |
@return ETrue if drive extensions are supported.
|
|
186 |
*/
|
|
187 |
TBool CAutoMounterFileSystem::IsExtensionSupported() const
|
|
188 |
{
|
|
189 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::IsExtensionSupported() [0x%x]"), this);
|
|
190 |
|
271
|
191 |
ASSERT(State() == EInitialised && ChildFsNum() >= KMinChildFsNum);
|
0
|
192 |
|
|
193 |
|
|
194 |
//-- in debug mode check file systems compatibility: ALL childs must support this feature
|
271
|
195 |
for(TUint i=0; i<ChildFsNum(); ++i)
|
0
|
196 |
{
|
|
197 |
if( !(GetChildFileSystem(i)->IsExtensionSupported()))
|
|
198 |
{
|
|
199 |
DBG_STATEMENT(Fault(EIncompatibleFileSystems));
|
|
200 |
__PRINT(_L("#<<- ::IsExtensionSupported(): Incompatible file sytems!"));
|
|
201 |
return EFalse;
|
|
202 |
}
|
|
203 |
}
|
|
204 |
|
|
205 |
|
|
206 |
return ETrue;
|
|
207 |
}
|
|
208 |
|
|
209 |
//-----------------------------------------------------------------------------
|
|
210 |
|
|
211 |
/**
|
|
212 |
Return the initial default path.
|
|
213 |
*/
|
|
214 |
TInt CAutoMounterFileSystem::DefaultPath(TDes& aPath) const
|
|
215 |
{
|
|
216 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::DefaultPath() [0x%x]"), this);
|
|
217 |
|
|
218 |
aPath=_L("?:\\");
|
|
219 |
aPath[0] = (TUint8) RFs::GetSystemDriveChar();
|
|
220 |
return KErrNone;
|
|
221 |
}
|
|
222 |
|
|
223 |
|
|
224 |
//-----------------------------------------------------------------------------
|
|
225 |
|
|
226 |
/**
|
|
227 |
Additional interfaces support.
|
|
228 |
*/
|
|
229 |
TInt CAutoMounterFileSystem::GetInterface(TInt aInterfaceId, TAny*& aInterface, TAny* aInput)
|
|
230 |
{
|
|
231 |
|
|
232 |
__PRINT2(_L("#<<- CAutoMounterFileSystem::GetInterface(id:%d) [0x%x]"), aInterfaceId, this);
|
|
233 |
|
|
234 |
switch(aInterfaceId)
|
|
235 |
{
|
|
236 |
//-- It is this filesystem private interface.
|
|
237 |
case EExtendedFunctionality:
|
|
238 |
aInterface = (CFileSystem::MFileSystemExtInterface*)this;
|
|
239 |
return KErrNone;
|
|
240 |
|
|
241 |
//-- a special case for child filesystems.
|
|
242 |
//-- ALL of them must respond to this interface query exactly the same way. I.e. It is impossible
|
|
243 |
//-- to have some of the child FS supporting it and some not.
|
|
244 |
case EProxyDriveSupport:
|
|
245 |
return DoProcessProxyDriveSupport();
|
|
246 |
|
|
247 |
|
|
248 |
default:
|
|
249 |
//-- This is the request to other (child file system) from the file server
|
|
250 |
//-- Actually, this part must never be called. File Server shall query the file system interfaces _after_ mounting the concrete FS
|
|
251 |
//-- calling TDrive::iCurrentMount->FileSystem().GetInterface()
|
|
252 |
ASSERT(0);
|
|
253 |
return CFileSystem::GetInterface(aInterfaceId, aInterface, aInput);
|
|
254 |
|
|
255 |
}
|
|
256 |
}
|
|
257 |
|
|
258 |
|
|
259 |
//-----------------------------------------------------------------------------
|
|
260 |
|
|
261 |
/**
|
271
|
262 |
Find out if _all_ child file systems support the proxy drive. All child file systems shall behave exactly the same way.
|
|
263 |
This is mostly for the USB host drives support. All child file systems should either support this feature or do not.
|
|
264 |
Otherwise, it may lead to very obscured cases of susystem misbehaviour.
|
|
265 |
|
0
|
266 |
@return KErrNone if all child file systems support proxy drives, or KErrNotSupported if all of them do not.
|
|
267 |
*/
|
|
268 |
TInt CAutoMounterFileSystem::DoProcessProxyDriveSupport()
|
|
269 |
{
|
|
270 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::DoProcessProxyDriveSupport[0x%x]"), this);
|
|
271 |
ASSERT(State() == EInitialised);
|
|
272 |
|
271
|
273 |
const TUint cnt = ChildFsNum();
|
|
274 |
ASSERT(cnt >= KMinChildFsNum);
|
0
|
275 |
|
|
276 |
//-- query the default filesystem #0
|
|
277 |
const TBool bRes = GetChildFileSystem(KDefaultFSNo)->IsProxyDriveSupported();
|
|
278 |
|
|
279 |
//-- query the rest of child filesystems
|
|
280 |
for(TUint i=1; i<cnt; ++i)
|
|
281 |
{
|
|
282 |
const TBool b = GetChildFileSystem(i)->IsProxyDriveSupported();
|
|
283 |
|
|
284 |
if(BoolXOR(b, bRes))
|
|
285 |
Fault(EIncompatibleFileSystems);
|
|
286 |
}
|
|
287 |
|
|
288 |
|
|
289 |
return bRes ? KErrNone : KErrNotSupported;
|
|
290 |
}
|
|
291 |
|
|
292 |
//-----------------------------------------------------------------------------
|
|
293 |
/**
|
|
294 |
Get the child file system name by its index (enumerator).
|
|
295 |
|
|
296 |
@param aFsNumber index of the child FS 0...KMaxTInt
|
|
297 |
@param aFsName on success the child file system name will be placed into this buffer
|
|
298 |
|
|
299 |
@return KErrNone if there is a child FS name with index 'aFsNumber' (child FS 'aFsNumber' is supported by automounter)
|
|
300 |
KErrNotFound if child FS 'aFsNumber' is not supported
|
|
301 |
*/
|
|
302 |
TInt CAutoMounterFileSystem::GetSupportedFileSystemName(TInt aFsNumber, TDes& aFsName) const
|
|
303 |
{
|
|
304 |
__PRINT2(_L("#<<- CAutoMounterFileSystem::GetSupportedFileSystemName[0x%x](%d)"), this, aFsNumber);
|
|
305 |
|
|
306 |
if(aFsNumber == RFs::KRootFileSystem)
|
|
307 |
{//-- this is a name query for "root filesystem" or automounter
|
|
308 |
aFsName = Name(); //-- ourselves
|
|
309 |
return KErrNone;
|
|
310 |
}
|
|
311 |
|
|
312 |
//-- this is a query for one of the child filesystems
|
271
|
313 |
if((TUint)aFsNumber < ChildFsNum())
|
0
|
314 |
{
|
|
315 |
aFsName = iFSNames[aFsNumber];
|
|
316 |
return KErrNone;
|
|
317 |
}
|
|
318 |
|
|
319 |
|
|
320 |
return KErrNotFound;
|
|
321 |
}
|
|
322 |
|
|
323 |
|
|
324 |
//-----------------------------------------------------------------------------
|
|
325 |
/**
|
|
326 |
This is the only factory method that can be called by file server for this file system.
|
|
327 |
In this method the automounter sequentially tries to mount every child and on success produces the corresponding CMountCB object.
|
|
328 |
|
|
329 |
@param apDrive pointer to the TDrive, child FS will need this to access media.
|
271
|
330 |
@param apFileSystem on return will contain the pointer to the CFileSystem that has produced the proper CMountCB if
|
|
331 |
one of the child file system has recognised the volume layout.
|
0
|
332 |
@param aForceMount if ETrue the appropriate child FS (designated by aFsNameHash) will be forcedly mounted on the volume. for volume formatting purposes.
|
|
333 |
@param aFsNameHash if !=0 specifies the file system name, see TVolFormatParam::CalcFSNameHash(). 0 means "file system name is not specified"
|
|
334 |
|
|
335 |
@return pointer to the constructed CMountCB by one of the child file systems (and pointer to this child FS in apFileSystem)
|
|
336 |
NULL if it was impossible to produce proper CMountCB object.
|
|
337 |
|
|
338 |
*/
|
|
339 |
CMountCB* CAutoMounterFileSystem::NewMountExL(TDrive* apDrive, CFileSystem** apFileSystem, TBool aForceMount, TUint32 aFsNameHash)
|
|
340 |
{
|
|
341 |
__PRINT4(_L("#<<- CAutoMounterFileSystem::NewMountExL[0x%x] drv:%d, ForceMount:%d, FSNameHash:0x%x"), this, apDrive->DriveNumber(), aForceMount, aFsNameHash);
|
|
342 |
|
|
343 |
ASSERT(State() == EInitialised && apDrive);
|
|
344 |
|
|
345 |
//-- This method is usually called from the appropriate drive thread; this file system is intended to be bound to
|
|
346 |
//-- removable drives. Having removable drive runnind in the main file server thread means that something is terribly wrongly configured.
|
|
347 |
if(apDrive->IsSynchronous())
|
|
348 |
Fault(EWrongDriveAttributes);
|
|
349 |
|
271
|
350 |
if(ChildFsNum() < KMinChildFsNum)
|
0
|
351 |
Fault(EWrongConfiguration);
|
|
352 |
|
|
353 |
|
|
354 |
//-- if aForceMount is true, this means that the TDrive tries mount the filesystem by force for formatting because normal mounting has failed before.
|
|
355 |
//-- in our case it means that the file system on the volume hadn't been recognised by any child FS.
|
|
356 |
//-- aFsNameHash shall designate the file system to be forcedly mounted. Depending on this the appropriat CMounCB object will be produced.
|
271
|
357 |
//-- if aFsNameHash is 0, i.e. not provided, this method will fail with KErrNotFound if it can't to select appropriate child FS to be used.
|
0
|
358 |
if(aForceMount)
|
|
359 |
{
|
271
|
360 |
CFileSystem *pFS = NULL; //-- the FS selected to produce CMountCB for media formatting
|
|
361 |
|
0
|
362 |
if(aFsNameHash == 0)
|
|
363 |
{//-- the file system to mount forcedly is not specified
|
271
|
364 |
//-- 1. check if we have only 1 child FS supported. Quite a weird case, but an easy choice.
|
|
365 |
if(ChildFsNum() == 1)
|
|
366 |
{//-- use the single known child FS
|
|
367 |
__PRINT1(_L("#<<- only 1 child FS available for formatting: %S"), &iFSNames[KDefaultFSNo]);
|
|
368 |
pFS = GetChildFileSystem(KDefaultFSNo);
|
|
369 |
}
|
|
370 |
else if(iChildFsForDefFmt >= 0)
|
|
371 |
{//-- the parameter "child fs for default formatting" is defined. try using this
|
|
372 |
__PRINT1(_L("#<<- using the default child FS for formatting: %S"), &iFSNames[iChildFsForDefFmt]);
|
|
373 |
pFS = GetChildFileSystem(iChildFsForDefFmt);
|
|
374 |
}
|
|
375 |
else
|
|
376 |
{
|
0
|
377 |
__PRINT(_L("#<<- Unable to select appropriate child FS for formatting!"));
|
|
378 |
User::Leave(KErrNotFound);
|
|
379 |
}
|
271
|
380 |
}
|
|
381 |
else //if(aFsNameHash == 0)
|
|
382 |
{//-- try to find appropriate child FS by its name hash provided by the upper level
|
|
383 |
pFS = GetChildFileSysteByNameHash(aFsNameHash);
|
0
|
384 |
if(!pFS)
|
|
385 |
{
|
|
386 |
__PRINT(_L("#<<- no child FS found by its name hash!"));
|
|
387 |
ASSERT(0);
|
|
388 |
User::Leave(KErrNotFound);
|
|
389 |
}
|
271
|
390 |
}
|
0
|
391 |
|
271
|
392 |
//-- ask the selected FS to produce us a mount for media formating
|
|
393 |
ASSERT(pFS);
|
0
|
394 |
CMountCB* pMount = pFS->NewMountL();
|
|
395 |
ASSERT(pMount);
|
|
396 |
|
|
397 |
*apFileSystem = pFS;
|
|
398 |
return pMount;
|
|
399 |
}//if(aForceMount)
|
|
400 |
|
|
401 |
|
|
402 |
|
|
403 |
//-- try instantiate a new CMountCB depending on the file system on the media
|
271
|
404 |
ASSERT(!aForceMount);
|
0
|
405 |
|
|
406 |
CMountCB* pMatchedMount;
|
|
407 |
TInt nRes = TryMountFilesystem(apDrive, &pMatchedMount, apFileSystem);
|
|
408 |
|
|
409 |
if(nRes == KErrNone)
|
|
410 |
{
|
|
411 |
ASSERT(pMatchedMount);
|
|
412 |
return pMatchedMount;
|
|
413 |
}
|
|
414 |
|
|
415 |
|
|
416 |
User::Leave(nRes);
|
|
417 |
return NULL;
|
|
418 |
}
|
|
419 |
|
271
|
420 |
|
0
|
421 |
//-----------------------------------------------------------------------------
|
|
422 |
/**
|
271
|
423 |
Parse the string with child file system names. These names come from config, which can be either
|
|
424 |
estart.txt or a text debug property that can override it.
|
0
|
425 |
|
271
|
426 |
@param aList string descriptor with contents like "fat,exfat" i.e. it is comma separated file system names
|
|
427 |
*/
|
|
428 |
void CAutoMounterFileSystem::DoParseChildNames(const TDesC8& aList)
|
|
429 |
{
|
|
430 |
ASSERT(State() == EInitialising);
|
0
|
431 |
|
|
432 |
TBuf<0x100> fsName;
|
|
433 |
|
271
|
434 |
fsName.Copy(aList);
|
|
435 |
__PRINT1(_L("#<<- childFS list:'%S'"), &fsName);
|
0
|
436 |
|
|
437 |
//-- parse CSV config line and fill in the file system names array
|
|
438 |
const TChar chDelim = ','; //-- token delimiter, comma
|
271
|
439 |
TPtrC8 ptrCurrLine(aList);
|
0
|
440 |
for(TInt i=0; ;++i)
|
|
441 |
{
|
|
442 |
const TInt delimPos = ptrCurrLine.Locate(chDelim);
|
|
443 |
if(delimPos <= 0)
|
|
444 |
{
|
|
445 |
fsName.Copy(ptrCurrLine);
|
|
446 |
}
|
|
447 |
else
|
|
448 |
{
|
|
449 |
TPtrC8 temp(ptrCurrLine.Ptr(), delimPos);
|
|
450 |
fsName.Copy(temp);
|
|
451 |
}
|
|
452 |
|
|
453 |
fsName.Trim();
|
|
454 |
__PRINT2(_L("#<<- child FS[%d]: '%S'"), i, &fsName);
|
|
455 |
|
|
456 |
|
|
457 |
if(fsName.Length() <= 0)
|
|
458 |
Fault(EPluginInitialise);
|
|
459 |
|
|
460 |
//-- check if the FS name being appended is unique
|
|
461 |
for(TUint j=0; j<iFSNames.Count(); ++j)
|
|
462 |
{
|
|
463 |
if(iFSNames[j] == fsName)
|
|
464 |
{
|
|
465 |
Fault(EPluginInitialise);
|
|
466 |
}
|
|
467 |
}
|
|
468 |
|
|
469 |
|
271
|
470 |
TInt nRes = iFSNames.Append(fsName);
|
|
471 |
(void)nRes;
|
0
|
472 |
ASSERT(nRes ==KErrNone);
|
|
473 |
|
|
474 |
if(delimPos <=0 )
|
|
475 |
break;
|
|
476 |
|
|
477 |
ptrCurrLine.Set(ptrCurrLine.Ptr()+delimPos+1, ptrCurrLine.Length()-delimPos-1);
|
|
478 |
}
|
|
479 |
|
271
|
480 |
}
|
|
481 |
|
|
482 |
//-----------------------------------------------------------------------------
|
|
483 |
|
|
484 |
//-- if this macro is defined, the automounter will use a default hard-coded list of child file systems if it is not found in the estart.txt
|
|
485 |
//-- and this list will consist of one filesystem "FAT".
|
|
486 |
//-- otherwise automounter will panic if it can't find appropriate config in estart.txt
|
|
487 |
#define ALLOW_CONFIGLESS
|
|
488 |
|
|
489 |
/**
|
|
490 |
Process Automounter configuration
|
|
491 |
*/
|
|
492 |
void CAutoMounterFileSystem::ParseConfig()
|
|
493 |
{
|
|
494 |
|
|
495 |
|
|
496 |
ASSERT(State() == ENotInitialised);
|
|
497 |
|
|
498 |
SetState(EInitialising);
|
|
499 |
|
|
500 |
|
|
501 |
|
|
502 |
//-- 1. initialise the array of file system names. These names shall be listed in a config string.
|
|
503 |
//-- the config string is taken from estart.txt usually and its format is like this:
|
|
504 |
//-- section: [AutoMounter] and property "AM_FSNames fat,exfat"
|
|
505 |
//-- in debug version a special text property can override the config string. This allows controlling automounter from
|
|
506 |
//-- the test environment.
|
|
507 |
|
|
508 |
TBuf8<0x100> buf(0);
|
|
509 |
|
|
510 |
_LIT8(KSection, "AutoMounter"); ///< section name
|
|
511 |
_LIT8(KKey_ChildFsList, "AM_FSNames"); ///< a key for the CSV list of child file system names
|
|
512 |
_LIT8(KProp_DefFmtFsIdx, "AM_DefFmtFsIdx");///< a key for the optional parameter that specifies the child file system index, which will be used for formatting unrecognised media
|
|
513 |
|
|
514 |
TBool bUseEstart= ETrue;
|
|
515 |
|
|
516 |
#ifdef _DEBUG
|
|
517 |
|
|
518 |
TInt nRes;
|
|
519 |
|
|
520 |
const TUid KSID_Test1={0x10210EB3}; //-- SID of the test that will define and set test property to control volume mounting
|
|
521 |
const TUint KPropKey = 0; //-- property key
|
|
522 |
|
|
523 |
//-- in debug mode the property will override the estart.txt config
|
|
524 |
if(RProperty::Get(KSID_Test1, KPropKey, buf) == KErrNone)
|
|
525 |
{
|
|
526 |
__PRINT(_L("#<<- reading config from the debug propery:"));
|
|
527 |
TBuf<0x100> buf16(0);
|
|
528 |
buf16.Copy(buf);
|
|
529 |
__PRINT(buf16);
|
|
530 |
|
|
531 |
bUseEstart = EFalse;
|
|
532 |
}
|
|
533 |
#endif //_DEBUG
|
|
534 |
|
|
535 |
if(bUseEstart)
|
|
536 |
{//-- need to read data from the estart.txt, section [AutoMounter]
|
|
537 |
__PRINT(_L("#<<- reading config from estart.txt..."));
|
|
538 |
|
|
539 |
//-- 1. read and parse a CSV list of child file system names
|
|
540 |
//-- this is a mandatory parameter
|
|
541 |
TBool bFound = F32Properties::GetString(KSection, KKey_ChildFsList, buf);
|
|
542 |
if(!bFound)
|
|
543 |
{
|
|
544 |
__PRINT(_L("#<<- child FS list isn't found in config !"));
|
|
545 |
|
|
546 |
#ifdef ALLOW_CONFIGLESS
|
|
547 |
//-- let's use a default list of child file systems (consisting of only one: "FAT")
|
|
548 |
//-- if it is allowed. FAT FS is suggested to be available and already loaded by file server.
|
|
549 |
//-- otherwise it will panic later
|
|
550 |
|
|
551 |
_LIT(KDefChildFS_Config, "fat"); //-- default list
|
|
552 |
__PRINT1(_L("#<<- Using a default list:'%S'"), &KDefChildFS_Config());
|
|
553 |
buf.Copy(KDefChildFS_Config);
|
|
554 |
|
|
555 |
#else //ALLOW_CONFIGLESS
|
|
556 |
|
|
557 |
Fault(EPluginInitialise);
|
|
558 |
|
|
559 |
#endif //ALLOW_CONFIGLESS
|
|
560 |
}
|
|
561 |
|
|
562 |
DoParseChildNames(buf);
|
|
563 |
|
|
564 |
ASSERT(iFSNames.Count());
|
|
565 |
|
|
566 |
//-- 2. read a child FS index that can be used for unrecognisable media default formatting
|
|
567 |
//-- this is an optional parameter. If we have just 1 Child FS, this parameter doesn't make much sense.
|
|
568 |
if(iFSNames.Count() > 1)
|
|
569 |
{
|
|
570 |
TInt32 nVal;
|
|
571 |
bFound = F32Properties::GetInt(KSection, KProp_DefFmtFsIdx, nVal);
|
|
572 |
|
|
573 |
if(!bFound)
|
|
574 |
iChildFsForDefFmt = KErrNotFound;
|
|
575 |
else
|
|
576 |
{//-- check the index validity
|
|
577 |
if(nVal <0 || nVal >= (TInt)iFSNames.Count())
|
|
578 |
{
|
|
579 |
__PRINT1(_L("#<<- Bad DefFmtFsIdx value:%d"), nVal);
|
|
580 |
Fault(EPluginInitialise);
|
|
581 |
}
|
|
582 |
else
|
|
583 |
{
|
|
584 |
iChildFsForDefFmt = nVal;
|
|
585 |
}
|
|
586 |
}
|
|
587 |
}
|
|
588 |
else//if(iFSNames.Count() > 1)
|
|
589 |
{//-- it looks like we have a weird case when the automounter is configured with just 1 child file system
|
|
590 |
iChildFsForDefFmt = KDefaultFSNo;
|
|
591 |
}
|
|
592 |
|
|
593 |
}//if(bUseEstart)
|
|
594 |
else
|
|
595 |
{
|
|
596 |
#ifdef _DEBUG
|
|
597 |
|
|
598 |
//-- it looks like there is a test property that overrides the estart.txt settings. This property should contain
|
|
599 |
//-- a representation of a whole [AutoMounter] section in estart.txt and can have "multiple lines" separated by 0x0d,0x0a
|
|
600 |
buf.TrimAll();
|
|
601 |
|
|
602 |
TInt nPos1;
|
|
603 |
TInt nPos2;
|
|
604 |
|
|
605 |
//-- 1. process "AM_FSNames" key
|
|
606 |
nPos1 = buf.FindF(KKey_ChildFsList);
|
|
607 |
if(nPos1 < 0)
|
|
608 |
{
|
|
609 |
__PRINT(_L("#<<- child FS list isn't found!"));
|
|
610 |
Fault(EPluginInitialise);
|
|
611 |
}
|
|
612 |
|
|
613 |
TPtrC8 ptr(buf.Mid(nPos1));
|
|
614 |
nPos2 = ptr.Locate('\n');
|
|
615 |
if(nPos2 > 0)
|
|
616 |
ptr.Set(ptr.Left(nPos2));
|
|
617 |
|
|
618 |
TLex8 lex(ptr);
|
|
619 |
|
|
620 |
lex.NextToken();
|
|
621 |
lex.SkipSpace();
|
|
622 |
ptr.Set(lex.Remainder());
|
|
623 |
|
|
624 |
DoParseChildNames(ptr);
|
|
625 |
ASSERT(iFSNames.Count());
|
|
626 |
|
|
627 |
|
|
628 |
//-- 2. process "DefFmtFsIdx" key
|
|
629 |
nPos1 = buf.FindF(KProp_DefFmtFsIdx);
|
|
630 |
if(nPos1 > 0 && iFSNames.Count() > 1)
|
|
631 |
{
|
|
632 |
ptr.Set(buf.Mid(nPos1));
|
|
633 |
nPos2 = ptr.Locate('\n');
|
|
634 |
if(nPos2 > 0)
|
|
635 |
ptr.Set(ptr.Left(nPos2));
|
|
636 |
|
|
637 |
lex.Assign(ptr);
|
|
638 |
lex.NextToken();
|
|
639 |
lex.SkipSpace();
|
|
640 |
|
|
641 |
nRes = lex.Val(nPos1);
|
|
642 |
ASSERT(nRes == KErrNone);
|
|
643 |
ASSERT(nPos1 >= 0 && nPos1 < (TInt)iFSNames.Count());
|
|
644 |
|
|
645 |
iChildFsForDefFmt = nPos1;
|
|
646 |
}
|
|
647 |
else
|
|
648 |
{
|
|
649 |
iChildFsForDefFmt = KErrNotFound;
|
|
650 |
}
|
|
651 |
|
|
652 |
#endif //_DEBUG
|
|
653 |
}
|
|
654 |
|
|
655 |
}
|
|
656 |
|
|
657 |
|
|
658 |
//-----------------------------------------------------------------------------
|
|
659 |
/**
|
|
660 |
Initialise this file system. Reads and processes configuration, fills in file system names container, etc.
|
|
661 |
*/
|
|
662 |
void CAutoMounterFileSystem::InitialiseFileSystem()
|
|
663 |
{
|
|
664 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::InitialiseFileSystem() [0x%x]"), this);
|
|
665 |
|
|
666 |
ASSERT(State() == ENotInitialised);
|
|
667 |
|
|
668 |
ParseConfig();
|
0
|
669 |
|
|
670 |
SetState(EInitialised);
|
|
671 |
|
|
672 |
//-- 2. check that the file server has all filesystems we need instantiated and stored in a global container
|
271
|
673 |
TUint cnt = ChildFsNum();
|
|
674 |
if(cnt < KMinChildFsNum)
|
0
|
675 |
{
|
271
|
676 |
__PRINT1(_L("#<<- ::InitialiseFileSystem(): too few File Systems bound: %d!"), cnt);
|
0
|
677 |
Fault(EPluginInitialise);
|
|
678 |
}
|
|
679 |
|
|
680 |
while(cnt--)
|
|
681 |
{
|
|
682 |
GetChildFileSystem(cnt);
|
|
683 |
}
|
|
684 |
|
|
685 |
|
|
686 |
}
|
|
687 |
|
|
688 |
|
|
689 |
|
|
690 |
//-----------------------------------------------------------------------------
|
|
691 |
/**
|
|
692 |
Tries to find out if some of the child file systems can be mounted on the given volume.
|
|
693 |
|
|
694 |
@param apDrive pointer to the TDrive, child FS will need this to access media.
|
|
695 |
@param on return will contain the pointer to the CMountCB object if some of the childs has decided that it can be mounted.
|
|
696 |
@param apFS on return will contain the pointer to the CFileSystem that has produced the proped CMountCB if
|
|
697 |
|
|
698 |
@return KErrNone on success, otherwise standard error code.
|
|
699 |
|
|
700 |
*/
|
|
701 |
TInt CAutoMounterFileSystem::TryMountFilesystem(TDrive* apDrive, CMountCB** apMount, CFileSystem** apFS)
|
|
702 |
{
|
|
703 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::TryMountFilesystem()[0x%x]"), this);
|
|
704 |
|
271
|
705 |
const TUint KNumFS = ChildFsNum(); //-- number of child file systems supported
|
|
706 |
ASSERT(State() == EInitialised && (KNumFS >= KMinChildFsNum));
|
0
|
707 |
|
|
708 |
|
|
709 |
*apMount = NULL;
|
|
710 |
*apFS = NULL;
|
|
711 |
|
|
712 |
|
|
713 |
TInt nRes;
|
271
|
714 |
TUint cntFS;
|
0
|
715 |
CMountCB* pMountCB = NULL;
|
|
716 |
CFileSystem* pMatchedFS = NULL;
|
|
717 |
|
|
718 |
for(cntFS=0; cntFS < KNumFS; ++cntFS)
|
|
719 |
{
|
|
720 |
|
|
721 |
__PRINT2(_L("#<<-@@ trying FS[%d]:%S"), cntFS, &iFSNames[cntFS]);
|
|
722 |
|
|
723 |
CFileSystem* pFS = GetChildFileSystem(cntFS); //-- Find current filesystem object in the FileServer's global container
|
|
724 |
|
|
725 |
//-- 2. create CMountCB instance and set it up
|
|
726 |
pMountCB = NULL;
|
|
727 |
|
|
728 |
TRAP(nRes, pMountCB = pFS->NewMountL());
|
|
729 |
if(nRes != KErrNone)
|
|
730 |
{
|
271
|
731 |
return nRes;
|
0
|
732 |
}
|
|
733 |
|
|
734 |
ASSERT(pMountCB);
|
|
735 |
pMountCB->SetDrive(apDrive);
|
|
736 |
|
|
737 |
|
|
738 |
//-- 2.1 Firstly try using special CMountCB interface to find out if current FS can be mounted on this media
|
|
739 |
nRes = pMountCB->CheckFileSystemMountable();
|
|
740 |
if(nRes == KErrNotSupported)
|
|
741 |
{
|
|
742 |
//-- file system doesn't support this feature,
|
|
743 |
//-- 2.2 try to check the file system by mounting and dismounting later. It can result in some long activity, like FAT scanning etc.
|
|
744 |
TRAP(nRes, pMountCB->MountL(EFalse));
|
|
745 |
pMountCB->Dismounted(); //-- dismount the mountCB, it will be required in dismounted state anyway
|
|
746 |
}
|
|
747 |
|
|
748 |
//-- 2.3 analyse the result of mounting
|
|
749 |
if(nRes != KErrNone)
|
|
750 |
{
|
|
751 |
if(nRes == KErrLocked)
|
|
752 |
{//-- this is a special case; The media (SD card for example) is locked.
|
|
753 |
//-- Pretend that everything is OK and return CMountCB instance that is produced by the _default_ file system.
|
|
754 |
//-- locked media case will be handled by the file server later.
|
|
755 |
ASSERT(cntFS == KDefaultFSNo); //-- the default FS is tried first and must detect the locked media
|
|
756 |
pMatchedFS = pFS;
|
|
757 |
__PRINT(_L("#<<-@@ The media is LOCKED !"));
|
|
758 |
break;
|
|
759 |
}
|
|
760 |
|
|
761 |
//-- failed to mount the file system, most likey it is not recognised
|
|
762 |
pMountCB->Close(); //-- this is a self-destructing object!
|
|
763 |
pMountCB = NULL;
|
|
764 |
__PRINT(_L("#<<-@@ Mount FAILED !"));
|
|
765 |
}
|
|
766 |
else
|
|
767 |
{
|
|
768 |
//-- mounted OK, the file system is recognised
|
|
769 |
__PRINT(_L("#<<-@@ Mount OK!"));
|
|
770 |
|
|
771 |
pMatchedFS = pFS;
|
|
772 |
break;
|
|
773 |
}
|
|
774 |
|
|
775 |
}//for(cntFS=0; cntFS<KNumFS; ++cntFS)
|
|
776 |
|
|
777 |
if(cntFS >= KNumFS)
|
|
778 |
{//-- no one from the FS factories recognised the file system
|
|
779 |
__PRINT1(_L("#<<- ::TryMountFilesystem()[0x%x] No file system recognised!"), this);
|
|
780 |
|
|
781 |
SetName(&KFileSystemName_AutoMounter);
|
|
782 |
return KErrCorrupt;
|
|
783 |
}
|
|
784 |
|
|
785 |
ASSERT(pMountCB && pMatchedFS);
|
|
786 |
*apMount = pMountCB;
|
|
787 |
*apFS = pMatchedFS;
|
|
788 |
|
|
789 |
//-- set this FS name to the name of recognised FS. In this case the automounter "pretends" to be one of the child file systems on
|
|
790 |
//-- successful mounting. This behaviour was considered to be incorrect.
|
|
791 |
//TPtrC fsName = pMatchedFS->Name();
|
|
792 |
//SetName(&fsName);
|
|
793 |
|
|
794 |
return KErrNone;
|
|
795 |
|
|
796 |
}
|
|
797 |
|
|
798 |
//-----------------------------------------------------------------------------
|
|
799 |
/**
|
|
800 |
get the child file system object by the index in file child system names container
|
|
801 |
|
|
802 |
@param aIndex index in the iFSNames
|
|
803 |
@return pointer to the FS object if it is found, NULL otherwise
|
|
804 |
*/
|
|
805 |
CFileSystem* CAutoMounterFileSystem::GetChildFileSystem(TUint aIndex) const
|
|
806 |
{
|
271
|
807 |
ASSERT(State() == EInitialised && (ChildFsNum() >= KMinChildFsNum) && aIndex < ChildFsNum());
|
0
|
808 |
|
|
809 |
const TDesC& fsName = iFSNames[aIndex]; //-- registered child file system name
|
|
810 |
CFileSystem* pFS = GetFileSystem(fsName); //-- Find filesystem object in the FileServer's global container
|
|
811 |
|
|
812 |
if(!pFS)
|
|
813 |
{
|
|
814 |
__PRINT1(_L("#<<- CAutoMounterFileSystem::GetChildFileSystem() FileServer doesn't have FS:%S Added!"), &fsName);
|
|
815 |
Fault(EFileSysNotAdded);
|
|
816 |
}
|
|
817 |
|
|
818 |
return pFS;
|
|
819 |
}
|
|
820 |
|
|
821 |
//-----------------------------------------------------------------------------
|
|
822 |
/**
|
|
823 |
Find the child file system object by the file system name name hash.
|
|
824 |
@param aFsNameHash FS name hash
|
|
825 |
@return pointer to the FS object if it is found, NULL otherwise
|
|
826 |
*/
|
|
827 |
CFileSystem* CAutoMounterFileSystem::GetChildFileSysteByNameHash(TUint32 aFsNameHash) const
|
|
828 |
{
|
271
|
829 |
ASSERT(State() == EInitialised && (ChildFsNum() >= KMinChildFsNum) && aFsNameHash);
|
0
|
830 |
|
271
|
831 |
const TUint cnt = ChildFsNum();
|
|
832 |
for(TUint i=0; i<cnt; ++i)
|
0
|
833 |
{
|
|
834 |
if(aFsNameHash == iFSNames.GetStringHash(i))
|
|
835 |
{
|
|
836 |
const TDesC& fsName = iFSNames[i]; //-- registered child file system name
|
|
837 |
__PRINT2(_L("#<<- ::GetChildFileSysteByNameHash() found FsName:%S by hash:0x%x"), &fsName, aFsNameHash);
|
|
838 |
CFileSystem* pFS = GetFileSystem(fsName); //-- Find filesystem object in the FileServer's global container
|
|
839 |
ASSERT(pFS);
|
|
840 |
return pFS;
|
|
841 |
}
|
|
842 |
|
|
843 |
}
|
|
844 |
|
|
845 |
__PRINT1(_L("#<<- ::GetChildFileSysteByNameHash() No FS name found by hash:0x%x"), aFsNameHash);
|
|
846 |
|
|
847 |
return NULL;
|
|
848 |
}
|
|
849 |
|
|
850 |
|
|
851 |
|
|
852 |
|
|
853 |
//#######################################################################################################################################
|
|
854 |
//# XStringArray implementation
|
|
855 |
//#######################################################################################################################################
|
|
856 |
|
|
857 |
XStringArray::XStringArray()
|
|
858 |
{
|
|
859 |
}
|
|
860 |
|
|
861 |
XStringArray::~XStringArray()
|
|
862 |
{
|
|
863 |
Reset();
|
|
864 |
iStrings.Close();
|
|
865 |
}
|
|
866 |
|
|
867 |
//-----------------------------------------------------------------------------
|
|
868 |
void XStringArray::Reset()
|
|
869 |
{
|
|
870 |
iStrings.ResetAndDestroy();
|
|
871 |
}
|
|
872 |
|
|
873 |
//-----------------------------------------------------------------------------
|
|
874 |
const TDesC& XStringArray::operator[](TUint aIndex) const
|
|
875 |
{
|
|
876 |
if(aIndex >= (TUint)iStrings.Count())
|
|
877 |
Panic(EIndexOutOfRange);
|
|
878 |
|
|
879 |
HBufC* des=iStrings[aIndex];
|
|
880 |
return *des;
|
|
881 |
}
|
|
882 |
|
|
883 |
//-----------------------------------------------------------------------------
|
|
884 |
/**
|
|
885 |
Append file system name to the container. The name is converted to upper case.
|
|
886 |
@param aString name descriptor.
|
|
887 |
@return standard error code
|
|
888 |
*/
|
|
889 |
TInt XStringArray::Append(const TDesC& aString)
|
|
890 |
{
|
|
891 |
HBufC* pBuf = aString.Alloc();
|
|
892 |
if(!pBuf)
|
|
893 |
return KErrNoMemory;
|
|
894 |
|
|
895 |
//-- string being appended shall be unique
|
|
896 |
for(TUint i=0; i<Count(); ++i)
|
|
897 |
{
|
|
898 |
if(operator[](i).CompareF(aString) == 0)
|
|
899 |
{
|
|
900 |
ASSERT(0);
|
|
901 |
return KErrNone;
|
|
902 |
}
|
|
903 |
}
|
|
904 |
|
|
905 |
pBuf->Des().UpperCase(); //-- convert the FS name to upper-case in order to correctly calculate hash later
|
|
906 |
return iStrings.Append(pBuf);
|
|
907 |
}
|
|
908 |
|
|
909 |
|
|
910 |
//-----------------------------------------------------------------------------
|
|
911 |
/**
|
|
912 |
Get child FS name hash by index in the names container.
|
|
913 |
@param aIndex name index in the container
|
|
914 |
@return file system name hash (crc32)
|
|
915 |
*/
|
|
916 |
TUint32 XStringArray::GetStringHash(TUint aIndex) const
|
|
917 |
{
|
|
918 |
const TDesC& des = operator[](aIndex);
|
|
919 |
return TVolFormatParam::CalcFSNameHash(des);
|
|
920 |
}
|
|
921 |
|
|
922 |
|
|
923 |
|
|
924 |
void XStringArray::Panic(TPanicCode aPanicCode) const
|
|
925 |
{
|
|
926 |
_LIT(KPanicCat,"XStringArray");
|
|
927 |
User::Panic(KPanicCat, aPanicCode);
|
|
928 |
}
|
|
929 |
|
|
930 |
|
|
931 |
|
|
932 |
|
|
933 |
|
|
934 |
|
|
935 |
|
|
936 |
|
|
937 |
|
|
938 |
|
|
939 |
|
|
940 |
|
|
941 |
|
|
942 |
|
|
943 |
|
|
944 |
|
|
945 |
|
|
946 |
|
|
947 |
|
|
948 |
|
|
949 |
|
|
950 |
|
|
951 |
|
|
952 |
|
|
953 |
|
|
954 |
|
|
955 |
|
|
956 |
|
|
957 |
|
|
958 |
|
|
959 |
|
|
960 |
|