80 TInt r=LocalDrive()->Read(aMediaPos, KSizeOfFatBootSector, bootSecBuf); |
89 TInt r=LocalDrive()->Read(aMediaPos, KSizeOfFatBootSector, bootSecBuf); |
81 if (r != KErrNone) |
90 if (r != KErrNone) |
82 { |
91 { |
83 __PRINT2(_L("CFatMountCB::DoReadBootSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r); |
92 __PRINT2(_L("CFatMountCB::DoReadBootSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r); |
84 |
93 |
85 //-- fiddling with the error code; taken from MountL() |
94 //-- fiddling with the error code; taken from MountL() |
86 if (r==KErrNotSupported) |
95 if (r==KErrNotSupported) |
87 return KErrNotReady; |
96 return KErrNotReady; |
88 #if defined(_LOCKABLE_MEDIA) |
97 #if defined(_LOCKABLE_MEDIA) |
89 else if(r==KErrLocked) |
98 else if(r==KErrLocked) |
90 return KErrLocked; |
99 return KErrLocked; |
91 #endif |
100 #endif |
92 else if (r!=KErrNoMemory && r!=KErrNotReady && r!=KErrCorrupt && r!=KErrUnknown) |
101 else if (r!=KErrNoMemory && r!=KErrNotReady && r!=KErrCorrupt && r!=KErrUnknown) |
93 return KErrCorrupt; |
102 return KErrCorrupt; |
94 |
103 |
95 return r; |
104 return r; |
96 } |
105 } |
97 |
106 |
155 |
164 |
156 @param aVolumeLabel Descriptor containing the new volume label |
165 @param aVolumeLabel Descriptor containing the new volume label |
157 @leave |
166 @leave |
158 */ |
167 */ |
159 void CFatMountCB::WriteVolumeLabelL(const TDesC8& aVolumeLabel) const |
168 void CFatMountCB::WriteVolumeLabelL(const TDesC8& aVolumeLabel) const |
160 { |
169 { |
161 if(aVolumeLabel.Length() > KVolumeLabelSize) |
170 if(aVolumeLabel.Length() > KVolumeLabelSize) |
162 User::Leave(KErrArgument); |
171 User::Leave(KErrArgument); |
163 |
172 |
164 User::LeaveIfError(LocalDrive()->Write(KFat16VolumeLabelPos,aVolumeLabel)); |
173 User::LeaveIfError(LocalDrive()->Write(KFat16VolumeLabelPos,aVolumeLabel)); |
165 } |
174 } |
166 |
175 |
167 |
176 |
168 |
177 |
169 //------------------------------------------------------------------------------------------------------------------- |
178 //------------------------------------------------------------------------------------------------------------------- |
170 |
179 |
171 const TUint16 KFat16CleanShutDownMask = 0x08000; ///< Mask used to indicate test clean/dirty bit for Fat16 |
180 const TUint16 KFat16CleanShutDownMask = 0x08000; ///< Mask used to indicate test clean/dirty bit for Fat16 |
172 |
181 |
173 /** |
182 /** |
174 Set or reset "VolumeClean" (ClnShutBitmask) flag. |
183 Set or reset "VolumeClean" (ClnShutBitmask) flag. |
175 |
184 |
176 @param aClean if ETrue, marks the volume as clean, otherwise as dirty. |
185 @param aClean if ETrue, marks the volume as clean, otherwise as dirty. |
177 @leave if write error occured. |
186 @leave if write error occured. |
178 */ |
187 */ |
179 void CFatMountCB::SetVolumeCleanL(TBool aClean) |
188 void CFatMountCB::SetVolumeCleanL(TBool aClean) |
180 { |
189 { |
181 //-- The volume can't be set clean if there are objects opened on it. This precondition must be checked before calling this function |
190 //-- The volume can't be set clean if there are objects opened on it. This precondition must be checked before calling this function |
182 if(aClean && LockStatus()!=0) |
191 if(aClean && LockStatus()!=0) |
183 { |
192 { |
184 __PRINT1(_L("#- CFatMountCB::SetVolumeCleanL drive:%d isn't free!"),DriveNumber()); |
193 __PRINT1(_L("#- CFatMountCB::SetVolumeCleanL drive:%d isn't free!"),DriveNumber()); |
185 ASSERT(0); |
194 ASSERT(0); |
186 User::Leave(KErrInUse); |
195 User::Leave(KErrInUse); |
187 return; |
196 return; |
188 } |
197 } |
189 |
198 |
190 if(FatType() == EFat12) |
199 if(FatType() == EFat12) |
191 {//-- Fat12 doesn't support this feature; do nothing other than notify the underlying drive |
200 {//-- Fat12 doesn't support this feature; do nothing other than notify the underlying drive |
192 // (ignoring any error for now as there's nothing we can do with it) |
201 // (ignoring any error for now as there's nothing we can do with it) |
193 (void)LocalDrive()->Finalise(aClean); |
202 (void)LocalDrive()->Finalise(aClean); |
194 return; |
203 return; |
195 } |
204 } |
196 |
205 |
197 //-- further read and write will be directly from the CProxyDrive, bypassing FAT cache. |
206 //-- further read and write will be directly from the CProxyDrive, bypassing FAT cache. |
198 //-- this is because CFatTable doesn't allow access to FAT[1] |
207 //-- this is because CFatTable doesn't allow access to FAT[1] |
199 |
208 |
223 { |
232 { |
224 const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i); |
233 const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i); |
225 User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT16[1] entry |
234 User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT16[1] entry |
226 } |
235 } |
227 } |
236 } |
228 |
237 |
229 //-- Notify the underlying media that the mount is consistent |
238 //-- Notify the underlying media that the mount is consistent |
230 // (ignoring any error for now as there's nothing we can do with it) |
239 // (ignoring any error for now as there's nothing we can do with it) |
231 (void)LocalDrive()->Finalise(aClean); |
240 (void)LocalDrive()->Finalise(aClean); |
232 |
241 |
233 __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry: %x->%x"), tmp, fatEntry); |
242 __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry: %x->%x"), tmp, fatEntry); |
234 |
243 |
235 } |
244 } |
236 else //if(FatConfig().FAT16_UseCleanShutDownBit()) |
245 else //if(FatConfig().FAT16_UseCleanShutDownBit()) |
282 |
291 |
283 @param aForceMount Flag to indicate whether mount should be forced to succeed if an error occurs |
292 @param aForceMount Flag to indicate whether mount should be forced to succeed if an error occurs |
284 @leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown. |
293 @leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown. |
285 */ |
294 */ |
286 void CFatMountCB::MountL(TBool aForceMount) |
295 void CFatMountCB::MountL(TBool aForceMount) |
287 { |
296 { |
288 const TInt driveNo = Drive().DriveNumber(); |
297 const TInt driveNo = Drive().DriveNumber(); |
289 |
298 |
290 __PRINT2(_L("CFatMountCB::MountL() drv:%d, forceMount=%d\n"),driveNo,aForceMount); |
299 __PRINT2(_L("CFatMountCB::MountL() drv:%d, forceMount=%d\n"),driveNo,aForceMount); |
291 |
300 |
292 ASSERT(State() == ENotMounted || State() == EDismounted); |
301 ASSERT(State() == ENotMounted || State() == EDismounted); |
293 SetState(EMounting); |
302 SetState(EMounting); |
294 SetReadOnly(EFalse); |
303 SetReadOnly(EFalse); |
295 |
304 |
296 |
305 |
297 User::LeaveIfError(CreateDrive(Drive().DriveNumber())); |
306 User::LeaveIfError(CreateDrive(Drive().DriveNumber())); |
298 |
307 |
299 //-- read FAT configuration parameters from estart.txt |
308 //-- read FAT configuration parameters from estart.txt |
300 iFatConfig.ReadConfig(driveNo); |
309 iFatConfig.ReadConfig(driveNo); |
301 |
310 |
302 |
311 |
303 //-- initialise interface to the low-level drive access |
312 //-- initialise interface to the low-level drive access |
304 if(!iDriverInterface.Init(this)) |
313 if(!iDriverInterface.Init(this)) |
305 User::LeaveIfError(KErrNoMemory); |
314 User::LeaveIfError(KErrNoMemory); |
306 |
315 |
307 //-- get drive capabilities |
316 //-- get drive capabilities |
308 TLocalDriveCapsV2Buf capsBuf; |
317 TLocalDriveCapsV2Buf capsBuf; |
309 User::LeaveIfError(LocalDrive()->Caps(capsBuf)); |
318 User::LeaveIfError(LocalDrive()->Caps(capsBuf)); |
310 |
319 |
311 iSize=capsBuf().iSize; |
320 iSize=capsBuf().iSize; |
312 iRamDrive = EFalse; |
321 iRamDrive = EFalse; |
313 |
322 |
314 if(capsBuf().iMediaAtt & KMediaAttVariableSize) |
323 if(capsBuf().iMediaAtt & KMediaAttVariableSize) |
315 {//-- this is a RAM drive |
324 {//-- this is a RAM drive |
316 UserSvr::UnlockRamDrive(); |
325 UserSvr::UnlockRamDrive(); |
317 iRamDrive = ETrue; |
326 iRamDrive = ETrue; |
318 } |
327 } |
319 |
328 |
320 if(aForceMount) |
329 if(aForceMount) |
321 {//-- the state is "forcedly mounted", special case. This is an inconsistent state. |
330 {//-- the state is "forcedly mounted", special case. This is an inconsistent state. |
322 SetState(EInit_Forced); |
331 SetState(EInit_Forced); |
323 return; |
332 return; |
324 } |
333 } |
325 |
334 |
326 //-- read and validate boot sector (sector 0) |
335 //-- read and validate boot sector (sector 0) |
327 TFatBootSector bootSector; |
336 TFatBootSector bootSector; |
328 User::LeaveIfError(ReadBootSector(bootSector, iRamDrive)); |
337 User::LeaveIfError(ReadBootSector(bootSector, iRamDrive)); |
329 |
338 |
330 //-- print out boot sector debug information |
339 //-- print out boot sector debug information |
331 bootSector.PrintDebugInfo(); |
340 bootSector.PrintDebugInfo(); |
332 |
341 |
333 //-- determine FAT type by data from boot sector. This is done by counting number of clusters, not by BPB_RootEntCnt |
342 //-- determine FAT type by data from boot sector. This is done by counting number of clusters, not by BPB_RootEntCnt |
334 iFatType=bootSector.FatType(); |
343 iFatType=bootSector.FatType(); |
335 ASSERT(iFatType != EInvalid); //-- this shall be checked in ReadBootSector() |
344 ASSERT(iFatType != EInvalid); //-- this shall be checked in ReadBootSector() |
336 |
345 |
337 //-- values from the boot sector are checked in TFatBootSector::IsValid() |
346 //-- values from the boot sector are checked in TFatBootSector::IsValid() |
338 //-- store volume UID, it can be checked on Remount |
347 //-- store volume UID, it can be checked on Remount |
359 |
368 |
360 @param aLocDrvCaps local drive capabilities |
369 @param aLocDrvCaps local drive capabilities |
361 @leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown. |
370 @leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown. |
362 */ |
371 */ |
363 void CFatMountCB::InitializeL(const TLocalDriveCaps& aLocDrvCaps, TBool /*aIgnoreFSInfo=EFalse*/) |
372 void CFatMountCB::InitializeL(const TLocalDriveCaps& aLocDrvCaps, TBool /*aIgnoreFSInfo=EFalse*/) |
364 { |
373 { |
365 __PRINT1(_L("CFatMountCB::InitializeL() drv:%d"), DriveNumber()); |
374 __PRINT1(_L("CFatMountCB::InitializeL() drv:%d"), DriveNumber()); |
366 |
375 |
367 ASSERT(State() == EMounting); //-- we must get here only from MountL() |
376 ASSERT(State() == EMounting); //-- we must get here only from MountL() |
368 |
377 |
369 //========== Find out number of clusters on the volume |
378 //========== Find out number of clusters on the volume |
370 if(iRamDrive && SectorsPerCluster()!=1) |
379 if(iRamDrive && SectorsPerCluster()!=1) |
371 {// Align iFirstFreeByte to cluster boundary if internal ram drive |
380 {// Align iFirstFreeByte to cluster boundary if internal ram drive |
372 const TInt sectorsPerClusterLog2=ClusterSizeLog2()-SectorSizeLog2(); |
381 const TInt sectorsPerClusterLog2=ClusterSizeLog2()-SectorSizeLog2(); |
373 const TInt rootDirEndSector=RootDirEnd()>>SectorSizeLog2(); |
382 const TInt rootDirEndSector=RootDirEnd()>>SectorSizeLog2(); |
374 const TInt alignedSector=((rootDirEndSector+SectorsPerCluster()-1)>>sectorsPerClusterLog2)<<sectorsPerClusterLog2; |
383 const TInt alignedSector=((rootDirEndSector+SectorsPerCluster()-1)>>sectorsPerClusterLog2)<<sectorsPerClusterLog2; |
375 iFirstFreeByte=alignedSector<<SectorSizeLog2(); |
384 iFirstFreeByte=alignedSector<<SectorSizeLog2(); |
376 } |
385 } |
377 else |
386 else |
378 { |
387 { |
379 iFirstFreeByte=RootDirEnd(); |
388 iFirstFreeByte=RootDirEnd(); |
380 } |
389 } |
381 |
390 |
382 |
391 |
383 {//-- check if volume geometry looks valid |
392 {//-- check if volume geometry looks valid |
384 const TInt usableSectors=TotalSectors()-(iFirstFreeByte>>SectorSizeLog2()); |
393 const TInt usableSectors=TotalSectors()-(iFirstFreeByte>>SectorSizeLog2()); |
385 iUsableClusters=usableSectors>>(ClusterSizeLog2()-SectorSizeLog2()); |
394 iUsableClusters=usableSectors>>(ClusterSizeLog2()-SectorSizeLog2()); |
386 |
395 |
387 const TUint32 KMinClusters = 32; //-- absolute minimum number of clusters on the volume |
396 const TUint32 KMinClusters = 32; //-- absolute minimum number of clusters on the volume |
388 const TUint32 KMaxClusters =(TotalSectors()-FirstFatSector()-NumberOfFats()*(FatSizeInBytes()>>SectorSizeLog2())) >> (ClusterSizeLog2()-SectorSizeLog2()); |
397 const TUint32 KMaxClusters =(TotalSectors()-FirstFatSector()-NumberOfFats()*(FatSizeInBytes()>>SectorSizeLog2())) >> (ClusterSizeLog2()-SectorSizeLog2()); |
389 |
398 |
390 if(usableSectors <=0 || iUsableClusters < KMinClusters || iUsableClusters > KMaxClusters) |
399 if(usableSectors <=0 || iUsableClusters < KMinClusters || iUsableClusters > KMaxClusters) |
393 User::Leave(KErrCorrupt); |
402 User::Leave(KErrCorrupt); |
394 } |
403 } |
395 } |
404 } |
396 |
405 |
397 |
406 |
398 //========== initialise RawDisk interface |
407 //========== initialise RawDisk interface |
399 //-- CFatMountCB parameters might have changed, e.g. after formatting. Reconstruct directory cache with new parameters |
408 //-- CFatMountCB parameters might have changed, e.g. after formatting. Reconstruct directory cache with new parameters |
400 |
409 |
401 delete iRawDisk; |
410 delete iRawDisk; |
402 iRawDisk=CRawDisk::NewL(*this, aLocDrvCaps); |
411 iRawDisk=CRawDisk::NewL(*this, aLocDrvCaps); |
403 iRawDisk->InitializeL(); |
412 iRawDisk->InitializeL(); |
404 |
413 |
405 |
414 |
406 //========== create FAT table object |
415 //========== create FAT table object |
407 delete iFatTable; |
416 delete iFatTable; |
408 iFatTable=CFatTable::NewL(*this, aLocDrvCaps); |
417 iFatTable=CFatTable::NewL(*this, aLocDrvCaps); |
409 |
418 |
410 //========== create and setup leaf direcotry cache if cache limit is set bigger than one |
419 //========== create and setup leaf direcotry cache if cache limit is set bigger than one |
411 const TUint32 cacheLimit = iFatConfig.LeafDirCacheSize(); |
420 const TUint32 cacheLimit = iFatConfig.LeafDirCacheSize(); |
412 if (cacheLimit > 1) |
421 if (cacheLimit > 1) |
413 { |
422 { |
414 // destroy the old leaf dir cache to avoid memory leak. |
423 // destroy the old leaf dir cache to avoid memory leak. |
415 delete iLeafDirCache; |
424 delete iLeafDirCache; |
416 iLeafDirCache = CLeafDirCache::NewL(cacheLimit); |
425 iLeafDirCache = CLeafDirCache::NewL(cacheLimit); |
417 } |
426 } |
418 else |
427 else |
419 { |
428 { |
420 iLeafDirCache = NULL; |
429 iLeafDirCache = NULL; |
421 } |
430 } |
422 |
431 |
423 //========== find out free clusters number on the volume |
432 //========== find out free clusters number on the volume |
424 FAT().CountFreeClustersL(); |
433 FAT().CountFreeClustersL(); |
425 |
434 |
426 SetState(EInit_R); //-- the state is "Initialized, but not writen" |
435 SetState(EInit_R); //-- the state is "Initialized, but not writen" |
428 //-- make a callback, telling FileServer about free space discovered. |
437 //-- make a callback, telling FileServer about free space discovered. |
429 const TInt64 freeSpace = ((TInt64)FAT().NumberOfFreeClusters()) << ClusterSizeLog2(); |
438 const TInt64 freeSpace = ((TInt64)FAT().NumberOfFreeClusters()) << ClusterSizeLog2(); |
430 SetDiskSpaceChange(freeSpace); |
439 SetDiskSpaceChange(freeSpace); |
431 |
440 |
432 __PRINT3(_L("#- CFatMountCB::InitializeL() done. drv:%d, Free clusters:%d, 1st Free cluster:%d"),DriveNumber(), FAT().NumberOfFreeClusters(), FAT().FreeClusterHint()); |
441 __PRINT3(_L("#- CFatMountCB::InitializeL() done. drv:%d, Free clusters:%d, 1st Free cluster:%d"),DriveNumber(), FAT().NumberOfFreeClusters(), FAT().FreeClusterHint()); |
433 } |
442 } |
434 |
443 |
435 //------------------------------------------------------------------------------------------------------------------- |
444 //------------------------------------------------------------------------------------------------------------------- |
436 |
445 |
437 |
446 |
438 |
447 |
441 |
450 |
442 @param aCluster Cluster to check |
451 @param aCluster Cluster to check |
443 @return Result of test |
452 @return Result of test |
444 */ |
453 */ |
445 TBool CFatMountCB::IsEndOfClusterCh(TInt aCluster) const |
454 TBool CFatMountCB::IsEndOfClusterCh(TInt aCluster) const |
446 { |
455 { |
447 if(Is16BitFat()) |
456 if(Is16BitFat()) |
448 return(aCluster>=0xFFF8 && aCluster<=0xFFFF); |
457 return(aCluster>=0xFFF8 && aCluster<=0xFFFF); |
449 else |
458 else |
450 return(aCluster>=0xFF8 && aCluster<=0xFFF); |
459 return(aCluster>=0xFF8 && aCluster<=0xFFF); |
451 } |
460 } |
452 |
461 |
453 /** |
462 /** |
454 Set a cluster to the end of cluster chain marker |
463 Set a cluster to the end of cluster chain marker |
455 |
464 |
456 @param aCluster cluster to set to end of chain marker |
465 @param aCluster cluster to set to end of chain marker |
457 */ |
466 */ |
458 void CFatMountCB::SetEndOfClusterCh(TInt &aCluster) const |
467 void CFatMountCB::SetEndOfClusterCh(TInt &aCluster) const |
459 { |
468 { |
460 if(Is16BitFat()) |
469 if(Is16BitFat()) |
461 aCluster=0xFFF8; |
470 aCluster=0xFFF8; |
462 else |
471 else |
463 aCluster=0xFF8; |
472 aCluster=0xFF8; |
464 } |
473 } |
465 |
474 |
466 /** |
475 /** |
467 Initialize data to represent the root directory |
476 Initialize data to represent the root directory |
468 |
477 |
469 @param anEntry Entry to initialise |
478 @param anEntry Entry to initialise |
470 */ |
479 */ |
471 void CFatMountCB::InitializeRootEntry(TFatDirEntry & anEntry) const |
480 void CFatMountCB::InitializeRootEntry(TFatDirEntry & anEntry) const |
472 { |
481 { |
473 anEntry.SetName(_L8("ROOT")); |
482 anEntry.SetName(_L8("ROOT")); |
474 anEntry.SetAttributes(KEntryAttDir); |
483 anEntry.SetAttributes(KEntryAttDir); |
475 anEntry.SetStartCluster(0); |
484 anEntry.SetStartCluster(0); |
476 } |
485 } |
477 |
486 |
478 |
487 |
479 /** |
488 /** |
480 Implementation of CMountCB::FileSystemSubType(). Retrieves the sub type of Fat file system |
489 Implementation of CMountCB::FileSystemSubType(). Retrieves the sub type of Fat file system |
481 and returns the name as a descriptor. |
490 and returns the name as a descriptor. |
482 |
491 |
483 @param aName Name of the sub type of Fat file system |
492 @param aName Name of the sub type of Fat file system |
484 @return KErrNone if successful; KErrArgument if aName is not long enough; KErrNotReady if |
493 @return KErrNone if successful; KErrArgument if aName is not long enough; KErrNotReady if |
485 the mount is not ready. |
494 the mount is not ready. |
486 |
495 |
487 @see CMountCB::FileSystemSubType() |
496 @see CMountCB::FileSystemSubType() |
488 */ |
497 */ |
489 TInt CFatMountCB::SubType(TDes& aName) const |
498 TInt CFatMountCB::SubType(TDes& aName) const |
490 { |
499 { |
491 if(aName.MaxLength() < 5) |
500 if(aName.MaxLength() < 5) |
492 return KErrArgument; |
501 return KErrArgument; |
493 |
502 |
494 switch (iFatType) |
503 switch (iFatType) |
495 { |
504 { |
496 case EFat12: |
505 case EFat12: |
497 { |
506 { |
498 aName = KFSSubType_FAT12; |
507 aName = KFSSubType_FAT12; |
499 return KErrNone; |
508 return KErrNone; |
500 } |
509 } |
501 case EFat16: |
510 case EFat16: |
502 { |
511 { |
503 aName = KFSSubType_FAT16; |
512 aName = KFSSubType_FAT16; |
504 return KErrNone; |
513 return KErrNone; |
505 } |
514 } |
506 default: |
515 default: |
507 // case EInvalidFatType |
516 // case EInvalidFatType |
508 return KErrNotReady; |
517 return KErrNotReady; |
509 } |
518 } |
510 } |
519 } |
511 |
520 |
512 //------------------------------------------------------------------------------------------------------------------- |
521 //------------------------------------------------------------------------------------------------------------------- |
513 /** |
522 /** |
514 CFatMountCB control method. |
523 CFatMountCB control method. |
515 @param aLevel specifies the operation to perfrom on the mount |
524 @param aLevel specifies the operation to perfrom on the mount |