|
1 // Copyright (c) 1995-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 // f32\sfile\sf_drv.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include "sf_std.h" |
|
19 #include "sf_file_cache.h" |
|
20 #include <hal.h> |
|
21 |
|
22 |
|
23 |
|
24 //const TInt KMaxNotifierAttempts=4; // not used anywhere |
|
25 |
|
26 static TPtrC StripBackSlash(const TDesC& aName) |
|
27 // |
|
28 // If aName ends in a backslash, strip it. |
|
29 // |
|
30 { |
|
31 |
|
32 __ASSERT_DEBUG(aName.Length(),Fault(EStripBackSlashBadName)); |
|
33 if (aName[aName.Length()-1]==KPathDelimiter) |
|
34 return(aName.Left(aName.Length()-1)); |
|
35 return(aName); |
|
36 } |
|
37 |
|
38 static void CheckSubClose(CFsObject* anObj,TInt aHandle, CSessionFs* aSession) |
|
39 // |
|
40 // Close anObj if its not NULL. |
|
41 // |
|
42 { |
|
43 __PRINT1(_L("CheckSubClose() session 0x0%x"),aSession); |
|
44 __PRINT1(_L("CheckSubClose() anObj 0x0%x"),anObj); |
|
45 |
|
46 if(!anObj) |
|
47 return; |
|
48 |
|
49 if(aHandle==0) |
|
50 { |
|
51 // can't have been added to the object index |
|
52 __ASSERT_DEBUG(KErrNotFound==aSession->Handles().At(anObj,ETrue),Fault(ESubOpenBadHandle)); |
|
53 anObj->Close(); |
|
54 } |
|
55 else |
|
56 aSession->Handles().Remove(aHandle,ETrue); |
|
57 } |
|
58 |
|
59 TInt ValidateDrive(TInt aDriveNumber,CFsRequest* aRequest) |
|
60 // |
|
61 // Validate a drive number and set iTheDrive. |
|
62 // |
|
63 { |
|
64 __CHECK_MAINTHREAD(); |
|
65 if (aDriveNumber==KDefaultDrive) |
|
66 aDriveNumber=aRequest->Session()->CurrentDrive(); |
|
67 if (!RFs::IsValidDrive(aDriveNumber)) |
|
68 return(KErrBadName); |
|
69 aRequest->SetDrive(&TheDrives[aDriveNumber]); |
|
70 return(KErrNone); |
|
71 } |
|
72 |
|
73 TInt ValidateDriveDoSubst(TInt aDriveNumber,CFsRequest* aRequest) |
|
74 // |
|
75 // Validate a drive number and set iTheDrive. |
|
76 // |
|
77 { |
|
78 |
|
79 TInt r=ValidateDrive(aDriveNumber,aRequest); |
|
80 if (r!=KErrNone) |
|
81 return(r); |
|
82 if (aRequest->Drive()->IsSubsted()) |
|
83 { |
|
84 aRequest->SetSubstedDrive(aRequest->Drive()); |
|
85 aRequest->SetDrive(&aRequest->Drive()->SubstedDrive()); |
|
86 } |
|
87 return(KErrNone); |
|
88 } |
|
89 |
|
90 void ValidateAtts(TUint /*anEntryAtts*/,TUint& aSetAttMask,TUint& aClearAttMask) |
|
91 // |
|
92 // Do not allow the entry type to be changed |
|
93 // |
|
94 { |
|
95 const TUint KReadOnlySetAtts = KEntryAttVolume | |
|
96 KEntryAttDir | |
|
97 KEntryAttRemote; |
|
98 |
|
99 const TUint KReadOnlyClrAtts = KEntryAttVolume | |
|
100 KEntryAttDir | |
|
101 KEntryAttRemote | |
|
102 KEntryAttModified; |
|
103 |
|
104 aSetAttMask &= ~KReadOnlySetAtts; |
|
105 aClearAttMask &= ~KReadOnlyClrAtts; |
|
106 } |
|
107 |
|
108 void CheckForLeaveAfterOpenL(TInt leaveError, CFsRequest* aRequest, TInt aHandle) |
|
109 // |
|
110 // Tidy up in the event of a leave after opening a file or directory |
|
111 { |
|
112 if (leaveError) |
|
113 { |
|
114 CFsObject* anObj=(CFsObject* )aRequest->ScratchValue(); |
|
115 CheckSubClose(anObj,aHandle,aRequest->Session()); |
|
116 User::Leave(leaveError); |
|
117 } |
|
118 } |
|
119 |
|
120 TDrive::TDrive() |
|
121 // |
|
122 // Constructor. |
|
123 // |
|
124 : iDriveNumber(0),iAtt(0),iChanged(EFalse), |
|
125 iFSys(NULL),iCurrentMount(NULL),iSubstedDrive(NULL),iSubst(NULL), |
|
126 iMount(NULL),iDriveFlags(0),iMountFailures(0) |
|
127 {} |
|
128 |
|
129 void TDrive::CreateL(TInt aDriveNumber) |
|
130 // |
|
131 // Allocate the drive number and any resources. |
|
132 // |
|
133 { |
|
134 __PRINT1(_L("TDrive::CreateL(%d)"),aDriveNumber); |
|
135 iDriveNumber=aDriveNumber; |
|
136 iMount=TheContainer->CreateL(); |
|
137 TInt r=iLock.CreateLocal(); |
|
138 User::LeaveIfError(r); |
|
139 } |
|
140 |
|
141 TInt TDrive::CheckMountAndEntryName(const TDesC& aName) |
|
142 // |
|
143 // Check drive is mounted then check aName is legal |
|
144 // |
|
145 { |
|
146 |
|
147 __PRINT1(_L("TDrive::CheckMountAndEntryName Drive%d"),DriveNumber()); |
|
148 TInt r=CheckMount(); |
|
149 if (r==KErrNone && IsIllegalFullName(aName)) |
|
150 return(KErrBadName); |
|
151 return(r); |
|
152 } |
|
153 |
|
154 void TDrive::MultiSlotDriveCheck() |
|
155 { |
|
156 // Check whether the current drive is a dual-slot/multi-slot |
|
157 // if so, we need to check which drive is connected now and |
|
158 // swap the mapping in LocalDrives::iMapping such that the |
|
159 // mapping of driveNumber to localDriveNumber is correct. |
|
160 |
|
161 Lock(); |
|
162 //Is this a multislot drive? |
|
163 if(LocalDrives::iIsMultiSlotDrive[iDriveNumber]) |
|
164 { |
|
165 for(TInt localDrvNum=0; localDrvNum<KMaxLocalDrives; localDrvNum++) |
|
166 { |
|
167 // ensure that this local drive is a multi-slot choice for this drive number.. |
|
168 if(LocalDrives::iReverseMapping[localDrvNum]==iDriveNumber) |
|
169 { |
|
170 // Caps - find out which one is connected |
|
171 TLocalDriveCapsBuf capsInfo; |
|
172 TInt r = LocalDrives::iLocalDrives[localDrvNum].Caps(capsInfo); |
|
173 if(r==KErrNotReady) |
|
174 { |
|
175 continue; //go to next localdrive |
|
176 } |
|
177 //found a connected drive |
|
178 //Update mapping |
|
179 #ifdef _DEBUG |
|
180 RDebug::Print(_L("Multislot drive mapping update: DriveNum %d to LocDrv %d"),iDriveNumber,localDrvNum); |
|
181 #endif |
|
182 |
|
183 LocalDrives::iMapping[iDriveNumber] = localDrvNum; |
|
184 break; // Swap complete - don't look any further |
|
185 } |
|
186 } |
|
187 } |
|
188 UnLock(); |
|
189 } |
|
190 |
|
191 TInt TDrive::CheckMount() |
|
192 // |
|
193 // Check the drive and try to mount a media if not already mounted. |
|
194 // |
|
195 { |
|
196 __PRINT2(_L("TDrive::CheckMount Drive%d, changed:%d"),DriveNumber(), iChanged); |
|
197 __CHECK_DRIVETHREAD(iDriveNumber); |
|
198 |
|
199 if (!iFSys) |
|
200 return KErrNotReady; |
|
201 |
|
202 if (iChanged) // If a media change has occurred |
|
203 { |
|
204 iMountFailures = 0; |
|
205 iChanged=EFalse; // Reset the flag |
|
206 if (IsMounted()) // Dismount the mount if it is still marked as mounted |
|
207 { |
|
208 DoDismount(); |
|
209 } |
|
210 //If we have a dual/multi removable media slot then we may need to |
|
211 //swop the mappings. |
|
212 MultiSlotDriveCheck(); |
|
213 } |
|
214 |
|
215 if (!IsMounted()) // Checks that iCurrentMount!=NULL |
|
216 { |
|
217 __PRINT(_L("TDrive::CheckMount() Not Mounted")); |
|
218 const TInt KMaxMountFailures = 3; |
|
219 // if we've repeatedly failed to mount, give up until a media change |
|
220 if (iMountFailures >= KMaxMountFailures) |
|
221 { |
|
222 __PRINT1(_L("TDrive::CheckMount() retries exceeded, last Err:%d"), iLastMountError); |
|
223 return iLastMountError; |
|
224 } |
|
225 |
|
226 if (!ReMount()) // Have we just remounted a mount we have previously encountered? |
|
227 { |
|
228 MountFileSystem(EFalse); // If not, mount it for the first time now |
|
229 } |
|
230 else if(IsWriteProtected() && IsWriteableResource()) |
|
231 { |
|
232 DoDismount(); |
|
233 return KErrAccessDenied; |
|
234 } |
|
235 } |
|
236 |
|
237 if (iReason==KErrNone && CurrentMount().LockStatus() > 0) |
|
238 { |
|
239 //-- this meand that the mount has drive access objetcs opened (RFormat or RRawDisk) |
|
240 __PRINT1(_L("TDrive::CheckMount() Mount is locked! LockStaus:%d"), CurrentMount().LockStatus()); |
|
241 return KErrInUse; |
|
242 } |
|
243 |
|
244 __PRINT1(_L("TDrive::CheckMount returned %d "),iReason); |
|
245 |
|
246 return(iReason); |
|
247 } |
|
248 |
|
249 //---------------------------------------------------------------------------- |
|
250 /** |
|
251 Try and re-mount any of the pending media |
|
252 |
|
253 @return ETrue if the mount matching media found and been attached back (set as iCurrentMount) |
|
254 */ |
|
255 TBool TDrive::ReMount() |
|
256 { |
|
257 const TInt mCount=Mount().Count(); |
|
258 __PRINT1(_L("TDrive::ReMount() MountCnt:%d"), mCount); |
|
259 |
|
260 const TInt u=(Mount().UniqueID()<<16); |
|
261 iReason=KErrNone; |
|
262 |
|
263 //-- try every instance of CMountCB that is associated with this object of TDrive. |
|
264 //-- mounts are stored in the container of mCount elements. |
|
265 //-- if some CMountCB recognises the media it belongs, it means that "remount succeded" |
|
266 for(TInt i=0; i<mCount; i++) |
|
267 { |
|
268 CMountCB* pM=(CMountCB*)Mount().At(u|i); |
|
269 |
|
270 if (ReMount(*pM)) |
|
271 return ETrue; |
|
272 } |
|
273 |
|
274 return EFalse; |
|
275 } |
|
276 |
|
277 //---------------------------------------------------------------------------- |
|
278 /** |
|
279 Try and re-mount the specified media. |
|
280 |
|
281 @return ETrue if remounting succeeded - i.e. the CMountCB instance that matches the media is found in the |
|
282 mounts container (Mount()) and bound to the media. |
|
283 */ |
|
284 TBool TDrive::ReMount(CMountCB& aMount) |
|
285 { |
|
286 __PRINT1(_L("TDrive::ReMount(0x%x)"), &aMount); |
|
287 iReason=KErrNone; |
|
288 |
|
289 if (!aMount.IsDismounted() && !aMount.ProxyDriveDismounted()) |
|
290 { |
|
291 aMount.SetDrive(this); |
|
292 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBReMount, EF32TraceUidFileSys, DriveNumber()); |
|
293 |
|
294 //-- actually, this is asking CMountCB to see if it belongs to the current media. |
|
295 iReason = aMount.ReMount(); |
|
296 |
|
297 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBReMountRet, EF32TraceUidFileSys, iReason); |
|
298 |
|
299 if (iReason == KErrNone) // ReMount succeeded |
|
300 { |
|
301 aMount.Open(); |
|
302 iCurrentMount = &aMount; |
|
303 __PRINT1(_L("TDrive::ReMount for Mount:0x%x OK!"), &aMount); |
|
304 return ETrue; |
|
305 } |
|
306 |
|
307 __PRINT2(_L("TDrive::ReMount for Mount:0x%x failed iReason=%d"),&aMount,iReason); |
|
308 } |
|
309 else |
|
310 { |
|
311 __PRINT1(_L("TDrive::ReMount() failed - Mount:0x%x is dismounted"), &aMount); |
|
312 } |
|
313 |
|
314 return EFalse; |
|
315 } |
|
316 |
|
317 |
|
318 |
|
319 //---------------------------------------------------------------------------- |
|
320 /** |
|
321 Mount the media on the drive. Optionally force a bad media to be mounted. |
|
322 |
|
323 @param apMount out: pointer to the produced CMountCB object; NULL if the CMountCB is not constructed |
|
324 @param aForceMount if ETrue, the filesystem will be forcedly mounted on the drive, disregarding what it contains. |
|
325 @param aFsNameHash file system name hash; see TDrive::MountFileSystem() |
|
326 */ |
|
327 void TDrive::DoMountFileSystemL(CMountCB*& apMount, TBool aForceMount, TUint32 aFsNameHash) |
|
328 { |
|
329 CFileSystem* pMountsFs = NULL; //-- reference to the filesystem that will be producing CMountCB |
|
330 |
|
331 apMount = NULL; |
|
332 |
|
333 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountL, EF32TraceUidFileSys, &FSys(), DriveNumber()); |
|
334 |
|
335 //-- construct a new CmountCB object. |
|
336 //-- on return pMountsFs will be the pointer to the factory object of CFileSystem that produced this mount |
|
337 apMount = FSys().NewMountExL(this, &pMountsFs, aForceMount, aFsNameHash); |
|
338 |
|
339 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountLRet, EF32TraceUidFileSys, KErrNone, apMount); |
|
340 __PRINT2(_L("TDrive::MountMediaL created mount:0x%x FileSys:0x%x"), apMount, pMountsFs); |
|
341 |
|
342 ASSERT(pMountsFs && apMount); |
|
343 |
|
344 apMount->SetMountNumber(iMountNumber++); |
|
345 apMount->InitL(*this, pMountsFs); //-- initialise Mount |
|
346 apMount->MountL(aForceMount); //-- mount the file system |
|
347 Mount().AddL(apMount,EFalse); //-- add mount object to the mounts container. |
|
348 |
|
349 iCurrentMount=apMount; |
|
350 } |
|
351 |
|
352 |
|
353 //---------------------------------------------------------------------------- |
|
354 /* |
|
355 Mount file system on the drive. |
|
356 @param aForceMount if EFalse, will try to mount the file system normally, the file system implementation will decide if it can work on this drive or not. |
|
357 if ETrue, will mount the file suystem by force, this is used mostly for formatting unrecognisable media. |
|
358 |
|
359 @param aFsNameHash optional parameter. Can specify the concrete file system name (hash). It can be used to force mounting some specific |
|
360 file system. Default value '0' means "not specified / not used" |
|
361 |
|
362 |
|
363 TDrive::iReason on return contains the operation result code. |
|
364 */ |
|
365 void TDrive::MountFileSystem(TBool aForceMount, TUint32 aFsNameHash /*=0*/ ) |
|
366 { |
|
367 __PRINT2(_L("TDrive::MountFileSystem aForceMount=%d, FSNameHash:0x%x"),aForceMount, aFsNameHash); |
|
368 __CHECK_DRIVETHREAD(iDriveNumber); |
|
369 |
|
370 iCurrentMount=NULL; |
|
371 if(!iFSys) |
|
372 { |
|
373 iReason=KErrNotReady; |
|
374 return; |
|
375 } |
|
376 |
|
377 CMountCB* pM=NULL; |
|
378 TRAP(iReason, DoMountFileSystemL(pM, aForceMount, aFsNameHash)); |
|
379 if (iReason == KErrNone) |
|
380 { |
|
381 iMountFailures = 0; |
|
382 ASSERT(iCurrentMount); |
|
383 } |
|
384 else |
|
385 { |
|
386 iLastMountError = iReason; |
|
387 iMountFailures++; |
|
388 __PRINT2(_L("TDrive::MountFileSystem 0x%x failed iReason=%d"),pM,iReason); |
|
389 if(pM) |
|
390 pM->Close(); |
|
391 |
|
392 ASSERT(!iCurrentMount); |
|
393 } |
|
394 } |
|
395 |
|
396 |
|
397 //---------------------------------------------------------------------------- |
|
398 /** |
|
399 Generic mount control method. |
|
400 @param aLevel specifies the operation to perfrom on the mount |
|
401 @param aOption specific option for the given operation |
|
402 @param aParam pointer to generic parameter, its meaning depends on aLevel and aOption |
|
403 |
|
404 @return standard error code. |
|
405 */ |
|
406 TInt TDrive::MountControl(TInt aLevel, TInt aOption, TAny* aParam) |
|
407 { |
|
408 TRACE4(UTF::EBorder, UTraceModuleFileSys::ECMountCBMountControl, EF32TraceUidFileSys, DriveNumber(), aLevel, aOption, aParam); |
|
409 TInt r = CurrentMount().MountControl(aLevel, aOption, aParam); |
|
410 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBMountControlRet, EF32TraceUidFileSys, r); |
|
411 |
|
412 return r; |
|
413 } |
|
414 |
|
415 //---------------------------------------------------------------------------- |
|
416 /** |
|
417 Request aFreeSpaceRequired free bytes from the mount associated with this drive. |
|
418 The volume free space on for some filesystems can be changing (usually increasing) after it has been mounted. |
|
419 If the mount supports this functionality, it can block this call until certain number of free bytes encounted if its free |
|
420 space calculation activity hasn't finished yet. |
|
421 |
|
422 @param aFreeSpaceRequired required free space, bytes. |
|
423 |
|
424 @return KErrNone on success and if there is at least aFreeSpaceRequired bytes on the volume |
|
425 KErrDiskFull on success and if there is no aFreeSpaceRequired bytes on the volume |
|
426 system-wide error code otherwise |
|
427 */ |
|
428 TInt TDrive::RequestFreeSpaceOnMount(TUint64 aFreeSpaceRequired) |
|
429 { |
|
430 TInt nRes; |
|
431 |
|
432 nRes = CheckMount(); |
|
433 if(nRes != KErrNone) |
|
434 return nRes; |
|
435 |
|
436 //-- 1. Try mount-specific request first. If the mount is still performing free space calculations, |
|
437 //-- the caller will be suspended until aFreeSpaceRequired bytes is available or scanning process finishes |
|
438 { |
|
439 TUint64 freeSpaceReq = aFreeSpaceRequired; |
|
440 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBFreeSpace, EF32TraceUidFileSys, DriveNumber()); |
|
441 nRes = CurrentMount().RequestFreeSpace(freeSpaceReq); |
|
442 TRACERET3(UTF::EBorder, UTraceModuleFileSys::ECMountCBFreeSpaceRet, EF32TraceUidFileSys, nRes, I64LOW(freeSpaceReq), I64HIGH(freeSpaceReq)); |
|
443 if(nRes == KErrNone) |
|
444 { |
|
445 return (freeSpaceReq >= aFreeSpaceRequired) ? KErrNone : KErrDiskFull; |
|
446 } |
|
447 } |
|
448 |
|
449 //-- given Mount doesn't support this functionality, use legacy method |
|
450 TVolumeInfo volInfo; |
|
451 nRes = Volume(volInfo); |
|
452 if(nRes !=KErrNone) |
|
453 return nRes; |
|
454 |
|
455 return ((TUint64)volInfo.iFree >= aFreeSpaceRequired) ? KErrNone : KErrDiskFull; |
|
456 } |
|
457 |
|
458 //---------------------------------------------------------------------------- |
|
459 /** |
|
460 Get size of the mounted volume. It can be less than physical volume size because FileSystem data may occupy some space. |
|
461 |
|
462 @param aSize on success mounted volume size in bytes will be returned there |
|
463 @return KErrNone on success, standard error code otherwise |
|
464 */ |
|
465 TInt TDrive::MountedVolumeSize(TUint64& aSize) |
|
466 { |
|
467 TInt nRes; |
|
468 |
|
469 nRes = CheckMount(); |
|
470 if(nRes != KErrNone) |
|
471 return nRes; |
|
472 |
|
473 //-- 1. Try mount-specific request first. It won't block this call as CMountCB::VolumeL() can do if some background activity is going on the mount |
|
474 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBVolumeSize, EF32TraceUidFileSys, DriveNumber()); |
|
475 nRes = CurrentMount().MountedVolumeSize(aSize); |
|
476 TRACERET3(UTF::EBorder, UTraceModuleFileSys::ECMountCBVolumeSize, EF32TraceUidFileSys, nRes, I64LOW(aSize), I64HIGH(aSize)); |
|
477 if(nRes == KErrNone) |
|
478 return nRes; |
|
479 |
|
480 //-- given Mount doesn't support this functionality, use legacy method |
|
481 TVolumeInfo volInfo; |
|
482 nRes = Volume(volInfo); |
|
483 if(nRes == KErrNone) |
|
484 { |
|
485 aSize = volInfo.iSize; |
|
486 } |
|
487 |
|
488 return nRes; |
|
489 } |
|
490 |
|
491 //---------------------------------------------------------------------------- |
|
492 /** |
|
493 Get _current_ amount of free space on the volume. Some mounts implementations can be updating the amount of free space |
|
494 in background. |
|
495 |
|
496 @param aFreeDiskSpace on success will contain a current amount of free space |
|
497 @return KErrNone on success, standard error code otherwise |
|
498 |
|
499 */ |
|
500 TInt TDrive::FreeDiskSpace(TInt64& aFreeDiskSpace) |
|
501 { |
|
502 TInt nRes; |
|
503 |
|
504 nRes = CheckMount(); |
|
505 if(nRes != KErrNone) |
|
506 return nRes; |
|
507 |
|
508 //-- 1. Try mount-specific request first. It won't block this call as CMountCB::VolumeL() can do |
|
509 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBCurrentFreeSpace, EF32TraceUidFileSys, DriveNumber()); |
|
510 nRes = CurrentMount().GetCurrentFreeSpaceAvailable(aFreeDiskSpace); |
|
511 TRACERET3(UTF::EBorder, UTraceModuleFileSys::ECMountCBCurrentFreeSpaceRet, EF32TraceUidFileSys, nRes, I64LOW(aFreeDiskSpace), I64HIGH(aFreeDiskSpace)); |
|
512 if(nRes == KErrNone) |
|
513 return nRes; |
|
514 |
|
515 //-- given Mount doesn't support this functionality, use legacy method |
|
516 TVolumeInfo volInfo; |
|
517 nRes = Volume(volInfo); |
|
518 if(nRes == KErrNone) |
|
519 { |
|
520 aFreeDiskSpace = volInfo.iFree; |
|
521 } |
|
522 |
|
523 return nRes; |
|
524 } |
|
525 |
|
526 //---------------------------------------------------------------------------- |
|
527 /** |
|
528 Finalise drive (the mount). |
|
529 |
|
530 @param aOperation describes finalisation operation ,see RFs::TFinaliseDrvMode |
|
531 @param aParam1 not used, for future expansion |
|
532 @param aParam2 not used, for future expansion |
|
533 |
|
534 @return Standard error code |
|
535 */ |
|
536 TInt TDrive::FinaliseMount(TInt aOperation, TAny* aParam1/*=NULL*/, TAny* aParam2/*=NULL*/) |
|
537 { |
|
538 TInt r=CheckMount(); |
|
539 if (r!=KErrNone) |
|
540 return(r); |
|
541 |
|
542 r = FlushCachedFileInfo(); |
|
543 if (r!=KErrNone) |
|
544 return(r); |
|
545 |
|
546 if(IsWriteProtected()) |
|
547 return(KErrAccessDenied); |
|
548 |
|
549 TRACE4(UTF::EBorder, UTraceModuleFileSys::ECMountCBFinaliseMount2, EF32TraceUidFileSys, DriveNumber(), aOperation, aParam1, aParam2); |
|
550 TRAP(r,CurrentMount().FinaliseMountL(aOperation, aParam1, aParam2)); |
|
551 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBFinaliseMount2Ret, EF32TraceUidFileSys, r); |
|
552 |
|
553 return r; |
|
554 } |
|
555 |
|
556 //---------------------------------------------------------------------------- |
|
557 /** old implementation */ |
|
558 TInt TDrive::FinaliseMount() |
|
559 { |
|
560 TInt r=CheckMount(); |
|
561 if (r!=KErrNone) |
|
562 return(r); |
|
563 |
|
564 r = FlushCachedFileInfo(); |
|
565 if (r!=KErrNone) |
|
566 return(r); |
|
567 |
|
568 if(IsWriteProtected()) |
|
569 return(KErrAccessDenied); |
|
570 |
|
571 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBFinaliseMount1, EF32TraceUidFileSys, DriveNumber()); |
|
572 TRAP(r,CurrentMount().FinaliseMountL()); |
|
573 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBFinaliseMount1Ret, EF32TraceUidFileSys, r); |
|
574 |
|
575 return r; |
|
576 } |
|
577 |
|
578 |
|
579 |
|
580 CFileCB* TDrive::LocateFile(const TDesC& aName) |
|
581 // |
|
582 // Locate a file of the same name already open on the drive. |
|
583 // |
|
584 { |
|
585 TDblQueIter<CFileCB> q(CurrentMount().iMountQ); |
|
586 CFileCB* pF; |
|
587 // early out for normal case, list is empty |
|
588 if(q==NULL) |
|
589 return NULL; |
|
590 |
|
591 // strip off trailing dots |
|
592 TInt length= aName.Length(); |
|
593 while((length !=0) && (aName[length-1]==KExtDelimiter)) |
|
594 { |
|
595 length--; |
|
596 } |
|
597 |
|
598 TPtrC temp(aName.Ptr(),length); |
|
599 |
|
600 TFileName tempName; |
|
601 tempName.CopyF(temp); |
|
602 TUint32 nameHash=CalcNameHash(tempName); |
|
603 |
|
604 while ((pF=q++)!=NULL) |
|
605 { |
|
606 if(nameHash==pF->NameHash()) |
|
607 { |
|
608 if (pF->FileNameF().Match(tempName)==KErrNone) |
|
609 return(pF); |
|
610 } |
|
611 } |
|
612 return(NULL); |
|
613 } |
|
614 |
|
615 |
|
616 CFileCache* TDrive::LocateClosedFile(const TDesC& aName, TBool aResurrect) |
|
617 // |
|
618 // Locate a recently closed file of the same name on the drive. |
|
619 // |
|
620 { |
|
621 // strip off trailing dots |
|
622 TInt length= aName.Length(); |
|
623 while((length !=0) && (aName[length-1]==KExtDelimiter)) |
|
624 { |
|
625 length--; |
|
626 } |
|
627 |
|
628 TPtrC temp(aName.Ptr(),length); |
|
629 |
|
630 TFileName tempName; |
|
631 tempName.CopyF(temp); |
|
632 TUint32 nameHash=CalcNameHash(tempName); |
|
633 |
|
634 CFileCache* pF = NULL; |
|
635 CMountCB* currentMount = &CurrentMount(); |
|
636 |
|
637 |
|
638 TClosedFileUtils::Lock(); |
|
639 |
|
640 TInt count = TClosedFileUtils::Count(); |
|
641 while(count--) |
|
642 { |
|
643 CFileCache* fileCache = TClosedFileUtils::At(count); |
|
644 if (&fileCache->Drive() == this && |
|
645 fileCache->NameHash()== nameHash && |
|
646 fileCache->FileNameF().Match(tempName)==KErrNone && |
|
647 &fileCache->Mount() == currentMount) |
|
648 { |
|
649 __ASSERT_DEBUG(TClosedFileUtils::IsClosed(fileCache), Fault(EObjRemoveContainerNotFound)); |
|
650 __CACHE_PRINT2(_L("CLOSEDFILES: LocateClosedFile(%S, %d\n"), &fileCache->FileNameF(), aResurrect); |
|
651 if (aResurrect) |
|
652 { |
|
653 TClosedFileUtils::ReOpen(fileCache, EFalse); |
|
654 } |
|
655 pF = fileCache; |
|
656 break; |
|
657 } |
|
658 |
|
659 } |
|
660 TClosedFileUtils::Unlock(); |
|
661 |
|
662 if (pF != NULL && !aResurrect) |
|
663 { |
|
664 pF->Close(); |
|
665 pF = NULL; |
|
666 } |
|
667 |
|
668 return(pF); |
|
669 } |
|
670 |
|
671 |
|
672 static TBool IsSubDir(const TDesC& aFullName,const TDesC& aParent) |
|
673 // |
|
674 // Returns ETrue if aFullName is a subdirectory of aParent |
|
675 // Assumes aParent is a path name with the trailing backslash removed |
|
676 // |
|
677 { |
|
678 |
|
679 __ASSERT_DEBUG(aParent.Length() && aParent[aParent.Length()-1]!=KPathDelimiter,Fault(EIsSubDirBadDes)); |
|
680 TPtrC entryFullName(NULL,0); |
|
681 TPtrC entryParent(NULL,0); |
|
682 TInt posFullName=0; |
|
683 TInt posParent=0; |
|
684 |
|
685 FOREVER |
|
686 { |
|
687 NextInPath(aParent,entryParent,posParent); |
|
688 if (entryParent.Length()==0) |
|
689 break; |
|
690 NextInPath(aFullName,entryFullName,posFullName); |
|
691 if (entryParent!=entryFullName) |
|
692 return(EFalse); |
|
693 } |
|
694 |
|
695 if (aFullName.Length()<=posFullName) |
|
696 return(EFalse); |
|
697 if (aFullName[posFullName]!=KPathDelimiter) |
|
698 return(EFalse); |
|
699 return(ETrue); |
|
700 } |
|
701 |
|
702 CFileCB* TDrive::LocateFileByPath(const TDesC& aPath) |
|
703 // |
|
704 // Locate a file opened in a subdirectory of aPath |
|
705 // |
|
706 { |
|
707 |
|
708 TDblQueIter<CFileCB> q(CurrentMount().iMountQ); |
|
709 CFileCB* pF; |
|
710 while ((pF=q++)!=NULL) |
|
711 { |
|
712 if (IsSubDir(pF->FileName(),aPath)) |
|
713 return(pF); |
|
714 } |
|
715 return(NULL); |
|
716 } |
|
717 |
|
718 void TDrive::FlushCachedFileInfoL() |
|
719 // |
|
720 // Flush data stored in the file control blocks |
|
721 // |
|
722 { |
|
723 __CHECK_DRIVETHREAD(iDriveNumber); |
|
724 TDblQueIter<CFileCB> q(CurrentMount().iMountQ); |
|
725 CFileCB* pF; |
|
726 while ((pF=q++)!=NULL) |
|
727 { |
|
728 if (pF->iAtt&KEntryAttModified) |
|
729 pF->FlushAllL(); |
|
730 } |
|
731 } |
|
732 |
|
733 /** |
|
734 Flushes (asynchronously) all dirty data on this drive and optionally |
|
735 purges non-dirty data |
|
736 |
|
737 aPurgeCache - purges all file caches on this drive AFTER dirty data has ben flushed |
|
738 |
|
739 returns KErrNone if complete |
|
740 CFsRequest::EReqActionBusy if flushing is in progress |
|
741 otherwise one of the other system-wide error codes. |
|
742 */ |
|
743 TInt TDrive::FlushCachedFileInfo(TBool aPurgeCache) |
|
744 { |
|
745 if (iCurrentMount == NULL) |
|
746 return KErrNone; |
|
747 |
|
748 TBool driveThread = FsThreadManager::IsDriveThread(iDriveNumber,EFalse); |
|
749 |
|
750 Lock(); |
|
751 |
|
752 |
|
753 TInt ret = KErrNone; |
|
754 |
|
755 TDblQueIter<CFileCB> q(iCurrentMount->iMountQ); |
|
756 CFileCB* pF; |
|
757 while ((pF=q++)!=NULL) |
|
758 { |
|
759 CFileCache* fileCache = pF->FileCache(); |
|
760 |
|
761 // Write dirty data if there is a file cache |
|
762 TInt flushDirtyRetCode = CFsRequest::EReqActionComplete; |
|
763 if (fileCache) |
|
764 { |
|
765 flushDirtyRetCode = fileCache->FlushDirty(); |
|
766 if (flushDirtyRetCode == CFsRequest::EReqActionComplete) // nothing to flush |
|
767 { |
|
768 if (aPurgeCache) |
|
769 fileCache->Purge(EFalse); |
|
770 } |
|
771 else if (flushDirtyRetCode == CFsRequest::EReqActionBusy) // flushing |
|
772 { |
|
773 ret = flushDirtyRetCode; |
|
774 } |
|
775 else // error |
|
776 { |
|
777 ret = flushDirtyRetCode; |
|
778 break; |
|
779 } |
|
780 } |
|
781 // if no file cache or no dirty data left, update the file entry & attributes |
|
782 if (driveThread && (pF->iAtt&KEntryAttModified) && flushDirtyRetCode == CFsRequest::EReqActionComplete ) |
|
783 { |
|
784 TRAP(ret, pF->FlushAllL()); |
|
785 if (ret != KErrNone) |
|
786 break; |
|
787 } |
|
788 } |
|
789 |
|
790 UnLock(); |
|
791 |
|
792 |
|
793 return ret; |
|
794 } |
|
795 |
|
796 //---------------------------------------------------------------------------- |
|
797 /** |
|
798 Purge dirty cache data associated with all files on a given mount |
|
799 */ |
|
800 void TDrive::PurgeDirty(CMountCB& aMount) |
|
801 { |
|
802 TDblQueIter<CFileCB> q(aMount.iMountQ); |
|
803 CFileCB* pF; |
|
804 while ((pF=q++)!=NULL) |
|
805 { |
|
806 CFileCache* fileCache = pF->FileCache(); |
|
807 if (fileCache) |
|
808 { |
|
809 fileCache->Purge(ETrue); |
|
810 fileCache->MarkFileClean(); |
|
811 } |
|
812 } |
|
813 } |
|
814 |
|
815 //---------------------------------------------------------------------------- |
|
816 TInt TDrive::ValidateShare(CFileCB& aFile, TShare aReqShare) |
|
817 // |
|
818 // Check that the sharing rules are obeyed. |
|
819 // |
|
820 { |
|
821 |
|
822 switch (aReqShare) |
|
823 { |
|
824 case EFileShareExclusive: |
|
825 case EFileShareReadersOnly: |
|
826 case EFileShareAny: |
|
827 case EFileShareReadersOrWriters: |
|
828 break; |
|
829 default: |
|
830 return(KErrArgument); |
|
831 } |
|
832 switch (aFile.iShare) |
|
833 { |
|
834 case EFileShareExclusive: |
|
835 return(KErrInUse); |
|
836 |
|
837 case EFileShareReadersOnly: |
|
838 case EFileShareAny: |
|
839 if (aReqShare != aFile.iShare && aReqShare != EFileShareReadersOrWriters) |
|
840 return(KErrInUse); |
|
841 break; |
|
842 |
|
843 case EFileShareReadersOrWriters: |
|
844 if (aReqShare==EFileShareExclusive) |
|
845 return(KErrInUse); |
|
846 // |
|
847 // If the file is currently open as EFileShareReadersOrWriters then |
|
848 // promote the share to the requested share mode. |
|
849 // |
|
850 // If the requested share is EFileShareReadersOnly, verfiy that no |
|
851 // other share has the file open for writing. |
|
852 // |
|
853 |
|
854 if (aReqShare == EFileShareReadersOnly) |
|
855 { |
|
856 FileShares->Lock(); |
|
857 TInt count = FileShares->Count(); |
|
858 while(count--) |
|
859 { |
|
860 CFileShare* share = (CFileShare*)(*FileShares)[count]; |
|
861 if (&share->File() == &aFile) |
|
862 { |
|
863 if(share->iMode & EFileWrite) |
|
864 { |
|
865 FileShares->Unlock(); |
|
866 return KErrInUse; |
|
867 } |
|
868 } |
|
869 } |
|
870 FileShares->Unlock(); |
|
871 } |
|
872 break; |
|
873 |
|
874 default: |
|
875 Fault(EDrvIllegalShareValue); |
|
876 break; |
|
877 } |
|
878 return(KErrNone); |
|
879 } |
|
880 |
|
881 void TDrive::DriveInfo(TDriveInfo& anInfo) |
|
882 // |
|
883 // Get the drive info. |
|
884 // |
|
885 { |
|
886 anInfo.iType=EMediaNotPresent; |
|
887 anInfo.iMediaAtt=0; |
|
888 |
|
889 TInt batStatus=HAL::EPowerBatteryStatus_Zero; |
|
890 TInt r=HAL::Get(HAL::EPowerBatteryStatus, batStatus); |
|
891 if (r==KErrNone) |
|
892 { |
|
893 switch(batStatus) |
|
894 { |
|
895 case HAL::EPowerBatteryStatus_Zero: |
|
896 anInfo.iBattery=EBatLow; |
|
897 break; |
|
898 case HAL::EPowerBatteryStatus_Replace: |
|
899 anInfo.iBattery=EBatLow; |
|
900 break; |
|
901 case HAL::EPowerBatteryStatus_Low: |
|
902 anInfo.iBattery=EBatLow; |
|
903 break; |
|
904 case HAL::EPowerBatteryStatus_Good: |
|
905 anInfo.iBattery=EBatGood; |
|
906 break; |
|
907 } |
|
908 } |
|
909 else |
|
910 anInfo.iBattery=EBatNotSupported; |
|
911 |
|
912 if(iFSys) |
|
913 { |
|
914 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemDriveInfo, EF32TraceUidFileSys, &FSys(), DriveNumber()); |
|
915 FSys().DriveInfo(anInfo,DriveNumber()); |
|
916 TRACE3(UTF::EBorder, UTraceModuleFileSys::ECFileSystemDriveInfoRet, EF32TraceUidFileSys, |
|
917 anInfo.iType, anInfo.iDriveAtt, anInfo.iMediaAtt); |
|
918 } |
|
919 |
|
920 anInfo.iDriveAtt=Att(); |
|
921 } |
|
922 |
|
923 TInt TDrive::Volume(TVolumeInfo& aVolume) |
|
924 // |
|
925 // Get the drive volume info. |
|
926 // |
|
927 { |
|
928 TInt r=CheckMount(); |
|
929 if (r==KErrNone) |
|
930 { |
|
931 DriveInfo(aVolume.iDrive); |
|
932 CMountCB& m=CurrentMount(); |
|
933 aVolume.iName=m.VolumeName(); |
|
934 aVolume.iUniqueID=m.iUniqueID; |
|
935 aVolume.iSize=m.iSize; |
|
936 |
|
937 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBVolumeL, EF32TraceUidFileSys, DriveNumber()); |
|
938 TRAP(r,m.VolumeL(aVolume)) |
|
939 TRACE7(UTF::EBorder, UTraceModuleFileSys::ECMountCBVolumeLRet, EF32TraceUidFileSys, |
|
940 r, aVolume.iUniqueID, I64LOW(aVolume.iSize), I64HIGH(aVolume.iSize), |
|
941 I64LOW(aVolume.iFree), I64HIGH(aVolume.iFree), aVolume.iFileCacheFlags); |
|
942 |
|
943 } |
|
944 return(r); |
|
945 } |
|
946 |
|
947 |
|
948 void TDrive::SetVolumeL(const TDesC& aName,HBufC*& aBuf) |
|
949 // |
|
950 // Set the volume name. |
|
951 // |
|
952 { |
|
953 __CHECK_DRIVETHREAD(iDriveNumber); |
|
954 aBuf=aName.AllocL(); |
|
955 TPtr volumeName=aBuf->Des(); |
|
956 |
|
957 TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBSetVolumeL, EF32TraceUidFileSys, DriveNumber(), aName); |
|
958 CurrentMount().SetVolumeL(volumeName); |
|
959 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBSetVolumeLRet, EF32TraceUidFileSys, KErrNone); |
|
960 |
|
961 |
|
962 delete &CurrentMount().VolumeName(); |
|
963 CurrentMount().SetVolumeName(aBuf); |
|
964 } |
|
965 |
|
966 TInt TDrive::SetVolume(const TDesC& aName) |
|
967 // |
|
968 // Set the volume name. |
|
969 // |
|
970 { |
|
971 TInt r=CheckMount(); |
|
972 HBufC* pV=NULL; |
|
973 if (r==KErrNone) |
|
974 { |
|
975 if(IsWriteProtected()) |
|
976 return(KErrAccessDenied); |
|
977 TRAP(r,SetVolumeL(aName,pV)) |
|
978 if (r!=KErrNone) |
|
979 delete pV; |
|
980 } |
|
981 return(r); |
|
982 } |
|
983 |
|
984 TInt TDrive::MkDir(const TDesC& aName) |
|
985 // |
|
986 // Make a directory. |
|
987 // |
|
988 { |
|
989 TInt r=CheckMount(); |
|
990 if (r!=KErrNone) |
|
991 return(r); |
|
992 if(IsWriteProtected()) |
|
993 return(KErrAccessDenied); |
|
994 TParse newDirName; |
|
995 newDirName.Set(aName,NULL,NULL); |
|
996 |
|
997 TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBMkDirL, EF32TraceUidFileSys, DriveNumber(), aName); |
|
998 TRAP(r,CurrentMount().MkDirL(newDirName.FullName())) |
|
999 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBMkDirLRet, EF32TraceUidFileSys, r); |
|
1000 |
|
1001 return(r); |
|
1002 } |
|
1003 |
|
1004 TInt TDrive::RmDir(const TDesC& aName) |
|
1005 // |
|
1006 // Remove a directory. |
|
1007 // |
|
1008 { |
|
1009 TInt r=CheckMount(); |
|
1010 if (r!=KErrNone) |
|
1011 return(r); |
|
1012 TEntry entry; |
|
1013 r=Entry(aName,entry); |
|
1014 if (r!=KErrNone) |
|
1015 return(r); |
|
1016 if (entry.IsDir()==EFalse) |
|
1017 return(KErrPathNotFound); |
|
1018 if ((entry.iAtt&KEntryAttReadOnly) || IsWriteProtected()) |
|
1019 return(KErrAccessDenied); |
|
1020 |
|
1021 TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBRmDirL, EF32TraceUidFileSys, DriveNumber(), aName); |
|
1022 TRAP(r,CurrentMount().RmDirL(aName)) |
|
1023 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBRmDirLRet, EF32TraceUidFileSys, r); |
|
1024 |
|
1025 return(r); |
|
1026 } |
|
1027 |
|
1028 TInt TDrive::Delete(const TDesC& aName) |
|
1029 // |
|
1030 // Delete files allowing wild cards. |
|
1031 // |
|
1032 { |
|
1033 TInt r=CheckMountAndEntryName(aName); |
|
1034 if (r!=KErrNone) |
|
1035 return(r); |
|
1036 CFileCB* pF=LocateFile(aName); |
|
1037 if (pF!=NULL) |
|
1038 return(KErrInUse); |
|
1039 |
|
1040 // remove from closed queue - NB this isn't strictly necessary if file is read-only or write-protected... |
|
1041 LocateClosedFile(aName, EFalse); |
|
1042 |
|
1043 TEntry entry; |
|
1044 r=Entry(aName,entry); |
|
1045 if (r!=KErrNone) |
|
1046 return(r); |
|
1047 if (entry.IsDir() || IsWriteProtected() || entry.IsReadOnly()) |
|
1048 return(KErrAccessDenied); |
|
1049 |
|
1050 TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBDeleteL, EF32TraceUidFileSys, DriveNumber(), aName); |
|
1051 TRAP(r,CurrentMount().DeleteL(aName)) |
|
1052 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBDeleteLRet, EF32TraceUidFileSys, r); |
|
1053 |
|
1054 return(r); |
|
1055 } |
|
1056 |
|
1057 TInt TDrive::CheckMountAndEntryNames(const TDesC& anOldName,const TDesC& aNewName) |
|
1058 // |
|
1059 // Check mount, that neither is open, and that both names are legal. |
|
1060 // |
|
1061 { |
|
1062 |
|
1063 TInt r=CheckMountAndEntryName(anOldName); |
|
1064 if (r!=KErrNone) |
|
1065 return(r); |
|
1066 if (IsIllegalFullName(aNewName)) |
|
1067 return(KErrBadName); |
|
1068 return(KErrNone); |
|
1069 } |
|
1070 |
|
1071 TInt TDrive::CheckDirectories(const TDesC& anOldName,const TDesC& aNewName) |
|
1072 // |
|
1073 // Return KErrAlreadyExists if aNewName exists and |
|
1074 // KErrAccessDenied if anOldName is a directory being moved to a subdirectory of itself |
|
1075 // |
|
1076 { |
|
1077 |
|
1078 TEntry entry; |
|
1079 TInt r=Entry(anOldName,entry); |
|
1080 if (r!=KErrNone) |
|
1081 return(r); |
|
1082 if (entry.IsDir()) |
|
1083 { |
|
1084 //-- check the length of the destination directory name. It shall not exceed 253 characters. |
|
1085 //-- aNewName looks like "\\dir1" i.e. drive letter and ':' is removed from the name and there is no trailing '\\' in this case. |
|
1086 |
|
1087 const TInt maxDirNameLength = KMaxFileName - 3; |
|
1088 if(aNewName.Length() > maxDirNameLength) |
|
1089 return KErrBadName; |
|
1090 if(IsSubDir(aNewName,anOldName)) |
|
1091 return(KErrInUse); // rename into a subdir of itself |
|
1092 if (LocateFileByPath(anOldName)) |
|
1093 return(KErrInUse); // a file inside anOldName is open |
|
1094 } |
|
1095 else if (LocateFile(anOldName)) |
|
1096 return(KErrInUse); |
|
1097 |
|
1098 r=Entry(aNewName,entry); |
|
1099 if (r!=KErrNone && r!=KErrNotFound) |
|
1100 return(r); |
|
1101 return(KErrNone); |
|
1102 } |
|
1103 |
|
1104 TInt TDrive::Rename(const TDesC& anOldName,const TDesC& aNewName) |
|
1105 // |
|
1106 // Rename files or directories. No wild cards. |
|
1107 // |
|
1108 { |
|
1109 __CHECK_DRIVETHREAD(iDriveNumber); |
|
1110 TInt r=CheckMountAndEntryNames(anOldName,aNewName); |
|
1111 if (r!=KErrNone) |
|
1112 return(r); |
|
1113 TPtrC oldEntryName(StripBackSlash(anOldName)); |
|
1114 TPtrC newEntryName(StripBackSlash(aNewName)); |
|
1115 r=CheckDirectories(oldEntryName,newEntryName); |
|
1116 if (r!=KErrNone) |
|
1117 return(r); |
|
1118 if(IsWriteProtected()) |
|
1119 return(KErrAccessDenied); |
|
1120 |
|
1121 // remove from closed queue |
|
1122 LocateClosedFile(anOldName, EFalse); |
|
1123 LocateClosedFile(aNewName, EFalse); |
|
1124 |
|
1125 TRACEMULT3(UTF::EBorder, UTraceModuleFileSys::ECMountCBRenameL, EF32TraceUidFileSys, DriveNumber(), oldEntryName,newEntryName); |
|
1126 TRAP(r,CurrentMount().RenameL(oldEntryName,newEntryName)) |
|
1127 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBRenameLRet, EF32TraceUidFileSys, r); |
|
1128 |
|
1129 return(r); |
|
1130 } |
|
1131 |
|
1132 TInt TDrive::Replace(const TDesC& anOldName,const TDesC& aNewName) |
|
1133 // |
|
1134 // Replace anOldName with aNewName atomically. No wild cards. No directories |
|
1135 // |
|
1136 { |
|
1137 TInt r=CheckMountAndEntryNames(anOldName,aNewName); |
|
1138 if (r!=KErrNone) |
|
1139 return(r); |
|
1140 TEntry entry; |
|
1141 r=Entry(aNewName,entry); |
|
1142 if (r!=KErrNotFound) |
|
1143 { |
|
1144 if (r!=KErrNone) |
|
1145 return(r); |
|
1146 if (entry.IsDir() || entry.IsReadOnly()) |
|
1147 return(KErrAccessDenied); |
|
1148 if (LocateFile(aNewName)) |
|
1149 return(KErrInUse); |
|
1150 } |
|
1151 r=Entry(anOldName,entry); |
|
1152 if (r!=KErrNone) |
|
1153 return(r); |
|
1154 if (entry.IsDir() || IsWriteProtected()) |
|
1155 return(KErrAccessDenied); |
|
1156 if (LocateFile(anOldName)) |
|
1157 return(KErrInUse); |
|
1158 |
|
1159 // remove from closed queue |
|
1160 LocateClosedFile(anOldName, EFalse); |
|
1161 LocateClosedFile(aNewName, EFalse); |
|
1162 |
|
1163 TRACEMULT3(UTF::EBorder, UTraceModuleFileSys::ECMountCBReplaceL, EF32TraceUidFileSys, DriveNumber(), anOldName, aNewName); |
|
1164 TRAP(r,CurrentMount().ReplaceL(anOldName,aNewName)) |
|
1165 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBReplaceLRet, EF32TraceUidFileSys, r); |
|
1166 |
|
1167 return(r); |
|
1168 } |
|
1169 |
|
1170 TInt TDrive::Entry(const TDesC& aName,TEntry& anEntry) |
|
1171 // |
|
1172 // Get the entry details. |
|
1173 // |
|
1174 { |
|
1175 __CHECK_DRIVETHREAD(iDriveNumber); |
|
1176 TInt r=CheckMountAndEntryName(aName); |
|
1177 if (r!=KErrNone) |
|
1178 return(r); |
|
1179 TPtrC entryName(StripBackSlash(aName)); |
|
1180 TRAP(r,DoEntryL(entryName,anEntry)); |
|
1181 |
|
1182 if (r==KErrHidden) |
|
1183 r=KErrNotFound; |
|
1184 else if (r==KErrPathHidden) |
|
1185 r=KErrPathNotFound; |
|
1186 |
|
1187 return(r); |
|
1188 } |
|
1189 |
|
1190 void TDrive::DoEntryL(const TDesC& aName, TEntry& anEntry) |
|
1191 // |
|
1192 // Get entry details |
|
1193 // |
|
1194 { |
|
1195 FlushCachedFileInfoL(); |
|
1196 |
|
1197 TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBEntryL, EF32TraceUidFileSys, DriveNumber(), aName); |
|
1198 CurrentMount().EntryL(aName,anEntry); |
|
1199 TRACE5(UTF::EBorder, UTraceModuleFileSys::ECMountCBEntryLRet, EF32TraceUidFileSys, |
|
1200 KErrNone, anEntry.iAtt, |
|
1201 I64LOW(anEntry.iModified.Int64()), I64HIGH(anEntry.iModified.Int64()), |
|
1202 anEntry.iSize); |
|
1203 |
|
1204 } |
|
1205 |
|
1206 TInt TDrive::CheckAttributes(const TDesC& aName,TUint& aSetAttMask,TUint& aClearAttMask) |
|
1207 // |
|
1208 // Validate the changes against the current entry attributes |
|
1209 // |
|
1210 { |
|
1211 |
|
1212 TEntry entry; |
|
1213 TRAPD(r,DoEntryL(aName,entry)); |
|
1214 if (r!=KErrNone) |
|
1215 return(r); |
|
1216 ValidateAtts(entry.iAtt,aSetAttMask,aClearAttMask); |
|
1217 return(KErrNone); |
|
1218 } |
|
1219 |
|
1220 TInt TDrive::SetEntry(const TDesC& aName,const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask) |
|
1221 // |
|
1222 // Set the entry details. |
|
1223 // |
|
1224 { |
|
1225 __CHECK_DRIVETHREAD(iDriveNumber); |
|
1226 TInt r=CheckMountAndEntryName(aName); |
|
1227 if (r!=KErrNone) |
|
1228 return(r); |
|
1229 TPtrC entryName(StripBackSlash(aName)); |
|
1230 CFileCB* pF=LocateFile(entryName); |
|
1231 if (pF!=NULL) |
|
1232 return(KErrInUse); |
|
1233 r=CheckAttributes(entryName,aSetAttMask,aClearAttMask); |
|
1234 if (r!=KErrNone) |
|
1235 return(r); |
|
1236 if (IsWriteProtected()) |
|
1237 return(KErrAccessDenied); |
|
1238 TTime nullTime(0); |
|
1239 if (aTime!=nullTime) |
|
1240 aSetAttMask|=KEntryAttModified; |
|
1241 |
|
1242 TRACEMULT6(UTF::EBorder, UTraceModuleFileSys::ECMountCBSetEntryL, EF32TraceUidFileSys, |
|
1243 DriveNumber(), aName, I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()), aSetAttMask, aClearAttMask); |
|
1244 TRAP(r,CurrentMount().SetEntryL(entryName,aTime,aSetAttMask,aClearAttMask)) |
|
1245 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBSetEntryLRet, EF32TraceUidFileSys, r); |
|
1246 |
|
1247 return(r); |
|
1248 } |
|
1249 |
|
1250 TInt TDrive::FileTemp(CFsRequest* aRequest,TInt& aHandle,const TDesC& aPath,TDes& aName,TUint aMode) |
|
1251 // |
|
1252 // Create a temporary file and return the file name. |
|
1253 // |
|
1254 { |
|
1255 __CHECK_DRIVETHREAD(iDriveNumber); |
|
1256 aName=aPath; |
|
1257 TInt len=aName.Length(); |
|
1258 TInt t=User::TickCount()&0xfffff; |
|
1259 aMode|=EFileWrite; |
|
1260 for (TInt retry=0;retry<KMaxTempNameAttempts;retry++) |
|
1261 { |
|
1262 aName.SetLength(len); |
|
1263 aName.AppendFormat(_L("TMP%05x.$$$"),t); |
|
1264 TEntry e; |
|
1265 TInt r=Entry(aName,e); |
|
1266 if (r!=KErrNone) |
|
1267 { |
|
1268 if (r!=KErrNotFound) |
|
1269 return(r); |
|
1270 return(FileOpen(aRequest,aHandle,aName,aMode,EFileCreate)); |
|
1271 } |
|
1272 t=((t|1)*13)&0xfffff; |
|
1273 } |
|
1274 return(KErrGeneral); |
|
1275 } |
|
1276 |
|
1277 LOCAL_C HBufC* CreateFileNameL(const TDesC& aName) |
|
1278 // |
|
1279 // Create a HBufC from aName |
|
1280 // Converts _L("\\F32.\\GROUP\\release.") to _L("\\F32\\GROUP\\release") |
|
1281 // |
|
1282 { |
|
1283 |
|
1284 TParsePtrC name(aName); |
|
1285 TFileName fileName; |
|
1286 fileName.Append(KPathDelimiter); |
|
1287 |
|
1288 if (name.Path().Length()) |
|
1289 { |
|
1290 TInt pos=0; |
|
1291 TPtrC entry(NULL,0); |
|
1292 FOREVER |
|
1293 { |
|
1294 NextInPath(name.Path(),entry,pos); |
|
1295 if (entry.Length()==0) |
|
1296 break; |
|
1297 fileName.Append(entry); |
|
1298 fileName.Append(KPathDelimiter); |
|
1299 } |
|
1300 } |
|
1301 |
|
1302 fileName.Append(name.Name()); |
|
1303 if (name.Ext().Length()>1) |
|
1304 fileName.Append(name.Ext()); |
|
1305 return(fileName.AllocL()); |
|
1306 } |
|
1307 |
|
1308 void TDrive::FileOpenL(CFsRequest* aRequest,TInt& aHandle,const TDesC& aName,TUint aMode,TFileOpen anOpen,CFileCB*& aFileCB,CFileShare*& aFileShare) |
|
1309 // |
|
1310 // Open/Create/Replace a file. |
|
1311 // |
|
1312 { |
|
1313 aFileCB=NULL; |
|
1314 aFileShare=NULL; |
|
1315 TInt r = CheckMount(); |
|
1316 if (r!=KErrNone) |
|
1317 User::Leave(r); |
|
1318 |
|
1319 if (IsIllegalFullName(aRequest->Src())) |
|
1320 User::Leave(KErrBadName); |
|
1321 |
|
1322 if (CurrentMount().Locked()) |
|
1323 User::Leave(KErrInUse); |
|
1324 |
|
1325 if ((aMode & EFileWrite) != 0) |
|
1326 { |
|
1327 TDriveInfo driveInfo; |
|
1328 DriveInfo(driveInfo); |
|
1329 if (driveInfo.iType==EMediaRom || (driveInfo.iMediaAtt&KMediaAttWriteProtected)!=0) |
|
1330 User::Leave(KErrAccessDenied); |
|
1331 } |
|
1332 |
|
1333 TShare share=(TShare)(aMode&KFileShareMask); |
|
1334 if (share==EFileShareReadersOnly && (aMode&EFileWrite)!=0) |
|
1335 User::Leave(KErrArgument); |
|
1336 |
|
1337 if (aMode & EFileReadAsyncAll) |
|
1338 { |
|
1339 // Async read all mode is not compatible with EFileShareExclusive or EFileShareReadersOnly, |
|
1340 // as these modes prevent a writer from accessing the file and completing the request. |
|
1341 if(share == EFileShareExclusive || share == EFileShareReadersOnly) |
|
1342 User::Leave(KErrArgument); |
|
1343 } |
|
1344 |
|
1345 // check for silly cache on / off combinations |
|
1346 const TUint KBadWriteMode = EFileWriteBuffered | EFileWriteDirectIO; |
|
1347 const TUint KBadReadMode = EFileReadBuffered | EFileReadDirectIO; |
|
1348 const TUint KBadReadAheadMode = EFileReadAheadOn | EFileReadAheadOff; |
|
1349 const TUint KBadReadAheadMode2 = EFileReadDirectIO | EFileReadAheadOn; |
|
1350 if (((aMode & KBadWriteMode) == KBadWriteMode) || |
|
1351 ((aMode & KBadReadMode) == KBadReadMode) || |
|
1352 ((aMode & KBadReadAheadMode) == KBadReadAheadMode) || |
|
1353 ((aMode & KBadReadAheadMode2) == KBadReadAheadMode2)) |
|
1354 { |
|
1355 User::Leave(KErrArgument); |
|
1356 } |
|
1357 |
|
1358 // Only allow delete on close for a newly created file. |
|
1359 if ((aMode & EDeleteOnClose) && (anOpen!=EFileCreate)) |
|
1360 User::Leave(KErrArgument); |
|
1361 |
|
1362 CFileCB* pF=LocateFile(aName); |
|
1363 CFileCache* pFileCache = NULL; |
|
1364 TBool openFile=EFalse; |
|
1365 if (pF!=NULL) |
|
1366 { |
|
1367 if (pF->iShare==EFileShareReadersOnly && (aMode&EFileWrite)!=0) |
|
1368 User::Leave(KErrInUse); |
|
1369 if (anOpen==EFileCreate) |
|
1370 User::Leave(KErrAlreadyExists); |
|
1371 TInt r=ValidateShare(*pF,share); |
|
1372 if (r!=KErrNone) |
|
1373 User::Leave(r); |
|
1374 if ((r=pF->Open())!=KErrNone) |
|
1375 User::Leave(r); |
|
1376 aFileCB=pF; |
|
1377 pFileCache = pF->FileCache(); |
|
1378 } |
|
1379 else |
|
1380 { |
|
1381 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewFileL, EF32TraceUidFileSys, &FSys(), DriveNumber()); |
|
1382 |
|
1383 //-- construct CFileCB object, belonging to the corresponding mount |
|
1384 pF = aFileCB = CurrentMount().NewFileL(); |
|
1385 |
|
1386 TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewFileLRet, EF32TraceUidFileSys, r, pF); |
|
1387 TDrive* createdDrive=!aRequest->SubstedDrive() ? this : aRequest->SubstedDrive(); |
|
1388 |
|
1389 HBufC* fileName = CreateFileNameL(aName); |
|
1390 |
|
1391 pF->InitL(this, createdDrive, fileName); |
|
1392 |
|
1393 |
|
1394 pF->iShare = share; |
|
1395 openFile=ETrue; |
|
1396 CurrentMount().iMountQ.AddLast(*pF); |
|
1397 Files->AddL(pF,ETrue); |
|
1398 } |
|
1399 |
|
1400 CFileShare* pS=aFileShare=new(ELeave) CFileShare(pF); |
|
1401 |
|
1402 // We need to call CFileCB::PromoteShare immediately after the CFileShare |
|
1403 // instance is created since the destructor calls CFileCB::DemoteShare() |
|
1404 // which checks the share count is non-zero |
|
1405 pS->iMode=aMode; |
|
1406 pF->PromoteShare(pS); |
|
1407 |
|
1408 pS->InitL(); |
|
1409 aFileCB=NULL; |
|
1410 FileShares->AddL(pS,ETrue); |
|
1411 aHandle=aRequest->Session()->Handles().AddL(pS,ETrue); |
|
1412 |
|
1413 |
|
1414 if (openFile) |
|
1415 { |
|
1416 TRACEMULT5(UTF::EBorder, UTraceModuleFileSys::ECMountCBFileOpenL, EF32TraceUidFileSys, DriveNumber(), aName, aMode, (TUint) anOpen, (TUint) pF); |
|
1417 CurrentMount().FileOpenL(aName,aMode,anOpen,pF); |
|
1418 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBFileOpenLRet, EF32TraceUidFileSys, KErrNone); |
|
1419 |
|
1420 // Delete on close may now be safely flagged if required. |
|
1421 // The file did not exist on the media prior to the |
|
1422 // CMountCB::FileOpenL() call for the case of a create. |
|
1423 if ((aMode & EDeleteOnClose) && (anOpen==EFileCreate)) |
|
1424 pF->SetDeleteOnClose(); |
|
1425 |
|
1426 TBool localBufferSuppport = (CurrentMount().LocalBufferSupport(pF) == KErrNone)?(TBool)ETrue:(TBool)EFalse; |
|
1427 pF->SetLocalBufferSupport(localBufferSuppport); |
|
1428 if (localBufferSuppport) |
|
1429 { |
|
1430 // if file exists on closed queue resurrect it or discard it, |
|
1431 // depending on the file open mode |
|
1432 pFileCache = LocateClosedFile(aName, anOpen == EFileOpen?(TBool)ETrue:(TBool)EFalse); |
|
1433 if (pFileCache) |
|
1434 { |
|
1435 pFileCache = pFileCache->ReNewL(*pS); // NB may return NULL if caching not enabled |
|
1436 } |
|
1437 else |
|
1438 { |
|
1439 pFileCache = CFileCache::NewL(*pS); // NB may return NULL if caching not enabled |
|
1440 } |
|
1441 if (pFileCache) |
|
1442 // set the cached size to be the same as the uncached size |
|
1443 pF->SetCachedSize64(pF->Size64()); |
|
1444 } |
|
1445 else |
|
1446 { |
|
1447 __CACHE_PRINT(_L("TDrive::FileOpenL(), Local buffers not supported")); |
|
1448 } |
|
1449 } |
|
1450 |
|
1451 // initialize share mode flags |
|
1452 if (pFileCache != NULL) |
|
1453 pFileCache->Init(*pS); |
|
1454 } |
|
1455 |
|
1456 TInt TDrive::FileOpen(CFsRequest* aRequest,TInt& aHandle,const TDesC& aName,TUint aMode,TFileOpen anOpen) |
|
1457 // |
|
1458 // Open/Create/Replace a file. |
|
1459 // |
|
1460 { |
|
1461 __CHECK_DRIVETHREAD(iDriveNumber); |
|
1462 CFileCB* pF=NULL; |
|
1463 CFileShare* pS=NULL; |
|
1464 aHandle=0; |
|
1465 TRAPD(r,FileOpenL(aRequest,aHandle,aName,aMode,anOpen,pF,pS)) |
|
1466 |
|
1467 // Allow files > 2GB-1 to be opened only if EFileBigFile is specified in iMode |
|
1468 if (r == KErrNone && pS && ((TUint64)pS->File().Size64() > KMaxLegacyFileSize) && (!(pS->IsFileModeBig()))) |
|
1469 r = KErrTooBig; |
|
1470 |
|
1471 if (r!=KErrNone) |
|
1472 { |
|
1473 if (r==KErrHidden) |
|
1474 r=KErrNotFound; |
|
1475 else if (r==KErrPathHidden) |
|
1476 r=KErrPathNotFound; |
|
1477 |
|
1478 if(pF && !pS) |
|
1479 pF->Close(); |
|
1480 CheckSubClose(pS,aHandle,aRequest->Session()); |
|
1481 } |
|
1482 return(r); |
|
1483 } |
|
1484 |
|
1485 void TDrive::DirOpenL(CSessionFs* aSession,TInt& aHandle,const TDesC& aName,TUint anAtt,const TUidType& aUidType,CDirCB*& aDir) |
|
1486 // |
|
1487 // Open a directory listing. Leave on error. |
|
1488 // |
|
1489 { |
|
1490 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewDirL, EF32TraceUidFileSys, &FSys(), DriveNumber()); |
|
1491 |
|
1492 CDirCB* pD = aDir = CurrentMount().NewDirL(); //-- construct CDirCB object, belonging to the corresponding mount |
|
1493 |
|
1494 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewDirLRet, EF32TraceUidFileSys, KErrNone, pD); |
|
1495 pD->InitL(this); |
|
1496 // modify resource counter after initialisation to ensure correct cleanup |
|
1497 AddResource(CurrentMount()); |
|
1498 pD->iAtt=anAtt; |
|
1499 pD->iUidType=aUidType; |
|
1500 Dirs->AddL(pD,ETrue); |
|
1501 aHandle=aSession->Handles().AddL(pD,ETrue); |
|
1502 |
|
1503 TRACEMULT3(UTF::EBorder, UTraceModuleFileSys::ECMountCBDirOpenL, EF32TraceUidFileSys, DriveNumber(), aName, (TUint) pD); |
|
1504 CurrentMount().DirOpenL(aName,pD); |
|
1505 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBDirOpenLRet, EF32TraceUidFileSys, KErrNone); |
|
1506 } |
|
1507 |
|
1508 TInt TDrive::DirOpen(CSessionFs* aSession,TInt& aHandle,const TDesC& aName,TUint anAtt,const TUidType& aUidType) |
|
1509 // |
|
1510 // Open a directory listing. |
|
1511 // |
|
1512 { |
|
1513 TInt r=CheckMountAndEntryName(aName); |
|
1514 if (r!=KErrNone) |
|
1515 return(r); |
|
1516 if (CurrentMount().Locked()) |
|
1517 return(KErrInUse); |
|
1518 CDirCB* pD=NULL; |
|
1519 aHandle=0; |
|
1520 TRAP(r,DirOpenL(aSession,aHandle,aName,anAtt,aUidType,pD)); |
|
1521 |
|
1522 if (r==KErrHidden) |
|
1523 r=KErrNotFound; |
|
1524 else if (r==KErrPathHidden) |
|
1525 r=KErrPathNotFound; |
|
1526 |
|
1527 if (r!=KErrNone) |
|
1528 CheckSubClose(pD,aHandle,aSession); |
|
1529 return(r); |
|
1530 } |
|
1531 |
|
1532 |
|
1533 TInt TDrive::ReadFileSection(const TDesC& aName,TInt aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage) |
|
1534 // |
|
1535 // Starting from aPos, read aLength bytes of a file into a Trg, |
|
1536 // regardless of lock state |
|
1537 // |
|
1538 { |
|
1539 return ReadFileSection64(aName, aPos, aTrg, aLength, aMessage); |
|
1540 } |
|
1541 |
|
1542 |
|
1543 TInt TDrive::ReadFileSection64(const TDesC& aName,TInt64 aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage) |
|
1544 // |
|
1545 // Starting from aPos, read aLength bytes of a file into a Trg, |
|
1546 // regardless of lock state |
|
1547 // |
|
1548 { |
|
1549 |
|
1550 // flush dirty data if already open |
|
1551 CFileCB* file; |
|
1552 IsFileOpen(aName, file); |
|
1553 if (file && file->FileCache()) |
|
1554 { |
|
1555 if (file->FileCache()->FlushDirty() == CFsRequest::EReqActionBusy) |
|
1556 return CFsRequest::EReqActionBusy; |
|
1557 } |
|
1558 |
|
1559 __PRINT(_L("TDrive::ReadSection")); |
|
1560 TInt r=CheckMountAndEntryName(aName); |
|
1561 if (r!=KErrNone) |
|
1562 return(r); |
|
1563 TPtrC entryName(StripBackSlash(aName)); |
|
1564 |
|
1565 TRACETHREADID(aMessage); |
|
1566 TRACEMULT7(UTF::EBorder, UTraceModuleFileSys::ECMountCBReadFileSectionL, EF32TraceUidFileSys, |
|
1567 DriveNumber(), aName, I64LOW(aPos), I64HIGH(aPos), (TUint) aTrg, aLength, I64LOW(threadId)); |
|
1568 TRAP(r,ReadSectionL(entryName,aPos,aTrg,aLength,aMessage)); |
|
1569 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBReadFileSectionLRet, EF32TraceUidFileSys, r); |
|
1570 |
|
1571 if (r==KErrHidden) |
|
1572 r=KErrNotFound; |
|
1573 else if (r==KErrPathHidden) |
|
1574 r=KErrPathNotFound; |
|
1575 |
|
1576 return(r); |
|
1577 } |
|
1578 |
|
1579 |
|
1580 void TDrive::ReadSectionL(const TDesC& aName,TInt64 aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage) |
|
1581 // |
|
1582 // Starting from aPos, read aLength bytes of a file into a Trg, |
|
1583 // regardless of lock state |
|
1584 // |
|
1585 { |
|
1586 __PRINT(_L("TDrive::ReadSectionL")); |
|
1587 |
|
1588 FlushCachedFileInfoL(); |
|
1589 CurrentMount().ReadSection64L(aName,aPos,aTrg,aLength,aMessage); |
|
1590 } |
|
1591 |
|
1592 /** |
|
1593 Check the disk's integrity |
|
1594 */ |
|
1595 TInt TDrive::CheckDisk() |
|
1596 { |
|
1597 TInt r=CheckMount(); |
|
1598 if (r==KErrNone) |
|
1599 TRAP(r,FlushCachedFileInfoL()); |
|
1600 if (r==KErrNone) |
|
1601 { |
|
1602 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBCheckDisk1, EF32TraceUidFileSys, DriveNumber()); |
|
1603 r=CurrentMount().CheckDisk(); |
|
1604 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBCheckDisk1Ret, EF32TraceUidFileSys, r); |
|
1605 } |
|
1606 return(r); |
|
1607 } |
|
1608 |
|
1609 /** |
|
1610 @prototype |
|
1611 */ |
|
1612 TInt TDrive::CheckDisk(TInt aOperation, TAny* aParam1/*=NULL*/, TAny* aParam2/*=NULL*/) |
|
1613 { |
|
1614 TInt r=CheckMount(); |
|
1615 if (r==KErrNone) |
|
1616 TRAP(r,FlushCachedFileInfoL()); |
|
1617 if (r==KErrNone) |
|
1618 { |
|
1619 TRACE4(UTF::EBorder, UTraceModuleFileSys::ECMountCBCheckDisk2, EF32TraceUidFileSys, DriveNumber(), aOperation, aParam1, aParam2); |
|
1620 r=CurrentMount().CheckDisk(aOperation, aParam1, aParam2); |
|
1621 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBCheckDisk2Ret, EF32TraceUidFileSys, r); |
|
1622 } |
|
1623 |
|
1624 return(r); |
|
1625 } |
|
1626 |
|
1627 TInt TDrive::ScanDrive() |
|
1628 { |
|
1629 __CHECK_DRIVETHREAD(iDriveNumber); |
|
1630 TInt r=CheckMount(); |
|
1631 if(r==KErrNone) |
|
1632 { |
|
1633 if(IsWriteProtected()) |
|
1634 return(KErrAccessDenied); |
|
1635 TRAP(r,FlushCachedFileInfoL()); |
|
1636 } |
|
1637 if(r!=KErrNone) |
|
1638 return r; |
|
1639 |
|
1640 // Empty closed file queue |
|
1641 TClosedFileUtils::Remove(DriveNumber()); |
|
1642 |
|
1643 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBScanDrive1, EF32TraceUidFileSys, DriveNumber()); |
|
1644 r = CurrentMount().ScanDrive(); |
|
1645 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBScanDrive1Ret, EF32TraceUidFileSys, r); |
|
1646 |
|
1647 return r; |
|
1648 } |
|
1649 |
|
1650 |
|
1651 /** |
|
1652 @prototype |
|
1653 */ |
|
1654 TInt TDrive::ScanDrive(TInt aOperation, TAny* aParam1/*=NULL*/, TAny* aParam2/*=NULL*/) |
|
1655 { |
|
1656 __CHECK_DRIVETHREAD(iDriveNumber); |
|
1657 TInt r=CheckMount(); |
|
1658 if(r==KErrNone) |
|
1659 { |
|
1660 if(IsWriteProtected()) |
|
1661 return(KErrAccessDenied); |
|
1662 TRAP(r,FlushCachedFileInfoL()); |
|
1663 } |
|
1664 if(r!=KErrNone) |
|
1665 return r; |
|
1666 |
|
1667 // Empty closed file queue |
|
1668 TClosedFileUtils::Remove(DriveNumber()); |
|
1669 |
|
1670 TRACE4(UTF::EBorder, UTraceModuleFileSys::ECMountCBScanDrive2, EF32TraceUidFileSys, DriveNumber(), aOperation, aParam1, aParam2); |
|
1671 r = CurrentMount().ScanDrive(aOperation, aParam1, aParam2); |
|
1672 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBScanDrive2Ret, EF32TraceUidFileSys, r); |
|
1673 |
|
1674 return r; |
|
1675 } |
|
1676 |
|
1677 |
|
1678 TInt TDrive::GetShortName(const TDesC& aName,TDes& aShortName) |
|
1679 // |
|
1680 // Get the short name associated with a long file name |
|
1681 // |
|
1682 { |
|
1683 TInt r=CheckMountAndEntryName(aName); |
|
1684 if (r!=KErrNone) |
|
1685 return(r); |
|
1686 TPtrC entryName(StripBackSlash(aName)); |
|
1687 |
|
1688 TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBGetShortNameL, EF32TraceUidFileSys, DriveNumber(), entryName); |
|
1689 TRAP(r,CurrentMount().GetShortNameL(entryName,aShortName)); |
|
1690 TRACERETMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBGetShortNameLRet, EF32TraceUidFileSys, r, aShortName); |
|
1691 |
|
1692 return(r); |
|
1693 } |
|
1694 |
|
1695 TInt TDrive::GetLongName(const TDesC& aShortName,TDes& aLongName) |
|
1696 // |
|
1697 // Get the long name associated with a short file name |
|
1698 // |
|
1699 { |
|
1700 TInt r=CheckMountAndEntryName(aShortName); |
|
1701 if (r!=KErrNone) |
|
1702 return(r); |
|
1703 TPtrC entryName(StripBackSlash(aShortName)); |
|
1704 |
|
1705 TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBGetLongNameL, EF32TraceUidFileSys, DriveNumber(), entryName); |
|
1706 TRAP(r,CurrentMount().GetLongNameL(entryName,aLongName)); |
|
1707 TRACERETMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBGetLongNameLRet, EF32TraceUidFileSys, r, aLongName); |
|
1708 |
|
1709 return(r); |
|
1710 } |
|
1711 |
|
1712 TInt TDrive::IsFileOpen(const TDesC& aFileName,CFileCB*& aFileCB) |
|
1713 // |
|
1714 // Query whether the file is open or not. |
|
1715 // |
|
1716 { |
|
1717 __CHECK_DRIVETHREAD(iDriveNumber); |
|
1718 |
|
1719 aFileCB = NULL; |
|
1720 |
|
1721 TEntry dumEntry; |
|
1722 TInt r=Entry(aFileName,dumEntry); |
|
1723 if (r!=KErrNone) |
|
1724 return(r); |
|
1725 if(dumEntry.iAtt&KEntryAttDir) |
|
1726 return KErrArgument; |
|
1727 |
|
1728 Files->Lock(); |
|
1729 TInt count=Files->Count(); |
|
1730 |
|
1731 // create a hash to speed up the search |
|
1732 |
|
1733 TFileName foldedName; |
|
1734 TUint32 nameHash=0; |
|
1735 if (count > 0) |
|
1736 { |
|
1737 foldedName.CopyF(aFileName); |
|
1738 nameHash=CalcNameHash(foldedName); |
|
1739 } |
|
1740 |
|
1741 while(count--) |
|
1742 { |
|
1743 CFileCB* file=(CFileCB*)(*Files)[count]; |
|
1744 |
|
1745 if ((&file->Drive()==this) && nameHash == file->NameHash() && file->FileNameF().Match(foldedName)!=KErrNotFound) |
|
1746 { |
|
1747 aFileCB = file; |
|
1748 break; |
|
1749 } |
|
1750 } |
|
1751 Files->Unlock(); |
|
1752 return(KErrNone); |
|
1753 } |
|
1754 |
|
1755 TInt TDrive::IsFileInRom(const TDesC& aFileName,TUint8*& aFileStart) |
|
1756 // |
|
1757 // Return the start of the file if it is in rom |
|
1758 // |
|
1759 { |
|
1760 TInt r=CheckMount(); |
|
1761 if (r==KErrNone) |
|
1762 CurrentMount().IsFileInRom(aFileName,aFileStart); |
|
1763 return(r); |
|
1764 } |
|
1765 |
|
1766 TBool TDrive::IsWriteProtected() |
|
1767 // |
|
1768 // return true if the media is write protected |
|
1769 // |
|
1770 { |
|
1771 // __CHECK_DRIVETHREAD(iDriveNumber); |
|
1772 TDriveInfo drvInfo; |
|
1773 drvInfo.iMediaAtt=0; |
|
1774 if(Att() && iFSys) |
|
1775 FSys().DriveInfo(drvInfo,DriveNumber()); |
|
1776 return((drvInfo.iMediaAtt&KMediaAttWriteProtected)!=0); |
|
1777 } |
|
1778 |
|
1779 |
|
1780 |
|
1781 |
|
1782 /** |
|
1783 Checks whether any resource that could write to disk is open on |
|
1784 the current mount. |
|
1785 |
|
1786 @return True, if a resource that could write to disk is open on |
|
1787 the current mount, false otherwise. |
|
1788 */ |
|
1789 EXPORT_C TBool TDrive::IsWriteableResource() const |
|
1790 { |
|
1791 // __CHECK_DRIVETHREAD(iDriveNumber); |
|
1792 if(iCurrentMount==NULL) |
|
1793 return(EFalse); |
|
1794 if(iCurrentMount->LockStatus()>0) |
|
1795 { |
|
1796 // check format subsessions |
|
1797 Formats->Lock(); |
|
1798 TInt count=Formats->Count(); |
|
1799 while(count--) |
|
1800 { |
|
1801 CFormatCB* format=(CFormatCB*)(*Formats)[count]; |
|
1802 if(&format->Mount()==iCurrentMount) |
|
1803 { |
|
1804 Formats->Unlock(); |
|
1805 return(ETrue); |
|
1806 } |
|
1807 } |
|
1808 Formats->Unlock(); |
|
1809 // check raw disk subsessions |
|
1810 RawDisks->Lock(); |
|
1811 count=RawDisks->Count(); |
|
1812 while(count--) |
|
1813 { |
|
1814 CRawDiskCB* rawDisk=(CRawDiskCB*)(*RawDisks)[count]; |
|
1815 if(&rawDisk->Mount()==iCurrentMount && !rawDisk->IsWriteProtected()) |
|
1816 { |
|
1817 Formats->Unlock(); |
|
1818 return(ETrue); |
|
1819 } |
|
1820 } |
|
1821 Formats->Unlock(); |
|
1822 } |
|
1823 else if(iCurrentMount->LockStatus()<0) |
|
1824 { |
|
1825 // check file share subsessions |
|
1826 FileShares->Lock(); |
|
1827 TInt count=FileShares->Count(); |
|
1828 while(count--) |
|
1829 { |
|
1830 CFileShare* fileShare=(CFileShare*)(*FileShares)[count]; |
|
1831 if (&fileShare->File().Mount()==iCurrentMount && ((fileShare->iMode&EFileWrite)!=0)) |
|
1832 { |
|
1833 FileShares->Unlock(); |
|
1834 return(ETrue); |
|
1835 } |
|
1836 } |
|
1837 FileShares->Unlock(); |
|
1838 } |
|
1839 return(EFalse); |
|
1840 } |
|
1841 |
|
1842 |
|
1843 |
|
1844 |
|
1845 /** |
|
1846 Tests whether the current function can cause a write to disk. |
|
1847 |
|
1848 @return True, if the current function can cause a write to disk, |
|
1849 false otherwise. |
|
1850 */ |
|
1851 EXPORT_C TBool TDrive::IsCurrentWriteFunction() const |
|
1852 { |
|
1853 // __CHECK_DRIVETHREAD(iDriveNumber); |
|
1854 CDriveThread* pT=NULL; |
|
1855 TInt r=FsThreadManager::GetDriveThread(iDriveNumber, &pT); |
|
1856 __ASSERT_ALWAYS(r==KErrNone && pT,Fault(EDriveCurrentWriteFunction)); |
|
1857 return(pT->IsRequestWriteable()); |
|
1858 } |
|
1859 |
|
1860 |
|
1861 |
|
1862 |
|
1863 TInt TDrive::ForceRemountDrive(const TDesC8* aMountInfo,TInt aMountInfoMessageHandle,TUint aFlags) |
|
1864 // |
|
1865 // Force a remount of the drive |
|
1866 // |
|
1867 { |
|
1868 __PRINT(_L("TDrive::ForceRemountDrive")); |
|
1869 __CHECK_DRIVETHREAD(iDriveNumber); |
|
1870 if(iFSys==NULL) |
|
1871 return(KErrNotReady); |
|
1872 TInt r; |
|
1873 CMountCB* pM=NULL; |
|
1874 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountL, EF32TraceUidFileSys, &FSys(), DriveNumber()); |
|
1875 TRAP(r,pM=FSys().NewMountL()); |
|
1876 TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountLRet, EF32TraceUidFileSys, r, pM); |
|
1877 if(r!=KErrNone) |
|
1878 return(r); |
|
1879 pM->SetDrive(this); |
|
1880 |
|
1881 TRACE4(UTF::EBorder, UTraceModuleFileSys::ECMountCBForceRemountDrive, EF32TraceUidFileSys, |
|
1882 DriveNumber(), aMountInfo, aMountInfoMessageHandle, aFlags); |
|
1883 r=pM->ForceRemountDrive(aMountInfo,aMountInfoMessageHandle,aFlags); |
|
1884 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBForceRemountDriveRet, EF32TraceUidFileSys, r); |
|
1885 |
|
1886 pM->Close(); |
|
1887 return(r); |
|
1888 } |
|
1889 |
|
1890 TBool TDrive::IsExtensionMounted(CProxyDriveFactory* aFactory) |
|
1891 // |
|
1892 // return ETrue if extension mounted on the drive |
|
1893 // |
|
1894 { |
|
1895 for(TInt i=0;i<iExtInfo.iCount;++i) |
|
1896 { |
|
1897 if(iExtInfo.iInfo[i].iFactory==aFactory) |
|
1898 return(ETrue); |
|
1899 } |
|
1900 return(EFalse); |
|
1901 } |
|
1902 |
|
1903 TInt TDrive::MountExtension(CProxyDriveFactory* aFactory,TBool aIsPrimary) |
|
1904 // |
|
1905 // Mount an extension |
|
1906 // |
|
1907 { |
|
1908 __PRINT1(_L("TDrive::MountExtension aIsPrimary=%d"),aIsPrimary); |
|
1909 if(aIsPrimary) |
|
1910 { |
|
1911 __CHECK_MAINTHREAD(); |
|
1912 // primary extension mounted before file system since it must be present |
|
1913 // for successful mount |
|
1914 __ASSERT_ALWAYS(!iFSys,Fault(EMountExtensionFSys)); |
|
1915 if(iExtInfo.iCount!=0) |
|
1916 return(KErrAccessDenied); |
|
1917 iExtInfo.iInfo[iExtInfo.iCount].iFactory=aFactory; |
|
1918 iExtInfo.iInfo[iExtInfo.iCount++].iIsPrimary=ETrue; |
|
1919 return(KErrNone); |
|
1920 } |
|
1921 __CHECK_DRIVETHREAD(iDriveNumber); |
|
1922 // must be a secondary extension |
|
1923 if(iFSys==NULL) |
|
1924 return(KErrNotReady); |
|
1925 TBool extSupported = iFSys->IsExtensionSupported(); |
|
1926 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemIsExtensionSupported, EF32TraceUidFileSys, extSupported); |
|
1927 if(!extSupported) |
|
1928 return(KErrNotSupported); |
|
1929 if(IsExtensionMounted(aFactory)) |
|
1930 return(KErrAlreadyExists); |
|
1931 if(iCurrentMount && (CurrentMount().LockStatus()!=0 || Mount().Count()>1)) |
|
1932 return(KErrInUse); |
|
1933 if(iExtInfo.iCount>=KMaxExtensionCount) |
|
1934 return(KErrAccessDenied); |
|
1935 iExtInfo.iInfo[iExtInfo.iCount].iFactory=aFactory; |
|
1936 iExtInfo.iInfo[iExtInfo.iCount++].iIsPrimary=EFalse; |
|
1937 // now dismount and mount so that the extension incorporated |
|
1938 Dismount(); |
|
1939 TInt r=CheckMount(); |
|
1940 // if mount fails then remove the secondary extension |
|
1941 if(r!=KErrNone) |
|
1942 { |
|
1943 --iExtInfo.iCount; |
|
1944 __ASSERT_DEBUG(iExtInfo.iCount>=0,Fault(EExtensionInfoCount0)); |
|
1945 } |
|
1946 return(r); |
|
1947 } |
|
1948 |
|
1949 TInt TDrive::DismountExtension(CProxyDriveFactory* aFactory, TBool /*aIsPrimary*/) |
|
1950 // |
|
1951 // Dismount an extension |
|
1952 // |
|
1953 { |
|
1954 __PRINT(_L("TDrive::DismountExtension")); |
|
1955 __CHECK_DRIVETHREAD(iDriveNumber); |
|
1956 |
|
1957 // Empty closed file queue |
|
1958 TClosedFileUtils::Remove(DriveNumber()); |
|
1959 |
|
1960 if(iExtInfo.iCount==0) |
|
1961 return(KErrNotFound); |
|
1962 if(iCurrentMount && (CurrentMount().LockStatus()!=0 || Mount().Count()>1)) |
|
1963 return(KErrInUse); |
|
1964 for(TInt i=0;i<iExtInfo.iCount;++i) |
|
1965 { |
|
1966 if(iExtInfo.iInfo[i].iFactory==aFactory) |
|
1967 { |
|
1968 // cannot dismount a primary extension without dismounting the file system |
|
1969 if(i==0 && iExtInfo.iInfo[i].iIsPrimary) |
|
1970 return(KErrAccessDenied); |
|
1971 // slide any remaining extensions down |
|
1972 for(TInt j=i+1;j<iExtInfo.iCount;++j) |
|
1973 iExtInfo.iInfo[j-1].iFactory=iExtInfo.iInfo[j].iFactory; |
|
1974 iExtInfo.iCount--; |
|
1975 __ASSERT_DEBUG(iExtInfo.iCount>=0,Fault(EExtensionInfoCount1)); |
|
1976 Dismount(); |
|
1977 return(KErrNone); |
|
1978 } |
|
1979 } |
|
1980 return(KErrNotFound); |
|
1981 } |
|
1982 |
|
1983 TInt TDrive::ExtensionName(TDes& aExtensionName,TInt aPos) |
|
1984 // |
|
1985 // Return the extension name |
|
1986 // |
|
1987 { |
|
1988 __CHECK_DRIVETHREAD(iDriveNumber); |
|
1989 |
|
1990 if(iFSys==NULL) |
|
1991 return(KErrNotReady); |
|
1992 |
|
1993 if(aPos<iExtInfo.iCount) |
|
1994 { |
|
1995 aExtensionName=iExtInfo.iInfo[aPos].iFactory->Name(); |
|
1996 return(KErrNone); |
|
1997 } |
|
1998 return(KErrNotFound); |
|
1999 } |
|
2000 |
|
2001 #if defined(_LOCKABLE_MEDIA) |
|
2002 |
|
2003 TInt TDrive::LockDevice(TMediaPassword& aOld,TMediaPassword& aNew,TBool aStore) |
|
2004 // |
|
2005 // Lock media device |
|
2006 // |
|
2007 { |
|
2008 __PRINT(_L("TDrive::LockDevice")); |
|
2009 __CHECK_DRIVETHREAD(iDriveNumber); |
|
2010 if(iFSys==NULL) |
|
2011 return(KErrNotReady); |
|
2012 TInt r; |
|
2013 CMountCB* pM=NULL; |
|
2014 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountL, EF32TraceUidFileSys, &FSys(), DriveNumber()); |
|
2015 TRAP(r,pM=FSys().NewMountL()); |
|
2016 TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountLRet, EF32TraceUidFileSys, r, pM); |
|
2017 if(r!=KErrNone) |
|
2018 return(r); |
|
2019 pM->SetDrive(this); |
|
2020 |
|
2021 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECMountCBLock, EF32TraceUidFileSys, DriveNumber(), aStore); |
|
2022 r=pM->Lock(aOld,aNew,aStore); |
|
2023 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBLockRet, EF32TraceUidFileSys, r); |
|
2024 |
|
2025 pM->Close(); |
|
2026 return(r); |
|
2027 } |
|
2028 |
|
2029 TInt TDrive::UnlockDevice(TMediaPassword& aPassword,TBool aStore) |
|
2030 // |
|
2031 // Unlock media device |
|
2032 // |
|
2033 { |
|
2034 __PRINT(_L("TDrive::UnlockDevice")); |
|
2035 __CHECK_DRIVETHREAD(iDriveNumber); |
|
2036 if(iFSys==NULL) |
|
2037 return(KErrNotReady); |
|
2038 TInt r; |
|
2039 CMountCB* pM=NULL; |
|
2040 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountL, EF32TraceUidFileSys, &FSys(), DriveNumber()); |
|
2041 TRAP(r,pM=FSys().NewMountL()); |
|
2042 TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountLRet, EF32TraceUidFileSys, r, pM); |
|
2043 if(r!=KErrNone) |
|
2044 return(r); |
|
2045 |
|
2046 // reset mount failure count - which is likely to be non-zero if drive is locked |
|
2047 iMountFailures = 0; |
|
2048 |
|
2049 pM->SetDrive(this); |
|
2050 |
|
2051 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECMountCBUnlock, EF32TraceUidFileSys, DriveNumber(), aStore); |
|
2052 r=pM->Unlock(aPassword,aStore); |
|
2053 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBUnlockRet, EF32TraceUidFileSys, r); |
|
2054 |
|
2055 pM->Close(); |
|
2056 return(r); |
|
2057 } |
|
2058 |
|
2059 TInt TDrive::ClearDevicePassword(TMediaPassword& aPassword) |
|
2060 // |
|
2061 // Clear password of media device |
|
2062 // |
|
2063 { |
|
2064 __PRINT(_L("TDrive::ClearDevicePassword")); |
|
2065 __CHECK_DRIVETHREAD(iDriveNumber); |
|
2066 if(iFSys==NULL) |
|
2067 return(KErrNotReady); |
|
2068 TInt r; |
|
2069 CMountCB* pM=NULL; |
|
2070 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountL, EF32TraceUidFileSys, &FSys(), DriveNumber()); |
|
2071 TRAP(r,pM=FSys().NewMountL()); |
|
2072 TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountLRet, EF32TraceUidFileSys, r, pM); |
|
2073 if(r!=KErrNone) |
|
2074 return(r); |
|
2075 pM->SetDrive(this); |
|
2076 |
|
2077 // ClearPassword() will only work if the card is already unlocked. |
|
2078 // If the stack powers down, the card will become locked, so now that TBusLocalDrive::Caps() |
|
2079 // no longer powers up ths stack, we need to unlock the card first - but ignore the error as |
|
2080 // the stack may unlock from the password store. |
|
2081 TDriveInfo info; |
|
2082 DriveInfo(info); |
|
2083 if (info.iMediaAtt & KMediaAttLocked) |
|
2084 UnlockDevice(aPassword, EFalse); |
|
2085 |
|
2086 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBClearPassword, EF32TraceUidFileSys, DriveNumber()); |
|
2087 r=pM->ClearPassword(aPassword); |
|
2088 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBClearPasswordRet, EF32TraceUidFileSys, r); |
|
2089 |
|
2090 pM->Close(); |
|
2091 return(r); |
|
2092 } |
|
2093 |
|
2094 TInt TDrive::EraseDevicePassword() |
|
2095 // |
|
2096 // Erase password from the media device |
|
2097 // |
|
2098 { |
|
2099 __PRINT(_L("TDrive::EraseDevicePassword")); |
|
2100 __CHECK_DRIVETHREAD(iDriveNumber); |
|
2101 if(iFSys==NULL) |
|
2102 return(KErrNotReady); |
|
2103 TInt r; |
|
2104 CMountCB* pM=NULL; |
|
2105 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountL, EF32TraceUidFileSys, &FSys(), DriveNumber()); |
|
2106 TRAP(r,pM=FSys().NewMountL()); |
|
2107 TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewMountLRet, EF32TraceUidFileSys, r, pM); |
|
2108 if(r!=KErrNone) |
|
2109 return(r); |
|
2110 pM->SetDrive(this); |
|
2111 |
|
2112 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBErasePassword, EF32TraceUidFileSys, DriveNumber()); |
|
2113 r=pM->ErasePassword(); |
|
2114 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBErasePasswordRet, EF32TraceUidFileSys, r); |
|
2115 |
|
2116 pM->Close(); |
|
2117 return(r); |
|
2118 } |
|
2119 |
|
2120 #else |
|
2121 |
|
2122 TInt TDrive::LockDevice(TMediaPassword& /*aOld*/,TMediaPassword& /*aNew*/,TBool /*aStore*/) |
|
2123 // |
|
2124 // Lock media device |
|
2125 // |
|
2126 { |
|
2127 return(KErrNotSupported); |
|
2128 } |
|
2129 |
|
2130 TInt TDrive::UnlockDevice(TMediaPassword& /*aPassword*/,TBool /*aStore*/) |
|
2131 // |
|
2132 // Unlock media device |
|
2133 // |
|
2134 { |
|
2135 return(KErrNotSupported); |
|
2136 } |
|
2137 |
|
2138 TInt TDrive::ClearDevicePassword(TMediaPassword& /*aPassword*/) |
|
2139 // |
|
2140 // Clear password of media device |
|
2141 // |
|
2142 { |
|
2143 return(KErrNotSupported); |
|
2144 } |
|
2145 |
|
2146 TInt TDrive::EraseDevicePassword(TMediaPassword& /*aPassword*/) |
|
2147 // |
|
2148 // Clear password of media device |
|
2149 // |
|
2150 { |
|
2151 return(KErrNotSupported); |
|
2152 } |
|
2153 |
|
2154 #endif |
|
2155 |
|
2156 |
|
2157 |
|
2158 |
|
2159 /** |
|
2160 Gets the current notification state, which indicates whether the client |
|
2161 is notified of any read or write failures. |
|
2162 |
|
2163 The notification status is a property of the current session with |
|
2164 the file server, the value of which is stored in CSessionFs::iNotifyUser. |
|
2165 If set to ETrue, the client will receive notifications from the file system. |
|
2166 |
|
2167 Called by CMountCB::GetNotifyUser(). |
|
2168 |
|
2169 @return True, if the client receives notifications from the file system, |
|
2170 false otherwise. |
|
2171 |
|
2172 @see CMountCB |
|
2173 */ |
|
2174 EXPORT_C TBool TDrive::GetNotifyUser() |
|
2175 { |
|
2176 __CHECK_DRIVETHREAD(iDriveNumber); |
|
2177 if(iDriveFlags & ENotifyOff) |
|
2178 return(EFalse); |
|
2179 else |
|
2180 { |
|
2181 CDriveThread* pT=NULL; |
|
2182 |
|
2183 const TInt r=FsThreadManager::GetDriveThread(iDriveNumber,&pT); |
|
2184 |
|
2185 //-- if this drive is synchronous, i.e. all requests are processed in the main FS thread, |
|
2186 //-- pretend that user notifications are turned off to avoid panic in the assert below. |
|
2187 //-- for synch. drives pT will always be NULL and it's not possible to obtain CSessionFs by drive number. |
|
2188 if(r == KErrAccessDenied) |
|
2189 return EFalse; |
|
2190 |
|
2191 __ASSERT_ALWAYS(r==KErrNone && pT,Fault(EDriveGetNotifyUser)); |
|
2192 return(pT->IsSessionNotifyUser()); |
|
2193 } |
|
2194 } |
|
2195 |
|
2196 |
|
2197 |
|
2198 |
|
2199 /** |
|
2200 Dismounts the current mount. This is method is called from outside, so do some finalisation work on mount. |
|
2201 After calling this function there is no current mount on the drive. |
|
2202 */ |
|
2203 EXPORT_C void TDrive::Dismount() |
|
2204 { |
|
2205 __PRINT1(_L("TDrive::Dismount() iCurrentMount:0x%x"),iCurrentMount); |
|
2206 |
|
2207 iMountFailures = 0; |
|
2208 if (!iCurrentMount) |
|
2209 return; |
|
2210 |
|
2211 TRAP_IGNORE(FlushCachedFileInfoL()); |
|
2212 |
|
2213 //-- try our best to finalise the mount (the mount can decide to do some job during finalisation, e.g. write some data) |
|
2214 TRAP_IGNORE(iCurrentMount->FinaliseMountL()); |
|
2215 |
|
2216 DoDismount(); |
|
2217 } |
|
2218 |
|
2219 |
|
2220 |
|
2221 |
|
2222 /** |
|
2223 Forcibly dismounts the current mount and prevents it being remounted. |
|
2224 After calling this function there is no current mount on the drive. |
|
2225 */ |
|
2226 void TDrive::ForceDismount() |
|
2227 { |
|
2228 __PRINT1(_L("TDrive::ForceDismount() iCurrentMount:0x%x"),iCurrentMount); |
|
2229 |
|
2230 iMountFailures = 0; |
|
2231 |
|
2232 if(!iCurrentMount) |
|
2233 return; |
|
2234 |
|
2235 TRAP_IGNORE(FlushCachedFileInfoL()); |
|
2236 iCurrentMount->SetDismounted(); //! this affects TDrive::ReMount() |
|
2237 DoDismount(); |
|
2238 } |
|
2239 |
|
2240 /** |
|
2241 An internal method. Dismounts and closes a current mount. |
|
2242 This method must not involve writing data to the media, because it could have beeen physically changed before. |
|
2243 Called only from TDrive::CheckMount(). |
|
2244 */ |
|
2245 void TDrive::DoDismount() |
|
2246 { |
|
2247 __PRINT1(_L("TDrive::DoDismount() iCurrentMount:0x%x"),iCurrentMount); |
|
2248 |
|
2249 iMountFailures = 0; |
|
2250 |
|
2251 if (!iCurrentMount) |
|
2252 return; |
|
2253 |
|
2254 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBDismounted, EF32TraceUidFileSys, DriveNumber()); |
|
2255 iCurrentMount->Dismounted(); |
|
2256 TRACE0(UTF::EBorder, UTraceModuleFileSys::ECMountCBDismountedRet, EF32TraceUidFileSys); |
|
2257 |
|
2258 iCurrentMount->Close(); |
|
2259 iCurrentMount=NULL; |
|
2260 } |
|
2261 |
|
2262 |
|
2263 /** |
|
2264 Return the number of active mounts associated with this drive. |
|
2265 (inactive mounts are those that have been forcibly dismounted) |
|
2266 */ |
|
2267 TInt TDrive::ActiveMounts() const |
|
2268 { |
|
2269 TInt activeMounts = 0; |
|
2270 |
|
2271 TInt idx = Mount().Count(); |
|
2272 while(idx--) |
|
2273 { |
|
2274 if(((CMountCB*)Mount()[idx])->IsDismounted()) |
|
2275 { |
|
2276 activeMounts++; |
|
2277 } |
|
2278 } |
|
2279 |
|
2280 __PRINT1(_L("TDrive::ActiveMounts = %d"), activeMounts); |
|
2281 return activeMounts; |
|
2282 } |
|
2283 |
|
2284 |
|
2285 |
|
2286 |
|
2287 /** |
|
2288 Reactivate any disactive mounts on the drive following a dismount. |
|
2289 (inactive mounts are those that have been foribly dismounted) |
|
2290 */ |
|
2291 void TDrive::ReactivateMounts() |
|
2292 { |
|
2293 __PRINT(_L("TDrive::ReactivateMounts")); |
|
2294 |
|
2295 TInt idx = Mount().Count(); |
|
2296 while(idx--) |
|
2297 { |
|
2298 ((CMountCB*)Mount()[idx])->SetDismounted(EFalse); |
|
2299 } |
|
2300 } |
|
2301 |
|
2302 |
|
2303 |
|
2304 |
|
2305 /** |
|
2306 Increments the drive dismount lock. This defers dismount |
|
2307 of a file system until all clients have notified that it |
|
2308 is safe to do so. |
|
2309 |
|
2310 @see RFs::NotifyDismount |
|
2311 */ |
|
2312 void TDrive::DismountLock() |
|
2313 { iDismountLock++; } |
|
2314 |
|
2315 |
|
2316 |
|
2317 |
|
2318 /** |
|
2319 Decrements the drive dismount lock. When the lock count |
|
2320 reaches zero, the file system may be unmounted |
|
2321 |
|
2322 @see RFs::AllowDismount |
|
2323 @return The new lock count |
|
2324 */ |
|
2325 TInt TDrive::DismountUnlock() |
|
2326 { |
|
2327 return(--iDismountLock); |
|
2328 } |
|
2329 |
|
2330 |
|
2331 |
|
2332 |
|
2333 /** |
|
2334 Return the state of the dismount lock. |
|
2335 */ |
|
2336 TBool TDrive::DismountLocked() const |
|
2337 { return(iDismountLock); } |
|
2338 |
|
2339 |
|
2340 |
|
2341 |
|
2342 /** |
|
2343 Pending flag - set while waiting for clients to accept the dismount |
|
2344 */ |
|
2345 void TDrive::SetDismountDeferred(TBool aPending) |
|
2346 { |
|
2347 if(aPending) |
|
2348 iDriveFlags |= EDismountDeferred; |
|
2349 else |
|
2350 iDriveFlags &= ~EDismountDeferred; |
|
2351 } |
|
2352 |
|
2353 |
|
2354 |
|
2355 TInt TDrive::ControlIO(const RMessagePtr2& aMessage,TInt aCommand,TAny* aParam1,TAny* aParam2) |
|
2356 // |
|
2357 // General purpose test interface - .FSY specific. |
|
2358 // |
|
2359 { |
|
2360 TInt r=CheckMount(); |
|
2361 if(r==KErrNone || (r==KErrInUse && iReason==KErrNone)) |
|
2362 { |
|
2363 TRACETHREADID(aMessage); |
|
2364 TRACE5(UTF::EBorder, UTraceModuleFileSys::ECMountCBControlIO, EF32TraceUidFileSys, |
|
2365 DriveNumber(), aCommand, aParam1, aParam2, I64LOW(threadId)); |
|
2366 r=CurrentMount().ControlIO(aMessage,aCommand,aParam1,aParam2); |
|
2367 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBControlIORet, EF32TraceUidFileSys, r); |
|
2368 } |
|
2369 return(r); |
|
2370 } |
|
2371 |
|
2372 |
|
2373 |
|
2374 |
|
2375 /** |
|
2376 Gets the drive attributes |
|
2377 |
|
2378 @return The drive attributes. |
|
2379 */ |
|
2380 EXPORT_C TUint TDrive::Att() |
|
2381 { |
|
2382 TUint a=iAtt; |
|
2383 return(a); |
|
2384 } |
|
2385 |
|
2386 void TDrive::SetAtt(TUint aValue) |
|
2387 // |
|
2388 // set drive attributes |
|
2389 // |
|
2390 { |
|
2391 iAtt=aValue; |
|
2392 } |
|
2393 |
|
2394 EXPORT_C TBool TDrive::IsDriveThread() const |
|
2395 // |
|
2396 // Return ETrue if the current thread id is the same as that of the drive's drive thread |
|
2397 // |
|
2398 { |
|
2399 return(FsThreadManager::IsDriveThread(iDriveNumber,ETrue)); |
|
2400 } |
|
2401 |
|
2402 EXPORT_C TBool TDrive::IsMainThread() const |
|
2403 // |
|
2404 // Reture ETrue if the current thread id is the same as that of the main file server thread |
|
2405 // |
|
2406 { |
|
2407 return(FsThreadManager::IsMainThread()); |
|
2408 } |
|
2409 |
|
2410 EXPORT_C void TDrive::DriveFault(TBool aDriveError) const |
|
2411 // |
|
2412 // |
|
2413 // |
|
2414 { |
|
2415 if(aDriveError) |
|
2416 ::Fault(EFsDriveThreadError); |
|
2417 else |
|
2418 ::Fault(EFsMainThreadError); |
|
2419 } |
|
2420 |
|
2421 TInt TDrive::ClampFile(const TDesC& aName, TAny* aHandle) |
|
2422 // |
|
2423 // Attempt to clamp file |
|
2424 // |
|
2425 { |
|
2426 CMountCB* mount = (CMountCB*)&(CurrentMount()); |
|
2427 TInt driveNo = DriveNumber(); |
|
2428 return(mount->ClampFile(driveNo,aName,aHandle)); |
|
2429 } |
|
2430 |
|
2431 |
|
2432 TInt TDrive::UnclampFile(CMountCB* aMount, RFileClamp* aHandle) |
|
2433 // |
|
2434 // Attempt to unclamp file |
|
2435 // |
|
2436 { |
|
2437 return(aMount->UnclampFile(aHandle)); |
|
2438 } |
|
2439 |
|
2440 |
|
2441 TInt TDrive::ClampsOnDrive() |
|
2442 // |
|
2443 // Returns the number of clamps on this drive |
|
2444 // |
|
2445 { |
|
2446 Lock(); |
|
2447 TInt clamps = IsMounted()?((CMountCB*)&(CurrentMount()))->NoOfClamps():0; |
|
2448 UnLock(); |
|
2449 return (clamps); |
|
2450 } |
|
2451 |
|
2452 |
|
2453 |
|
2454 void TDrive::SetClampFlag(TBool aClamped) |
|
2455 // |
|
2456 // Indicate if any files are clamped |
|
2457 // |
|
2458 { |
|
2459 if(aClamped) |
|
2460 iDriveFlags |= EClampPresent; |
|
2461 else |
|
2462 iDriveFlags &= ~EClampPresent; |
|
2463 } |
|
2464 |
|
2465 |
|
2466 TBool TDrive::ClampFlag() |
|
2467 // |
|
2468 // Report if any files are clamped |
|
2469 // |
|
2470 { return(iDriveFlags & EClampPresent); } |
|
2471 |
|
2472 |
|
2473 |
|
2474 #if defined(_DEBUG) || defined(_DEBUG_RELEASE) |
|
2475 TInt TDrive::ClearDeferredDismount() |
|
2476 // debug-only function for testing |
|
2477 { |
|
2478 Lock(); |
|
2479 FsNotify::HandleDismount(EFsDismountRegisterClient, DriveNumber(), ETrue, KErrNone); |
|
2480 SetDismountDeferred(EFalse); |
|
2481 UnLock(); |
|
2482 return KErrNone; |
|
2483 } |
|
2484 #endif |
|
2485 |
|
2486 |
|
2487 TInt TDrive::DismountProxyDrive() |
|
2488 // |
|
2489 // Dismount a proxy drive |
|
2490 // |
|
2491 { |
|
2492 __PRINT(_L("TDrive::DismountProxyDrive")); |
|
2493 __CHECK_DRIVETHREAD(iDriveNumber); |
|
2494 |
|
2495 if (!IsProxyDrive(iDriveNumber) || LocalDrives::DriveNumberToLocalDriveNumber(iDriveNumber) == KDriveInvalid) |
|
2496 return KErrArgument; |
|
2497 |
|
2498 if(iCurrentMount) |
|
2499 return(KErrInUse); |
|
2500 |
|
2501 |
|
2502 // Prevent ALL inactive mounts from EVER being remounted as they MAY (& probably do) point to |
|
2503 // this proxy-drive which we are about to delete.... |
|
2504 // NB We could try to find out which mounts actually use this particular proxy-drive, but that's |
|
2505 // a bit tricky to determine if there are extensions present as CMountCB::ProxyDrive() will only |
|
2506 // return the first proxy drive in the chain. |
|
2507 TInt mCount=Mount().Count(); |
|
2508 TInt u=(Mount().UniqueID()<<16); |
|
2509 for (TInt i=0;i<mCount;i++) |
|
2510 { |
|
2511 CMountCB* pM=(CMountCB*)Mount().At(u|i); |
|
2512 pM->SetProxyDriveDismounted(); |
|
2513 } |
|
2514 |
|
2515 FsThreadManager::LockDrive(iDriveNumber); |
|
2516 // Proxy drives are responsible for managing the drive threads... |
|
2517 FsThreadManager::CloseDrive(iDriveNumber); |
|
2518 LocalDrives::ClearProxyDriveMapping(iDriveNumber); |
|
2519 FsThreadManager::UnlockDrive(iDriveNumber); |
|
2520 |
|
2521 return KErrNone; |
|
2522 } |
|
2523 |
|
2524 //---------------------------------------------------------------------------- |
|
2525 /** |
|
2526 Complete, remove and delete notification requests |
|
2527 @param aCompletionCode completion code for some notifications |
|
2528 */ |
|
2529 void TDrive::DoCompleteDismountNotify(TInt aCompletionCode) |
|
2530 { |
|
2531 FsNotify::HandleDismount(EFsDismountRegisterClient, iDriveNumber, ETrue, KErrNone); |
|
2532 FsNotify::HandleDismount(EFsDismountNotifyClients, iDriveNumber, ETrue, aCompletionCode); |
|
2533 FsNotify::HandleDismount(EFsDismountForceDismount, iDriveNumber, ETrue, aCompletionCode); |
|
2534 } |
|
2535 |
|
2536 //---------------------------------------------------------------------------- |
|
2537 /** |
|
2538 a helper method that allows forced dismounting current mount for volume formatting. |
|
2539 */ |
|
2540 TInt TDrive::ForceUnmountFileSystemForFormatting() |
|
2541 { |
|
2542 TInt nRes; |
|
2543 |
|
2544 //-- check if there are any clamps on this drive |
|
2545 nRes = ClampsOnDrive(); |
|
2546 if(nRes > 0) |
|
2547 return KErrInUse; |
|
2548 |
|
2549 //-- purge all dirty data in the files associated with this drive's mount |
|
2550 CDriveThread* pT=NULL; |
|
2551 nRes = FsThreadManager::GetDriveThread(DriveNumber(), &pT); |
|
2552 if(nRes == KErrNone && pT) |
|
2553 { |
|
2554 pT->CompleteReadWriteRequests(); |
|
2555 } |
|
2556 |
|
2557 PurgeDirty(CurrentMount()); |
|
2558 |
|
2559 //-- |
|
2560 |
|
2561 ForceDismount(); |
|
2562 |
|
2563 DoCompleteDismountNotify(KErrDisMounted); //-- complete all dismount notifications |
|
2564 |
|
2565 return KErrNone; |
|
2566 } |
|
2567 |
|
2568 //----------------------------------------------------------------------------- |
|
2569 /** |
|
2570 Instantiate CFormatCB object for formatting the file ssytem on the given TDrive. |
|
2571 |
|
2572 @param aRequest file server request object |
|
2573 @param aFmtHandle out: format handle |
|
2574 @param aFmtMode format mode |
|
2575 @param apLDFormatInfo pointer to legacy parameters structure; NULL means "not used" |
|
2576 @param apVolFormatParam pointer to the newparameters structure; NULL means "not used" |
|
2577 |
|
2578 @return pointer to the instantiated CFormatCB object. |
|
2579 */ |
|
2580 CFormatCB* TDrive::FormatOpenL(CFsRequest* aRequest, TInt& aFmtHandle, TFormatMode aFmtMode, const TLDFormatInfo* apLDFormatInfo, const TVolFormatParam* apVolFormatParam) |
|
2581 { |
|
2582 ASSERT(!(apLDFormatInfo && apVolFormatParam)); //-- these parameters are mutually exclusive |
|
2583 |
|
2584 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewFormatL, EF32TraceUidFileSys, &FSys(), DriveNumber()); |
|
2585 |
|
2586 CFormatCB* pFormat = CurrentMount().NewFormatL(); |
|
2587 |
|
2588 TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewFormatLRet, EF32TraceUidFileSys, KErrNone, pFormat); |
|
2589 |
|
2590 Formats->AddL(pFormat, ETrue); |
|
2591 pFormat->InitL(this, aFmtMode); |
|
2592 |
|
2593 if(aFmtMode & ESpecialFormat) |
|
2594 { |
|
2595 if(apLDFormatInfo) |
|
2596 {//-- the user has specified formatting parameters as TLDFormatInfo |
|
2597 pFormat->SetFormatParameters(apLDFormatInfo); |
|
2598 } |
|
2599 else if(apVolFormatParam && apVolFormatParam->SomeParamsSet()) |
|
2600 {//-- the user has specified formatting parameters as TVolFormatParam |
|
2601 TInt nRes = pFormat->SetFormatParameters(apVolFormatParam); |
|
2602 User::LeaveIfError(nRes); //-- the particular file system might not support this feature |
|
2603 } |
|
2604 else |
|
2605 {//-- this is a special case, ESpecialFormat is set, but no parameters provided at all; |
|
2606 //-- invalidate CFormatCB::iSpecialInfo to make filesystem not to use it |
|
2607 pFormat->SetFormatParameters((TLDFormatInfo*)NULL); |
|
2608 } |
|
2609 } |
|
2610 |
|
2611 |
|
2612 // modify resource counter after initialised to ensure correct cleanup |
|
2613 AddDiskAccess(CurrentMount()); |
|
2614 aFmtHandle = aRequest->Session()->Handles().AddL(pFormat, ETrue); |
|
2615 |
|
2616 return pFormat; |
|
2617 } |
|
2618 |
|
2619 |
|
2620 |
|
2621 |
|
2622 |
|
2623 EXPORT_C void UNUSED1() {} |
|
2624 EXPORT_C void UNUSED2() {} |
|
2625 EXPORT_C void UNUSED3() {} |
|
2626 |
|
2627 |
|
2628 |
|
2629 |
|
2630 |
|
2631 |
|
2632 |
|
2633 |
|
2634 |