userlibandfileserver/fileserver/srom/sr_rom.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
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) 1995-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:
// f32\srom\sr_rom.cpp
// 
//

#include "sr_std.h"

#if defined(_UNICODE)
#define __SIZE(len) ((len)<<1)
#else
#define __SIZE(len) (len)
#endif

const TRomHeader* CRom::iRomHeaderAddress=(TRomHeader*)UserSvr::RomHeaderAddress();

TInt TRomDir::BinarySearch(const TDesC& aName, TInt aLengthLimit, TInt aMode, TBool aDir) const
	{
//	RDebug::Print(_L("BinarySearch %S ll=%d m=%d dir=%d"), &aName, aLengthLimit, aMode, aDir);
	const TRomDirSortInfo* s = SortInfo();
	TInt l = aDir ? 0 : s->iSubDirCount;
	TInt r = aDir ? s->iSubDirCount : s->iSubDirCount + s->iFileCount;
	TBool found = EFalse;
	while (r>l)
		{
		TInt m=(l+r)>>1;
		const TRomEntry* e = SortedEntry(m);
		TInt nl = Min(e->iNameLength, aLengthLimit);
		TPtrC en((const TText*)&e->iName[0], nl);
		TInt k = CRomMountCB::Compare(aName, en);
		if (k==0)
			{
			if (aMode == EArrayFindMode_Any)
				{
//				RDebug::Printf("Found %d", m);
				return m;
				}
			found = ETrue;
			if (aMode == EArrayFindMode_First)
				r=m;
			else
				l=m+1;
			}
		else if (k>0)
			l=m+1;
		else
			r=m;
		}
//	RDebug::Printf("Found=%d r=%d", found, r);
	return found ? r : KErrNotFound;
	}

// Navigate the path to find the leaf directory, starting at this.
const TRomDir* TRomDir::FindLeafDir(const TDesC& aPath) const
	{
	TLex lex(aPath);
	TInt r;
	const TRomDir* d = this;
	FOREVER
		{
		lex.Inc(); // Skip the file separator
		lex.Mark();
		r=lex.Remainder().Locate(KPathDelimiter);
		if (r==KErrNotFound)
			r=lex.Remainder().Length();
		if (r==0) // End of the path
			break;
		lex.Inc(r); // Set the token length
		TInt ix = d->BinarySearch(lex.MarkedToken(), KMaxTInt, EArrayFindMode_Any, ETrue);
		if (ix<0)
			return NULL;
		const TRomEntry* e = d->SortedEntry(ix);
//		if (!(e->iAtt & KEntryAttDir))
//			return NULL;
		d = (const TRomDir*)e->iAddressLin;
		}
	return d;
	}

LOCAL_C void Fault(TFault aFault)
//
// Report a fault in the rom file system.
//
	{

	User::Panic(_L("ROMFILESYS"),aFault);
	}

CRomMountCB::CRomMountCB(const CRom* aRom)
//
// Constructor
//
	: iRom(aRom)
	{
	}

void CRomMountCB::Dismounted()
//
// Dummy implementation of pure virtual function
//
	{}

void CRomMountCB::IsFileInRom(const TDesC& aName,TUint8*& aFileStart)
//
// Return the address of the file if it is in rom
//
	{
	
	TLinAddr dir;
	TLinAddr entry=0;
	aFileStart=NULL;
	TRAPD(r,FindEntryL(aName,KEntryAttNormal,ETrue,dir,entry));
	if (r!=KErrNone)
		return;
	aFileStart=(TUint8*)((const TRomEntry*)entry)->iAddressLin;
	}

TInt CRomMountCB::Compare(const TDesC& aLeft, const TDesC& aRight)
//
//Compares two filenames.  Folds ASCII characters to uppercase
//
	{

	TInt ll = aLeft.Length();
	TInt rl = aRight.Length();
	TInt len = Min(ll, rl);
	const TText* l = aLeft.Ptr();
	const TText* r = aRight.Ptr();
	while (len--)
		{
		TText lc = *l++;
		TText rc = *r++;
		if (lc >= 'A' && lc <= 'Z')
			lc += ('a' - 'A');
		if (rc >= 'A' && rc <= 'Z')
			rc += ('a' - 'A');
		TInt x = lc - rc;
		if (x)
			return x;
		}
	// match up to end of shorter string, now compare lengths
	return ll - rl;
	}

void CRomMountCB::FindBinaryL(const TDesC& aName, TUint aAtt, TBool aAttKnown, TLinAddr aDir, TLinAddr& aEntry, TInt aError) const
//
//Identical to FindL, but uses binary search for faster performance.
//However, can't deal with wildcards, whereas FindL can.
//
	{

	//Although the value of aEntry is not used, we expect it to be zero,
	__ASSERT_DEBUG(aEntry==0,Fault(ERomInvalidArgument));
	const TRomDir* d = (const TRomDir*)aDir;
	TBool ix;
	if (aAttKnown)
		ix = d->BinarySearch(aName, KMaxTInt, EArrayFindMode_Any, aAtt & KEntryAttDir);
	else
		{
		//We don't know whether we're looking for a file or a directory, so
		//look through both
		ix = d->BinarySearch(aName, KMaxTInt, EArrayFindMode_Any, EFalse);
		if (ix<0 || !MatchEntryAtt(d->SortedEntry(ix)->iAtt, aAtt) )
			ix = d->BinarySearch(aName, KMaxTInt, EArrayFindMode_Any, ETrue);
		}
	if (ix>=0)
		{
		const TRomEntry* e = d->SortedEntry(ix);
		if (MatchEntryAtt(e->iAtt, aAtt))
			{
			aEntry = (TLinAddr)e;
			return;
			}
		}
	User::Leave(aError);
	}

void CRomMountCB::FindL(const TDesC& aName, TUint anAtt, TLinAddr aDir, TLinAddr& anEntry, TInt anError) const
//
// Scan from aDir looking for aName.
// If found return the result in anEntry.
//
	{
	const TRomDir* pD = (const TRomDir*)aDir;
	const TRomEntry* pE;
	if (anEntry==0)
		pE = &pD->iEntry;
	else
		{
		pE = (const TRomEntry*)anEntry;
		pE = PtrAdd(pE, Align4(__SIZE(pE->iNameLength) + KRomEntrySize));
		}
	const TRomEntry* pEnd = PtrAdd(&pD->iEntry, pD->iSize);
	while (pE<pEnd)
		{
		TPtrC name = TPtrC((const TText*)&pE->iName[0], pE->iNameLength);
		if (name.MatchF(aName)!=KErrNotFound && MatchEntryAtt(pE->iAtt, anAtt))
			{
			anEntry = (TLinAddr)pE;
			return;
			}
		pE = PtrAdd(pE, Align4(__SIZE(pE->iNameLength) + KRomEntrySize));
		}
	User::Leave(anError);
	}

void CRomMountCB::FindEntryL(const TDesC& aName, TUint anAtt, TBool aAttKnown, TLinAddr& aDir, TLinAddr& anEntry) const
//
// Locate an entry from its full path name.
//
	{

	TInt namePos=aName.LocateReverse(KPathDelimiter)+1; // There is always a path delimiter
	const TRomDir* d = ((const TRomDir*)RomRootDirectory())->FindLeafDir(aName.Left(namePos));
	if (!d)
		User::Leave(KErrPathNotFound);
	anEntry=0;
	aDir = (TLinAddr)d;
	FindBinaryL(aName.Mid(namePos),anAtt,aAttKnown,aDir,anEntry,KErrNotFound);
	}

void CRomMountCB::MountL(TBool /*aForceMount*/)
//
// Mount a media. Only allowed to leave with KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
//
	{

	iUniqueID=0;
	iSize=(TUint)RomHeader().iUncompressedSize;
	SetVolumeName(_L("RomDrive").AllocL());
	}

TInt CRomMountCB::ReMount()
//
// Try and remount this media.
//
	{

	Fault(ERomReMountNotSupported);
	return(0);
	}

void CRomMountCB::VolumeL(TVolumeInfo& aVolume) const
//
// Return the volume info.
//
	{

	aVolume.iFree=0;
	}

void CRomMountCB::SetVolumeL(TDes& /*aName*/)
//
// Set the volume label.
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomMountCB::MkDirL(const TDesC& /*aName*/)
//
// Make a directory.
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomMountCB::RmDirL(const TDesC& /*aName*/)
//
// Remove a directory.
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomMountCB::DeleteL(const TDesC& /*aName*/)
//
// Delete a file.
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomMountCB::RenameL(const TDesC& /*anOldName*/,const TDesC& /*aNewName*/)
//
// Rename a file or directory.
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomMountCB::ReplaceL(const TDesC& /*anOldName*/,const TDesC& /*aNewName*/)
//
// Atomic replace.
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomMountCB::EntryL(const TDesC& aName,TEntry& anEntry) const
//
// Get entry details.
//
	{

	TLinAddr dir;
	TLinAddr entry;
	FindEntryL(aName,KEntryAttMaskSupported,EFalse,dir,entry);
	const TRomEntry* pE = (const TRomEntry*)entry;
	anEntry.iAtt=pE->iAtt;
	anEntry.iSize=pE->iSize;
	anEntry.iModified=RomHeader().iTime;
	anEntry.iName.Des().Copy((TText*)&pE->iName[0],pE->iNameLength);
	ReadUidL(pE->iAddressLin,anEntry);
	}

void CRomMountCB::SetEntryL(const TDesC& /*aName*/,const TTime& /*aTime*/,TUint /*aMask*/,TUint /*aVal*/)
//
// Set entry details.
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomMountCB::FileOpenL(const TDesC& aName,TUint aMode,TFileOpen anOpen,CFileCB* aFile)
//
// Open a file on the current mount.
//
	{

	if (aMode&EFileWrite)
		User::Leave(KErrAccessDenied);
	switch (anOpen)
		{
	case EFileCreate:
	case EFileReplace:
		User::Leave(KErrAccessDenied);
	case EFileOpen:
		break;
	default:
		User::Leave(KErrAccessDenied);
		}
	TLinAddr dir;
	TLinAddr entry;
	FindEntryL(aName,KEntryAttMustBeFile,ETrue,dir,entry);
	const TRomEntry* pE = (const TRomEntry*)entry;
	CRomFileCB& file=(*((CRomFileCB*)aFile));
	file.SetSize(pE->iSize);
	file.SetAtt(pE->iAtt);
	file.SetModified(RomHeader().iTime);
	file.SetBase((const TUint8*)pE->iAddressLin);
	}

void CRomMountCB::DirOpenL(const TDesC& aName, CDirCB* aDir)
//
// Open a file on the current mount.
//
	{

    TFileName fileName=aName;
    TInt namePos=aName.LocateReverse(KPathDelimiter)+1; // Exclude path delimiter
    if (namePos==aName.Length())
        fileName+=_L("*");
	const TRomDir* d = ((const TRomDir*)RomRootDirectory())->FindLeafDir(aName.Left(namePos));
	if (!d)
		User::Leave(KErrPathNotFound);
	CRomDirCB& dirCB = *(CRomDirCB*)aDir;
	dirCB.SetDir((TLinAddr)d, NULL, fileName.Mid(namePos));
	}

void CRomMountCB::RawReadL(TInt64 aPos,TInt aLength,const TAny* aDes,TInt anOffset,const RMessagePtr2& aMessage) const
//
// Read up to aLength data directly from the ROM
//
	{

	TUint romSize=RomHeader().iUncompressedSize;
	if (I64LOW(aPos)>=romSize)
		aMessage.WriteL(2,TPtrC8(NULL,0),anOffset);
	else
		{
		TInt len=Min((TInt)(romSize-I64LOW(aPos)),aLength);
		aMessage.WriteL(2,TPtrC8((TUint8*)RomHeader().iRomBase,len),anOffset);
		}
	}

void CRomMountCB::RawWriteL(TInt64 /*aPos*/,TInt /*aLength*/,const TAny* /*aDes*/,TInt /*anOffset*/,const RMessagePtr2& /*aMessage*/)
//
// Write aLength data to ROM (?)
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomMountCB::ReadUidL(TLinAddr anAddr,TEntry& anEntry) const
//
// Read a uid if present.
//
	{
	// Need to consider zero-length files (for which anAddr is 0)
	// and files too small to have a UID
	if (anEntry.iSize >= (TInt) sizeof(TCheckedUid))
		{
		TCheckedUid entryUid(TPtrC8((TUint8*)anAddr, sizeof(TCheckedUid)));
		anEntry.iType=entryUid.UidType();
		}
	else
		{
		anEntry.iType=KNullUid;
		}
	}



void CRomMountCB::ReadSectionL(const TDesC& aName,TInt aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage)
	{

	__PRINT(Print(_L("CRomMountCB::ReadSectionL")));
			
	TLinAddr dir;
	TLinAddr entry;
	FindEntryL(aName,KEntryAttMustBeFile,ETrue,dir,entry);
	const TRomEntry* pE = (TRomEntry*)entry;
	TInt size=pE->iSize;

	const TText8* baseAddress = (const TText8*)pE->iAddressLin;
	
	if (size>=(aPos+aLength)) //|| (size>aPos)
		{
		TPtrC8 section((baseAddress+aPos),aLength);
		aMessage.WriteL(0,section,0);
		}
	else if (size>aPos)
		{
		aLength=(size-aPos);
		TPtrC8 section((baseAddress+aPos),aLength);
		aMessage.WriteL(0,section,0);
		}	
	else
		User::Leave(KErrEof);
	
	}



void CRomMountCB::GetShortNameL(const TDesC& /*aLongName*/,TDes& /*aShortName*/)
//
// Return the short name associated with aLongName
// Assumes all rom names are 8.3
//
	{

	User::Leave(KErrNotSupported);
	}

void CRomMountCB::GetLongNameL(const TDesC& /*aShortName*/,TDes& /*aLongName*/)
//
// Return the short name associated with aLongName
// Assumes all rom names are 8.3
//
	{

	User::Leave(KErrNotSupported);
	}	

TInt CRomMountCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput) 
//
// Access the specified interface; behaviour is interface-specific
//
	{
	switch(aInterfaceId)
		{
		case (CMountCB::EFileAccessor):
			{
			((CMountCB::MFileAccessor*&) aInterface) = this;
			return KErrNone;
			}
		default:
			return (CMountCB::GetInterface(aInterfaceId,aInterface,aInput));
		}
	}

TInt CRomMountCB::GetFileUniqueId(const TDesC& /* aName */, TInt64& aUniqueId)
	{
	// Get unique identifier for the file - for ROM File System will just return zero
	aUniqueId = MAKE_TINT64(0,0);
	return KErrNone;
	}

TInt CRomMountCB::Spare3(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
	{
	return KErrNotSupported;
	}

TInt CRomMountCB::Spare2(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
	{
	return KErrNotSupported;
	}

TInt CRomMountCB::Spare1(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
	{
	return KErrNotSupported;
	}


CRomFileCB::CRomFileCB(const CRom* aRom)
//
// Constructor
//
	: iRom(aRom)
	{
	}

void CRomFileCB::ReadL(TInt aPos,TInt& aLength,const TAny* aTrg,const RMessagePtr2& aMessage)
//
// Read from the file.
//
	{

	__PRINT(Print(_L("CRomFileCB::ReadL")));

	if (aPos>=iSize)
		{
        TPtrC8 nullBuf(NULL,0);
		aMessage.WriteL(0,nullBuf,0);
		aLength=0;
		}
	else
		{
		TInt len=Min((iSize-aPos),aLength);
        TPtrC8 romBuf(iBase+aPos,len);
//		thread->WriteL(aTrg,romBuf,0);
		aMessage.WriteL(0,romBuf,0);
		aLength=len;
		}
	}

void CRomFileCB::WriteL(TInt /*aPos*/,TInt& /*aLength*/,const TAny* /*aDes*/,const RMessagePtr2& /*aMessage*/)
//
// Write to the file.
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomFileCB::RenameL(const TDesC& /*aDes*/)
//
// Rename the file.
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomFileCB::SetSizeL(TInt /*aSize*/)
//
// Set the file size.
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomFileCB::SetEntryL(const TTime& /*aTime*/,TUint /*aMask*/,TUint /*aVal*/)
//
// Set the entry's attributes and modified time.
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomFileCB::FlushAllL()
//
// Commit any buffered date to the media.
//
	{

	User::Leave(KErrAccessDenied);
	}

void CRomFileCB::FlushDataL()
//
// Commit any buffered date to the media.
//
	{

	User::Leave(KErrAccessDenied);
	}

TInt CRomFileCB::Address(TInt& aPos) const
//
// Return address of the file at aPos. Default implementation.
//
	{

	if (aPos>=iSize)
		return(KErrEof);
	aPos=(TInt)(iBase+aPos);
	return(KErrNone);
	}

CRomDirCB::CRomDirCB(const CRom* aRom)
//
// Constructor
//
	: iRom(aRom)
	{
	}

CRomDirCB::~CRomDirCB()
//
// Destruct
//
	{

	delete iMatch;
	}

TBool CRomDirCB::MatchUid()
//
// Match the uid ?
//
	{

	if (iUidType[0]!=TUid::Null() || iUidType[1]!=TUid::Null() || iUidType[2]!=TUid::Null())
		return(ETrue);
	return(EFalse);
	}

LOCAL_C TBool CompareUid(const TUidType& aUidTrg, const TUidType& aUidSuitor)
//
// Compare the suitor to the target pattern
//
	{
	
	if (aUidTrg[0]!=TUid::Null() && aUidTrg[0]!=aUidSuitor[0])
		return(EFalse);
	if (aUidTrg[1]!=TUid::Null() && aUidTrg[1]!=aUidSuitor[1])
		return(EFalse);
	if (aUidTrg[2]!=TUid::Null() && aUidTrg[2]!=aUidSuitor[2])
		return(EFalse);
	return(ETrue);
	}

void CRomDirCB::ReadL(TEntry& anEntry)
//
// Read the next entry from the directory.
//
	{

	CRomMountCB& mount=(CRomMountCB&)Mount();
	const TRomEntry* pE;
	FOREVER
		{
		//
		//May be called with wildcards in the path, so we need
		//to call the slow, sequential FindL
		//
		if (!iPending)
			mount.FindL(*iMatch,iAtt,iDir,iNext,KErrEof);
		iPending=EFalse;
		pE = (const TRomEntry*)iNext;
		iEntry.iName.Des().Copy((TText*)&pE->iName[0],pE->iNameLength);
		iEntry.iAtt=pE->iAtt;
		iEntry.iSize=pE->iSize;
		iEntry.iModified=RomHeader().iTime;
		anEntry=iEntry;
		if (MatchUid())
			{
			mount.ReadUidL(pE->iAddressLin,anEntry);
			if (CompareUid(iUidType,anEntry.iType))
				break;
			}
		else
			break;
		}
	if (iAtt&KEntryAttAllowUid && (anEntry.iAtt&KEntryAttDir)==0 && MatchUid()==EFalse)
		mount.ReadUidL(pE->iAddressLin,anEntry);
	}

void CRomDirCB::SetDir(TLinAddr aDir,TLinAddr anEntry,const TDesC& aName)
//
// Set the directory and entry that we are on after open.
//
	{

    iDir=aDir;
	iNext=anEntry;
	iMatch=aName.AllocL();
	iPending=(anEntry!=NULL);
	}

CRom::CRom()
//
// Constructor
//
	{
	}

CRom::~CRom()
//
// Destruct
//
	{
	}

TInt CRom::Install()
//
// Install the file system.
//
	{

	iVersion=TVersion(KF32MajorVersionNumber,KF32MinorVersionNumber,KF32BuildVersionNumber);
    TPtrC name=_L("Rom");
	return(SetName(&name));
	}

CMountCB* CRom::NewMountL() const
//
// Create a new mount control block.
//
	{

	return(new(ELeave) CRomMountCB(this));
	}

CFileCB* CRom::NewFileL() const
//
// Create a new file.
//
	{

	return(new(ELeave) CRomFileCB(this));
	}

CDirCB* CRom::NewDirL() const
//
// Create a new directory lister.
//
	{

	return(new(ELeave) CRomDirCB(this));
	}

CFormatCB* CRom::NewFormatL() const
//
// Create a new media formatter.
//
	{

	User::Leave(KErrAccessDenied);
	return(NULL);
	}

void CRom::DriveInfo(TDriveInfo& anInfo,TInt /*aDriveNumber*/) const
//
// Return the drive info.
//
	{
	anInfo.iDriveAtt=KDriveAttRom|KDriveAttInternal;
	anInfo.iMediaAtt=KMediaAttWriteProtected;
	anInfo.iType=EMediaRom;
	}

GLDEF_C void InstallRomFileSystemL()
//
// Create the ROM file system.
//
	{

	CFileSystem* pS=new(ELeave) CRom;
	CleanupStack::PushL(pS);
	User::LeaveIfError(InstallFileSystem(pS,RLibrary()));
	CleanupStack::Pop(1, pS);
	}

GLDEF_C const TRomHeader *RomHeader(CFileSystem *aFsys)
//
// Return the ROM header
//
	{

	return &((CRom *)aFsys)->RomHeader();
	}