userlibandfileserver/fileserver/smassstorage/cmassstoragemountcb.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
child 21 e7d2d738d3c2
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// CMassStorageMountCB implementation.
// 
//

/**
 @file
 @internalTechnology
*/

#include <f32fsys.h>
#include <f32file.h>
#include "cmassstoragemountcb.h"
#include "cmassstoragefilesystem.h"
#include "drivemanager.h"
#include "massstoragedebug.h"
#include "massstorageutil.h"

CMassStorageMountCB::CMassStorageMountCB(const RArray<TInt>& aDriveMapping)
    : iDriveMapping(aDriveMapping)
	{
	}

CMassStorageMountCB* CMassStorageMountCB::NewL(const RArray<TInt>& aDriveMapping)
	{
	return new (ELeave) CMassStorageMountCB(aDriveMapping);
	}

/**
Checks that the drive number is supported.

@leave KErrNotReady The drive number is not supported.
*/
TInt CMassStorageMountCB::CheckDriveNumberL()
	{
	__FNLOG("CMassStorageMountCB::CheckDriveNumberL");
	TInt driveNumber;
	driveNumber = Drive().DriveNumber();
	if (!IsValidLocalDriveMapping(driveNumber))
		{
		__PRINT1(_L("CMassStorageMountCB::CheckDriveNumberL: Drive number %d not supported"), driveNumber);
		User::Leave(KErrNotReady);
		}
	__PRINT1(_L("CMassStorageMountCB::CheckDriveNumberL: Drive number = %d"), driveNumber);
	return driveNumber;
	}

/**
Registers the drive with the Mass Storage drive manager.

@leave KErrNotSupported The drive is not compatible with Mass Storage.
*/
void CMassStorageMountCB::MountL(TBool /*aForceMount*/)
	{
	__FNLOG("CMassStorageMountCB::MountL");

	CheckDriveNumberL();
	CMassStorageFileSystem& msFsys = *reinterpret_cast<CMassStorageFileSystem*>(Drive().GetFSys());

	TInt lun = DriveNumberToLun(Drive().DriveNumber());

	if(lun < 0)
		{
		// This is not a supported Mass Storage drive
		User::Leave(KErrNotSupported);
		}

	TBusLocalDrive& localDrive = msFsys.iLocalDriveForMediaFlag[lun];

	TInt err = CreateLocalDrive(localDrive);
	User::LeaveIfError(err);

	CProxyDrive* proxyDrive = LocalDrive();

	TLocalDriveCapsV2Buf caps;
	err = localDrive.Caps(caps);
	//Make sure file system is FAT and removable
	if (err == KErrNone)
		{
		err = KErrNotSupported;
		if ((caps().iDriveAtt & KDriveAttRemovable) == KDriveAttRemovable)
			{
			if (caps().iType != EMediaNotPresent)
				{
				err = KErrNone;
				}
			}
		}

	if (err != KErrNone && err != KErrNotReady)
		{
		__PRINT1(_L("CMassStorageMountCB::MountL: Drive is not compatible with Mass Storage, err=%d"), err);
		User::Leave(err);
		}

	__PRINT(_L("CMassStorageMountCB::MountL: Registering drive"));

	// Set media changed to true so that Win2K doesn't used cached drive data
	(*msFsys.iMediaChanged)[lun] = ETrue;

	msFsys.Controller().DriveManager().RegisterDrive(*proxyDrive, (*msFsys.iMediaChanged)[lun], lun);

	SetVolumeName(_L("MassStorage").AllocL());
	}

/**
Returns the LUN that corresponds to the specified drive number.

@param aDriveNumber The drive number.
*/
TInt CMassStorageMountCB::DriveNumberToLun(TInt aDriveNumber)
	{
	__FNLOG("CMassStorageMountCB::DriveNumberToLun");
	TInt lun = -1;
	for (TInt i = 0; i < iDriveMapping.Count(); i++)
		{
		if (iDriveMapping[i] == aDriveNumber)
			{
			lun = i;
			break;
			}
		}
	__PRINT2(_L("CMassStorageMountCB::DriveNumberToLun: Drive %d maps to LUN %d"), aDriveNumber, lun);
	return lun;
	}

/**
Deregisters the drive from the Drive Manager.
*/
void CMassStorageMountCB::Dismounted()
	{
	__FNLOG("CMassStorageMountCB::Dismounted");
	TInt driveNumber = -1;
	TRAPD(err, driveNumber = CheckDriveNumberL());
	if (err != KErrNone)
		{
		return;
		}
	__PRINT(_L("CMassStorageMountCB::Dismounted: Deregistering drive"));
    CMassStorageFileSystem& msFsys = *reinterpret_cast<CMassStorageFileSystem*>(Drive().GetFSys());
	msFsys.Controller().DriveManager().DeregisterDrive(DriveNumberToLun(driveNumber));
	
	DismountedLocalDrive();
	}

/**
Unlocks the drive with the specified password, optionally storing the password for later use.

@param aPassword The password to use for unlocking the drive.
@param aStore True if the password is to be stored.
*/
TInt CMassStorageMountCB::Unlock(TMediaPassword& aPassword, TBool aStore)
	{
	__FNLOG("CMassStorageMountCB::Unlock");
	TInt driveNumber = -1;
	TRAPD(err, driveNumber = CheckDriveNumberL());
	if (err != KErrNone)
		{
		return err;
		}
	TBusLocalDrive& localDrive=GetLocalDrive(driveNumber);
	if(localDrive.Status() == KErrLocked)
		{
		localDrive.Status() = KErrNotReady;
		}
	TInt r = localDrive.Unlock(aPassword, aStore);
	if(r == KErrNone && aStore)
		{
		WritePasswordData();
		}
	return(r);
	}

/**
Stores the password for the drive to the password file.
*/
void CMassStorageMountCB::WritePasswordData()
	{
	__FNLOG("CMassStorageMountCB::WritePasswordData");
	TBusLocalDrive& local=GetLocalDrive(Drive().DriveNumber());
	TInt length = local.PasswordStoreLengthInBytes();
	if(length==0)
		{
		TBuf<sizeof(KMediaPWrdFile)> mediaPWrdFile(KMediaPWrdFile);
		mediaPWrdFile[0] = (TUint8) RFs::GetSystemDriveChar();
		WriteToDisk(mediaPWrdFile,_L8(""));
		return;
		}
	HBufC8* hDes=HBufC8::New(length);
	if(hDes==NULL)
		{
		return;
		}
	TPtr8 pDes=hDes->Des();
	TInt r=local.ReadPasswordData(pDes);
	if(r==KErrNone)
		{
		TBuf<sizeof(KMediaPWrdFile)> mediaPWrdFile(KMediaPWrdFile);
		mediaPWrdFile[0] = (TUint8) RFs::GetSystemDriveChar();
		WriteToDisk(mediaPWrdFile,pDes);
		}
	delete hDes;
	}

/**
Make sure that the file system is fat.
*/
TBool CMassStorageMountCB::ValidateBootSector()
	{
	__FNLOG("CMassStorageMountCB::ValidateBootSector");

	TFatBootSector bootSector;
	TInt r=ReadBootSector(bootSector);
	__PRINT1(_L("CMassStorageMountCB::MountL - ReadBootSector returned %d"),r);
	if (r != KErrNone)
		{
		return EFalse;
		}

	__PRINT(_L("\nBootSector info"));
	__PRINT8BIT1(_L("FAT type = %S"),bootSector.FileSysType());
	__PRINT8BIT1(_L("Vendor ID = %S"),bootSector.VendorId());
	__PRINT1(_L("BytesPerSector %d"),bootSector.BytesPerSector());
	__PRINT1(_L("SectorsPerCluster %d"),bootSector.SectorsPerCluster());
	__PRINT1(_L("ReservedSectors %d"),bootSector.ReservedSectors());
	__PRINT1(_L("NumberOfFats %d"),bootSector.NumberOfFats());
	__PRINT1(_L("RootDirEntries %d"),bootSector.RootDirEntries());
	__PRINT1(_L("Total Sectors = %d"),bootSector.TotalSectors());
	__PRINT1(_L("MediaDescriptor = 0x%x"),bootSector.MediaDescriptor());
	__PRINT1(_L("FatSectors %d"),bootSector.FatSectors());
	__PRINT1(_L("SectorsPerTrack %d"),bootSector.SectorsPerTrack());
	__PRINT1(_L("NumberOfHeads %d"),bootSector.NumberOfHeads());
	__PRINT1(_L("HugeSectors %d"),bootSector.HugeSectors());
	__PRINT1(_L("Fat32 Sectors %d"),bootSector.FatSectors32());
	__PRINT1(_L("Fat32 Flags %d"),bootSector.FATFlags());
	__PRINT1(_L("Fat32 Version Number %d"),bootSector.VersionNumber());
	__PRINT1(_L("Root Cluster Number %d"),bootSector.RootClusterNum());
	__PRINT1(_L("FSInfo Sector Number %d"),bootSector.FSInfoSectorNum());
	__PRINT1(_L("Backup Boot Rec Sector Number %d"),bootSector.BkBootRecSector());
	__PRINT1(_L("PhysicalDriveNumber %d"),bootSector.PhysicalDriveNumber());
	__PRINT1(_L("ExtendedBootSignature %d"),bootSector.ExtendedBootSignature());
	__PRINT1(_L("UniqueID %d"),bootSector.UniqueID());
	__PRINT8BIT1(_L("VolumeLabel %S"),bootSector.VolumeLabel());
	__PRINT8BIT1(_L("FileSysType %S\n"),bootSector.FileSysType());

    iUniqueID=bootSector.UniqueID();
	iIs16BitFat=bootSector.Is16BitFat();

	iIs32BitFat=bootSector.Is32BitFat();
	switch (DetermineFatType(bootSector))
		{
		case 12:
			iIs16BitFat = EFalse;
			iIs32BitFat = EFalse;
			break;
		case 16:
			iIs16BitFat = ETrue;
			iIs32BitFat = EFalse;
			break;
		case 32:
			iIs16BitFat = EFalse;
			iIs32BitFat = ETrue;
			break;
		default:
			return EFalse;
		}

	TInt sectorsPerCluster=bootSector.SectorsPerCluster();
	if (!IsPowerOfTwo(sectorsPerCluster))
		return EFalse;

	TInt sectorSizeLog2=Log2(bootSector.BytesPerSector());
	if (sectorSizeLog2<0 || !IsPowerOfTwo(bootSector.BytesPerSector()))
		return EFalse;

	TInt firstFatSector=bootSector.ReservedSectors();
	if (firstFatSector<1)
		return EFalse;

	TInt fatSizeInBytes;
	if(iIs32BitFat)
		{
		fatSizeInBytes=bootSector.FatSectors32()*bootSector.BytesPerSector();
		if (fatSizeInBytes<bootSector.BytesPerSector())
			return EFalse;
		}
	else
		{
		fatSizeInBytes=bootSector.FatSectors()*bootSector.BytesPerSector();
		if (fatSizeInBytes<bootSector.BytesPerSector())
			return EFalse;

		TInt rootDirectorySector=firstFatSector+bootSector.FatSectors()*bootSector.NumberOfFats();
		if (rootDirectorySector<3)
			return EFalse;

		TInt rootDirSizeInBytes=bootSector.RootDirEntries()*KSizeOfFatDirEntry;
		TInt numOfRootDirSectors=(rootDirSizeInBytes+(1<<sectorSizeLog2)-1)>>sectorSizeLog2;
		TInt rootDirEnd=(rootDirectorySector+numOfRootDirSectors)<<sectorSizeLog2;
		if (rootDirEnd<(4<<sectorSizeLog2))
			return EFalse;
		}


	TInt totalSectors=bootSector.TotalSectors();
	if (totalSectors==0)
		totalSectors=bootSector.HugeSectors();
	if (totalSectors<5)
		return EFalse;

	TInt numberOfFats=bootSector.NumberOfFats();
	if (numberOfFats<1)
		return EFalse;

	return ETrue;
	}

/**
Read non aligned boot data from media into TFatBootSector structure

@param aBootSector refrence to TFatBootSector populate
@return Media read error code
*/
TInt CMassStorageMountCB::ReadBootSector(TFatBootSector& aBootSector)
	{
	__FNLOG("CMassStorageMountCB::ReadBootSector");
	TInt pos=0;
	TUint8 data[KSizeOfFatBootSector];
    TPtr8 buf(&data[0],KSizeOfFatBootSector);
    TInt r=LocalDrive()->Read(0,KSizeOfFatBootSector,buf);
	if (r!=KErrNone)
		{
		__PRINT1(_L("LocalDrive::Read() failed - %d"),r);
		return(r);
		}
//	0	TUint8 iJumpInstruction[3]
	Mem::Copy(&aBootSector.iJumpInstruction,&data[pos],3);
	pos+=3;
// 3	TUint8 iVendorId[KVendorIdSize]
	Mem::Copy(&aBootSector.iVendorId,&data[pos],KVendorIdSize);
	pos+=KVendorIdSize;
// 11	TUint16 iBytesPerSector
	Mem::Copy(&aBootSector.iBytesPerSector,&data[pos],2);
	pos+=2;
// 13	TUint8 sectorsPerCluster
	Mem::Copy(&aBootSector.iSectorsPerCluster,&data[pos],1);
	pos+=1;
// 14	TUint16 iReservedSectors
	Mem::Copy(&aBootSector.iReservedSectors,&data[pos],2);
	pos+=2;
// 16	TUint8 numberOfFats
	Mem::Copy(&aBootSector.iNumberOfFats,&data[pos],1);
	pos+=1;
// 17	TUint16 iRootDirEntries
	Mem::Copy(&aBootSector.iRootDirEntries,&data[pos],2);
	pos+=2;
// 19	TUint16 totalSectors
	Mem::Copy(&aBootSector.iTotalSectors,&data[pos],2);
	pos+=2;
// 21	TUint8 iMediaDescriptor
	Mem::Copy(&aBootSector.iMediaDescriptor,&data[pos],1);
	pos+=1;
// 22	TUint16 iFatSectors
	Mem::Copy(&aBootSector.iFatSectors,&data[pos],2);
	pos+=2;
// 24	TUint16 iSectorsPerTrack
	Mem::Copy(&aBootSector.iSectorsPerTrack,&data[pos],2);
	pos+=2;
// 26	TUint16 iNumberOfHeads
	Mem::Copy(&aBootSector.iNumberOfHeads,&data[pos],2);
	pos+=2;
// 28	TUint32 iHiddenSectors
	Mem::Copy(&aBootSector.iHiddenSectors,&data[pos],4);
	pos+=4;
// 32	TUint32 iHugeSectors
	Mem::Copy(&aBootSector.iHugeSectors,&data[pos],4);
	pos+=4;

	if(aBootSector.iRootDirEntries == 0)	//indicates we have FAT32 volume
		{
		__PRINT(_L("\nFile system thinks Fat32"));

		//36 TUint32 iFatSectors32
		Mem::Copy(&aBootSector.iFatSectors32, &data[pos],4);
		pos+=4;
		//40 TUint16 iFATFlags
		Mem::Copy(&aBootSector.iFATFlags, &data[pos],2);
		pos+=2;
		//42 TUint16 iVersionNumber
		Mem::Copy(&aBootSector.iVersionNumber, &data[pos],2);
		pos+=2;
		//44 TUint32 iRootClusterNum
		Mem::Copy(&aBootSector.iRootClusterNum, &data[pos],4);
		pos+=4;
		//48 TUint16 iFSInfoSectorNum
		Mem::Copy(&aBootSector.iFSInfoSectorNum, &data[pos],2);
		pos+=2;
		//50 TUint16 iBkBootRecSector
		Mem::Copy(&aBootSector.iBkBootRecSector, &data[pos],2);
		pos+=(2+12);//extra 12 for the reserved bytes
		}

// 36|64	TUint8 iPhysicalDriveNumber
	Mem::Copy(&aBootSector.iPhysicalDriveNumber,&data[pos],1);
	pos+=1;
// 37|65	TUint8 iReserved
	Mem::Copy(&aBootSector.iReserved,&data[pos],1);
	pos+=1;
// 38|66	TUint8 iExtendedBootSignature
	Mem::Copy(&aBootSector.iExtendedBootSignature,&data[pos],1);
	pos+=1;
// 39|67	TUint32 iUniqueID
	Mem::Copy(&aBootSector.iUniqueID,&data[pos],4);
	pos+=4;
// 43|71	TUint8 iVolumeLabel[KVolumeLabelSize]
	Mem::Copy(&aBootSector.iVolumeLabel,&data[pos],KVolumeLabelSize);
	pos+=KVolumeLabelSize;
// 54|82	TUint8 iFileSysType[KFileSysTypeSize]
	Mem::Copy(&aBootSector.iFileSysType,&data[pos],KFileSysTypeSize);
// 62|90

	return(KErrNone);
	}

/**
Work out if we have a FAT12|16|32 volume.
Returns 12, 16 or 32 as appropriate.
Returns 0 if can't be calculated (invalid values)
*/
TInt CMassStorageMountCB::DetermineFatType(TFatBootSector& aBootSector)
	{
	TUint32 ressectors = aBootSector.ReservedSectors();

	if (aBootSector.SectorsPerCluster() < 1)
		return 0;

	if (aBootSector.RootDirEntries() != 0)
		{
		TUint32 rootdirbytes;
		rootdirbytes = aBootSector.RootDirEntries() * 32 + aBootSector.BytesPerSector() - 1;
		ressectors += rootdirbytes / aBootSector.BytesPerSector();
		}

	if (aBootSector.FatSectors() != 0)
		ressectors += aBootSector.NumberOfFats() * aBootSector.FatSectors();
	else
		ressectors += aBootSector.NumberOfFats() * aBootSector.FatSectors32();

	TUint32 totalsectors;
	if (aBootSector.TotalSectors() != 0)
		totalsectors = aBootSector.TotalSectors();
	else
		totalsectors = aBootSector.HugeSectors();

	if (ressectors < 1 || totalsectors < 1)
		return 0;

	TUint32 datasec;
	datasec = totalsectors - ressectors;

	TUint32 countofclusters;
	countofclusters = datasec / aBootSector.SectorsPerCluster();

	__PRINT1(_L("CFatMountCB: Count of clusters = %d\n"), countofclusters);

	if (countofclusters < 4085)
		{
		return 12;
		}
	else if (countofclusters < 65525)
		{
		return 16;
		}
	else
		{
		return 32;
		}
	}

TInt CMassStorageMountCB::ReMount()
	{
	return KErrNotReady;
	}

void CMassStorageMountCB::VolumeL(TVolumeInfo& /*aVolume*/) const
	{
	User::Leave(KErrNotReady);
	}

void CMassStorageMountCB::SetVolumeL(TDes& /*aName*/)
	{
	User::Leave(KErrNotReady);
	}

void CMassStorageMountCB::MkDirL(const TDesC& /*aName*/)
	{
	User::Leave(KErrNotReady);
	}

void CMassStorageMountCB::RmDirL(const TDesC& /*aName*/)
	{
	User::Leave(KErrNotReady);
	}

void CMassStorageMountCB::DeleteL(const TDesC& /*aName*/)
	{
	User::Leave(KErrNotReady);
	}

void CMassStorageMountCB::RenameL(const TDesC& /*anOldName*/,const TDesC& /*anNewName*/)
	{
	User::Leave(KErrNotReady);
	}

void CMassStorageMountCB::ReplaceL(const TDesC& /*anOldName*/,const TDesC& /*anNewName*/)
	{
	User::Leave(KErrNotReady);
	}

void CMassStorageMountCB::EntryL(const TDesC& /*aName*/,TEntry& /*anEntry*/) const
	{
	User::Leave(KErrNotReady);
	}

void CMassStorageMountCB::SetEntryL(const TDesC& /*aName*/,const TTime& /*aTime*/,TUint /*aSetAttMask*/,TUint /*aClearAttMask*/)
	{
	User::Leave(KErrNotReady);
	}

void CMassStorageMountCB::FileOpenL(const TDesC& /*aName*/,TUint /*aMode*/,TFileOpen /*anOpen*/,CFileCB* /*aFile*/)
	{
	User::Leave(KErrNotReady);
	}

void CMassStorageMountCB::DirOpenL(const TDesC& /*aName*/,CDirCB* /*aDir*/)
	{
	User::Leave(KErrNotReady);
	}


void CMassStorageMountCB::RawReadL(TInt64 /*aPos*/,TInt /*aLength*/,const TAny* /*aTrg*/,TInt /*anOffset*/,const RMessagePtr2& /*aMessage*/) const
	{
	User::Leave(KErrNotReady);
	}

void CMassStorageMountCB::RawWriteL(TInt64 /*aPos*/,TInt /*aLength*/,const TAny* /*aSrc*/,TInt /*anOffset*/,const RMessagePtr2& /*aMessage*/)
	{
	User::Leave(KErrNotReady);
	}


void CMassStorageMountCB::GetShortNameL(const TDesC& /*aLongName*/,TDes& /*aShortName*/)
	{
	User::Leave(KErrNotReady);
	}

void CMassStorageMountCB::GetLongNameL(const TDesC& /*aShorName*/,TDes& /*aLongName*/)
	{
	User::Leave(KErrNotReady);
	}

#if defined(_DEBUG)
TInt CMassStorageMountCB::ControlIO(const RMessagePtr2& aMessage,TInt aCommand,TAny* aParam1,TAny* aParam2)
//
// Debug function
//
	{
	if(aCommand>=(KMaxTInt/2))
		return LocalDrive()->ControlIO(aMessage,aCommand-(KMaxTInt/2),aParam1,aParam2);
	else
		return KErrNotSupported;
	}
#else
TInt CMassStorageMountCB::ControlIO(const RMessagePtr2& /*aMessage*/,TInt /*aCommand*/,TAny* /*aParam1*/,TAny* /*aParam2*/)
	{return(KErrNotSupported);}
#endif

void CMassStorageMountCB::ReadSectionL(const TDesC& /*aName*/,TInt /*aPos*/,TAny* /*aTrg*/,TInt /*aLength*/,const RMessagePtr2& /*aMessage*/)
	{
	User::Leave(KErrNotReady);
	}