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) 2001-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:
//
#include <e32std.h>
#include <e32std_private.h>
#include "sr_rofs.h"
#include <rofs.h>
CDirectoryCache::CDirectoryCache( CRofsMountCB& aMount, CProxyDrive& aLocalDrive, const TRofsHeader& aHeader )
: iMount( aMount ), iLocalDrive( aLocalDrive ),
iTreeMediaOffset( aHeader.iDirTreeOffset ),
iTreeSize( aHeader.iDirTreeSize ),
iFilesMediaOffset( aHeader.iDirFileEntriesOffset ),
iFilesSize( aHeader.iDirFileEntriesSize )
{
}
CDirectoryCache::~CDirectoryCache()
{
delete iTreeBuffer;
delete iFilesBuffer;
}
void CDirectoryCache::ConstructL()
{
iTreeBuffer = HBufC8::NewL( iTreeSize );
iFilesBuffer = HBufC8::NewL( iFilesSize );
TPtr8 ptr = iTreeBuffer->Des();
User::LeaveIfError( iLocalDrive.Read( iTreeMediaOffset, iTreeSize, ptr) );
TPtr8 ptr2 = iFilesBuffer->Des();
User::LeaveIfError( iLocalDrive.Read( iFilesMediaOffset, iFilesSize, ptr2) );
}
void CDirectoryCache::FindLeafDirL(const TDesC& aName, const TRofsDir*& aDir) const
//
// Navigate the path to find the leaf directory, starting at aDir.
//
{
TLex lex(aName);
TInt r;
FOREVER
{
lex.Inc(); // Skip the file separator
lex.Mark();
r=lex.Remainder().Locate(KPathDelimiter);
if ( KErrNotFound == r )
{
r=lex.Remainder().Length();
}
if ( 0 == r ) // End of the path
{
break;
}
lex.Inc(r); // Set the token length
const TRofsEntry* subDirEntry = NULL;
TInt r = DoBinaryFindSubDir(lex.MarkedToken(), KEntryAttDir|KEntryAttMatchExclusive, aDir, subDirEntry );
if( KErrNone != r )
{
User::Leave( KErrPathNotFound );
}
__ASSERT_DEBUG( 0 != (subDirEntry->iAtt & KEntryAttDir ), CRofs::Panic( CRofs::EPanicEntryNotDir ));
aDir = RofsDirFromSubDirEntry( subDirEntry );
}
}
TInt CDirectoryCache::DoBinaryFindSubDir(const TDesC& aName, TUint aAtt, const TRofsDir* aDir, const TRofsEntry*& aSubDirEntry ) const
//
// Scan the directory aDir looking for subdirectory aName using binary search.
// aName cannot contain wildcards and aSubDirEntry should always be NULL.
// If a matching entry is found writes pointer to the entry into aSubDirEntry
// and returns KErrNone.
//
{
if (aSubDirEntry != NULL)
{
return DoFindSubDir(aName, aAtt, aDir, aSubDirEntry);
}
TInt numDirs=GetDirCount(aDir);
TInt topIndex=numDirs-1;
TInt bottomIndex=0;
TBool bFound=EFalse;
TInt retVal=KErrNotFound;
if(topIndex>=0)
{
TUint16* offsets = (TUint16*) ((TUint8*) aDir + aDir->iStructSize);
offsets += 2; //to skip file and dir counts
while((!bFound) && (topIndex>=bottomIndex))
{
TInt32 middleIndex;
const TRofsEntry* pCurrentEntry=NULL;
middleIndex=(topIndex+bottomIndex)>>1;
//Offsets for directories are relative to the start of the
//directory block
TUint8* ptr = (TUint8*) aDir + (offsets[middleIndex] << 2);
pCurrentEntry = (TRofsEntry*) ptr;
TPtrC currName=TPtrC((const TText*)&pCurrentEntry->iName[0],pCurrentEntry->iNameLength);
TInt result=Compare(aName,currName);
if(result<0)
topIndex=middleIndex-1;
else if(result>0)
bottomIndex=middleIndex+1;
else
{
bFound=ETrue; // exit loop
if (iMount.MatchEntryAtt(pCurrentEntry->iAtt, aAtt))
{
aSubDirEntry=pCurrentEntry;
retVal=KErrNone;
}
}
}
}
return retVal;
}
TInt CDirectoryCache::DoFindSubDir(const TDesC& aName, TUint aAtt, const TRofsDir* aDir, const TRofsEntry*& aSubDirEntry ) const
//
// Scan the directory aDir looking for subdirectory aName. If aSubDirEntry is
// not NULL the search starts from the entry AFTER aSubDirEntry.
// If a matching entry is found writes pointer to the entry into aSubDirEntry
// and returns KErrNone.
//
{
const TRofsEntry* pEntry = aSubDirEntry; // which entry
const TRofsEntry* const pEnd = (TRofsEntry*)EndOfDirPlusOne( aDir );
if( !pEntry )
{
pEntry = FirstSubDirEntryFromDir( aDir );
}
else
{
// move to next entry
__ASSERT_DEBUG( pEntry >= FirstSubDirEntryFromDir( aDir ), CRofs::Panic( CRofs::EPanicEntryBeforeDirectory ));
__ASSERT_DEBUG( pEntry < pEnd, CRofs::Panic( CRofs::EPanicEntryAfterDirectory ));
pEntry = NextEntry( pEntry );
}
while ( pEntry < pEnd )
{
TPtrC name( NameAddress( pEntry ), pEntry->iNameLength);
if ( KErrNotFound != name.MatchF(aName) && iMount.MatchEntryAtt(pEntry->iAtt, aAtt) )
{
aSubDirEntry = pEntry;
return KErrNone;
}
pEntry = NextEntry( pEntry );
}
return KErrNotFound;
}
TInt CDirectoryCache::GetDirCount(const TRofsDir* aDir) const
//
//Return the number of directory entries contained in aDir
//
{
TUint16* dirCount = (TUint16*) ((TUint8*) aDir + aDir->iStructSize);
return *dirCount;
}
TInt CDirectoryCache::GetFileCount(const TRofsDir* aDir) const
//
//Return the number of file entries contained in aDir
//
{
TUint16* fileCount = (TUint16*) ((TUint8*) aDir + aDir->iStructSize);
fileCount++; //jump over the dir count
return *fileCount;
}
TInt CDirectoryCache::Compare(const TDesC& aLeft, const TDesC& aRight) const
//
//Compares two filenames. Folds ASCII characters to uppercase
//
{
TInt len=Min(aLeft.Length(),aRight.Length());
const TText* leftString = aLeft.Ptr();
const TText* rightString = aRight.Ptr();
while (len--)
{
TText leftChar=*leftString++;
TText rightChar=*rightString++;
if (leftChar<='Z' && leftChar>='A')
leftChar +='a'-'A'; // covert to UPPERCASE
if (rightChar<='Z' && rightChar>='A')
rightChar +='a'-'A'; // covert to UPPERCASE
TInt result=leftChar-rightChar;
if (result != 0)
return result;
}
// match up to end of shorter string, now compare lengths
return aLeft.Length()-aRight.Length();
}
TInt CDirectoryCache::ExtractMangleInfo(const TDesC& searchName, TUint8 &MountId, TUint8 &ReservedId) const
{
#define HexToInt(x) ( x.IsDigit()? (TUint8)(x-(TUint)'0') : 0x0a+(TUint8)((x>='A' && x<='Z')? x-(TUint)'A':x-(TUint)'a') )
const TInt KOpenBraceRevPos = 7;
const TInt KHyphenRevPos = 4;
const TInt KCloseBraceRevPos = 1;
TInt openBraceRevPos = searchName.LocateReverse('[');
TInt closeBraceRevPos = searchName.LocateReverse(']');
TInt hyphenRevPos = searchName.LocateReverse('-');
TInt searchNameLen = searchName.Length();
if(openBraceRevPos==KErrNotFound || closeBraceRevPos==KErrNotFound || hyphenRevPos==KErrNotFound)
return KErrNotFound;
openBraceRevPos = searchNameLen - openBraceRevPos;
closeBraceRevPos = searchNameLen - closeBraceRevPos;
hyphenRevPos = searchNameLen - hyphenRevPos;
if(openBraceRevPos!=KOpenBraceRevPos || hyphenRevPos!=KHyphenRevPos || closeBraceRevPos!=KCloseBraceRevPos)
return KErrNotFound;
const TText* nameString = searchName.Ptr();
TInt MountIdPos = searchNameLen - KOpenBraceRevPos + 1;
TInt ReservedIdPos = searchNameLen - KHyphenRevPos + 1;
TChar MountIdHNibble = *(nameString+MountIdPos);
TChar MountIdLNibble = *(nameString+MountIdPos+1);
TChar ReservedIdHNibble = *(nameString+ReservedIdPos);
TChar ReservedIdLNibble = *(nameString+ReservedIdPos+1);
if(MountIdHNibble.IsHexDigit() && MountIdLNibble.IsHexDigit() &&
ReservedIdHNibble.IsHexDigit() && ReservedIdLNibble.IsHexDigit())
{
MountId = (TUint8)((HexToInt(MountIdHNibble) << 4) | HexToInt(MountIdLNibble));
ReservedId = (TUint8)((HexToInt(ReservedIdHNibble) << 4) | HexToInt(ReservedIdLNibble));
return KErrNone;
}
return KErrNotFound;
}
TInt CDirectoryCache::DoBinaryFindFile(const TDesC& aName, TUint aAtt, const TRofsDir* aDir, const TRofsEntry*& aEntry ) const
//
// Scan from aDir looking for file aName using binary search.
// aName cannot contain wildcards and aEntry should always be NULL.
// If found return the result in aEntry.
//
{
if (aEntry != NULL)
{
return DoFindFile(aName, aAtt, aDir, aEntry);
}
TInt numFiles=GetFileCount(aDir);
TInt topIndex=numFiles-1;
TInt bottomIndex=0;
TInt result;
TBool doNameMangle = ETrue;
TBuf<KMaxFileName> searchName;
TBool bFound=EFalse;
TInt retVal=KErrNotFound;
searchName.Copy((const TText*)aName.Ptr(), aName.Length());
if(topIndex>=0)
{
TUint16* offsets = (TUint16*) ((TUint8*) aDir + aDir->iStructSize);
offsets += 2; //to skip file and dir counts
offsets += GetDirCount(aDir); //skip directory offsets
while((!bFound) && (topIndex>=bottomIndex))
{
TInt32 middleIndex;
const TRofsEntry* pCurrentEntry=NULL;
TBuf<KMaxFileName> currName;
middleIndex=(topIndex+bottomIndex)>>1;
//Offsets for files are relative to the start of the
//file block
TInt bufferOffset = (offsets[middleIndex]<<2) - iFilesMediaOffset + 4;
bufferOffset += aDir->iFileBlockAddress;
TUint8* ptr = (TUint8*) &iFilesBuffer[0];
pCurrentEntry=(TRofsEntry*) &ptr[bufferOffset];
currName.Copy(((const TText*)&pCurrentEntry->iName[0]), pCurrentEntry->iNameLength);
if(doNameMangle && ((~pCurrentEntry->iAttExtra & (KEntryAttUnique >> 23)) != 0))
currName.AppendFormat(_L("[%02x-00]"),iMount.iMountId);
result=Compare(searchName,currName);
if(result<0)
topIndex=middleIndex-1;
else if(result>0)
bottomIndex=middleIndex+1;
else
{
bFound=ETrue; // exit loop
if (iMount.MatchEntryAtt(pCurrentEntry->iAtt, aAtt))
{
aEntry=pCurrentEntry;
retVal = (pCurrentEntry->iFileAddress == KFileHidden) ? KErrHidden : KErrNone;
}
/* If we have found a file and we are in second pass of binary search without nameMangle
check whether it is unique file */
if(!doNameMangle)
{
/* If it is not a unique file then the file does not exist */
if((~pCurrentEntry->iAttExtra & (KEntryAttUnique >> 23)) == 0)
{
retVal = KErrNotFound;
aEntry = NULL;
}
}
}
/* If we are going to return and we are searching for the unique file,there is a possiblity
that the binary search would have missed it (since the file entries were sorted without
namemangle).*/
if((!bFound) && (topIndex<bottomIndex) && doNameMangle)
{
TUint8 MountId;
TUint8 ReservedId;
if(ExtractMangleInfo(searchName,MountId,ReservedId) != KErrNone)
break;
if(MountId != iMount.iMountId || ReservedId != 0)
break;
/* If the aNameLength is equal to the mangle name length, we cant proceed our search
with null strings */
if((TUint)(aName.Length()) == KRofsMangleNameLength)
break;
searchName.Copy((const TText*)aName.Ptr(), aName.Length()-KRofsMangleNameLength);
/* The next level of search is sufficient enough to start on the top portion of the list.
Thus resetting the bottomIndex to 0 is sufficient */
bottomIndex=0;
doNameMangle = EFalse;
}
}
}
return retVal;
}
TInt CDirectoryCache::DoFindFile(const TDesC& aName, TUint aAtt, const TRofsDir* aDir, const TRofsEntry*& aEntry ) const
//
// Scan from aDir looking for file aName.
// The search starts at the entry after aEntry, unless aEntry is NULL, in which
// case the srach starts from the beginning of the file block.
// If found return the result in aEntry.
//
{
__ASSERT_DEBUG( aDir != NULL, CRofs::Panic( CRofs::EPanicNullSubDir ));
if( aDir->iFileBlockAddress )
{
const TRofsEntry* pEntry;
if( !aEntry )
{
pEntry = FirstFileEntryFromDir( aDir );
}
else
{
pEntry = NextEntry( aEntry );
}
const TAny* const pEnd = EndOfFileBlockPlusOne( aDir );
while ( pEntry < pEnd )
{
TBuf<KMaxFileName> fileName;
fileName.Copy(NameAddress( pEntry ), pEntry->iNameLength);
if((~pEntry->iAttExtra & (KEntryAttUnique >> 23)) != 0)
fileName.AppendFormat(_L("[%02x-00]"),iMount.iMountId);
if ( KErrNotFound != fileName.MatchF(aName) && iMount.MatchEntryAtt(pEntry->iAtt, aAtt) )
{
aEntry = pEntry;
return(( pEntry->iFileAddress == KFileHidden ) ? KErrHidden : KErrNone);
}
pEntry = NextEntry( pEntry );
}
}
return KErrNotFound;
}
void CDirectoryCache::FindFileEntryL(const TDesC& aName, const TRofsEntry*& aEntry) const
//
// Locate an entry from its full path name.
//
{
TInt namePos=aName.LocateReverse(KPathDelimiter)+1; // There is always a path delimiter
const TRofsDir* dir = RootDirectory();
FindLeafDirL(aName.Left(namePos), dir);
aEntry=0;
TInt r = DoBinaryFindFile(aName.Mid(namePos), KEntryAttDir|KEntryAttMatchExclude, dir, aEntry);
if (r!=KErrNone)
User::Leave(r);
}
void CDirectoryCache::FindDirectoryEntryL(const TDesC& aName, const TRofsDir*& aDir) const
//
// Locate an entry from its full path name.
//
{
aDir = RootDirectory();
FindLeafDirL(aName,aDir);
}
void CDirectoryCache::GetNextMatchingL(const TDesC& aName, TUint aAtt, const TRofsDir*& aDir, const TRofsEntry*& aEntry, TInt aError, TBool bUseBinarySearch) const
//
// Retrieves the next directory or file entry from aDir that matches the pattern in aName
// (which should be the entry name only, not the full path)
// The search starts at the entry after aEntry
//
{
__ASSERT_DEBUG( aName.LocateReverse(KPathDelimiter) == KErrNotFound, CRofs::Panic( CRofs::EPanicBadMatchName ));
TInt r = KErrGeneral;
const TRofsEntry* entry = aEntry;
TBool searchFiles = EFalse;
if( entry && (entry < FirstSubDirEntryFromDir(aDir) || entry >= EndOfDirPlusOne(aDir)) )
{
searchFiles = ETrue;
}
else
{
// searching the directory list
if (!bUseBinarySearch)
{
r = DoFindSubDir( aName, aAtt, aDir, entry );
}
else
{
r = DoBinaryFindSubDir(aName, aAtt, aDir, entry);
}
if( KErrNotFound == r )
{
// start looking through the file list
entry = NULL; // start at beginning of list
searchFiles = ETrue;
}
}
if( searchFiles )
{
if (!bUseBinarySearch)
{
r = DoFindFile( aName, aAtt, aDir, entry );
}
else
{
r = DoBinaryFindFile(aName, aAtt, aDir, entry);
}
}
/*
if( aEntry >= FirstFileEntryFromDir( aDir )
&& aDir->iFileBlockAddress )
{
// we are searching the file list
r = DoFindFile( aName, aAtt, aDir, aEntry );
}
else
{
// searching the directory list
r = DoFindSubDir( aName, aAtt, aDir, aEntry );
if( KErrNotFound == r )
{
// start looking through the file list
TRofsEntry* entry = NULL; // start at beginning of list
r = DoFindFile( aName, aAtt, aDir, entry );
if( KErrNone == r )
{
aEntry = entry;
}
}
}
*/
if( r == KErrNone || r == KErrHidden)
{
// Move onto the next entry (this is valid even for hidden entries so
// that we can move onto the next entry, which may not be hidden)
aEntry = entry;
if(r == KErrNone)
{
return;
}
}
User::Leave(r == KErrHidden ? r : aError);
}
void CDirectoryCache::FindGeneralEntryL(const TDesC& aName, TUint aAtt, const TRofsDir*& aDir, const TRofsEntry*& aEntry ) const
{
TInt namePos=aName.LocateReverse(KPathDelimiter)+1; // There is always a path delimiter
aDir = RootDirectory();
FindLeafDirL(aName.Left(namePos), aDir);
GetNextMatchingL( aName.Mid(namePos), aAtt, aDir, aEntry, KErrNotFound, ETrue );
}
TUint8 CDirectoryCache::GetMountId( void )
{
return (TUint8)(iMount.iMountId);
};