os/kernelhwsrv/userlibandfileserver/fileserver/srofs/sr_rofs.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2001-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 //
    15 
    16 #include <e32std.h>
    17 #include <e32std_private.h>
    18 #include "sr_rofs.h"
    19 #include <rofs.h>
    20 #include <e32hal.h>
    21 
    22 void CRofs::Panic( TPanic aPanic )
    23 	{
    24 	_LIT( KCategory, "ROFSFSY" );
    25 	User::Panic( KCategory, aPanic );
    26 	}
    27 
    28 #ifdef _USE_TRUE_LRU_CACHE
    29 
    30 
    31 //***********************************************************
    32 //* Data Read Cache for Rofs
    33 //***********************************************************
    34 
    35 TCacheSegment::TCacheSegment()
    36 //
    37 // Constructor
    38 //
    39 	: iPos(-1)
    40 	{}
    41 
    42 void TCacheSegment::Set(TInt aPos)
    43 //
    44 // Set the diskPos of the data cached
    45 //
    46 	{
    47 	iPos=aPos;
    48 	}
    49 
    50 //***********************************************************
    51 CRofsLruCache::CRofsLruCache(CRofsMountCB* aMount, TInt64 aMediaSize)
    52 //
    53 // Least recently used data cache
    54 //
    55 	: iQue(_FOFF(TCacheSegment,iLink)), iMediaSize(aMediaSize)
    56 	{
    57 	iMount=aMount;
    58 	__PRINT(_L("CLruCache::CLruCache()"));
    59 	}
    60 
    61 CRofsLruCache::~CRofsLruCache()
    62 //
    63 // Free all data segments
    64 //
    65 	{
    66 	__PRINT(_L("CLruCache::~CLruCache()"));
    67 
    68 	TDblQueIter<TCacheSegment> iter(iQue);
    69 	while((TCacheSegment*)iter)
    70 		{
    71 		User::Free(iter++);
    72 		}
    73 	}
    74 
    75 TUint8* CRofsLruCache::Find(TInt aPos, TInt aLength)
    76 //
    77 // Find aPos in the cache or return NULL
    78 //
    79 	{
    80 	__PRINT(_L("CLruCache::Find()"));
    81 
    82 	TDblQueIter<TCacheSegment> iter(iQue);
    83 	TCacheSegment* data;
    84 	while((data=iter++)!=NULL)		//need to do a range check here
    85 		{
    86 		if(data->iPos < 0)
    87 			continue;
    88 		const TInt KEndOfSegment= data->iPos+ KSizeOfSegment;
    89 		if(data->iPos <= aPos && (KEndOfSegment >=aPos))
    90 			{
    91 			if((aPos+aLength) > (KEndOfSegment))
    92 				{
    93 				data->iLink.Deque();
    94 				iQue.AddLast(*data);
    95 				return(NULL);
    96 				}
    97 			if(!iQue.IsFirst(data)) 
    98 				{
    99 				data->iLink.Deque(); 
   100 				iQue.AddFirst(*data); 
   101 				}
   102 			return(&data->Data()[aPos-data->iPos]);
   103 			}
   104 		}
   105 	// If we got here, it means that we don't have it in cache at all 
   106 	return(NULL);
   107 		
   108 	}
   109 
   110 
   111 TUint8* CRofsLruCache::ReadL(TInt aPos, TInt aLength)
   112 //
   113 // Find aPos in the cache or read the data
   114 //
   115 	{
   116 	// Remember for Big size Nand the size of page can increase to 2K. Need to add this feature?
   117 	__PRINT(_L("CLruCache::ReadL()"));
   118 	
   119 	
   120 	// Search the cache 
   121 	TUint8* res=Find(aPos, aLength);
   122 	if (res)
   123 		return(res); 
   124 	
   125 	// Didn't find in the cache, read data from media 	 
   126 	// Align to page boundaries
   127 	TInt pagePos = aPos & ~(KPageSize-1);
   128 	
   129 	// Read from media
   130 	// Buffer to accomodate two page of data. 
   131 	// We won't cache any read bigger than one page
   132 	// Check if we have any segment available
   133 	TCacheSegment* seg= iQue.Last();
   134 	seg->iLink.Deque();
   135 	seg->Set(pagePos);
   136 	iQue.AddFirst(*seg);
   137 
   138 	// ensure we don't read past end of media
   139 	TInt cacheLen = (TInt) Min(iMediaSize -  pagePos, KSizeOfSegment);
   140 	TPtr8 dataBuf((seg->Data()), cacheLen);
   141 	TInt ret = iMount->LocalDrive()->Read(pagePos,cacheLen,dataBuf);
   142 
   143 	if (ret!=KErrNone)
   144 		{
   145 		User::Leave(ret);
   146 		}
   147 
   148 	return(&dataBuf[aPos & (KPageSize-1)]);
   149 	}
   150 
   151 CRofsLruCache* CRofsLruCache::New(TInt aSegmentSize, CRofsMountCB* aMount, TInt64 aMediaSize)
   152 //
   153 // Create an LruList and one segment
   154 //
   155 	{
   156 	__PRINT(_L("CRofsLruCache::New()"));
   157 	CRofsLruCache* lru=new CRofsLruCache(aMount, aMediaSize);
   158 	if (lru==NULL)
   159 		return(NULL);
   160 	for(TInt i=0; i<KSizeOfCacheInPages;i++)
   161 		{
   162 		TCacheSegment* seg=(TCacheSegment*)User::Alloc(aSegmentSize+sizeof(TCacheSegment));
   163 		if (seg==NULL)
   164 			{
   165 			delete lru;
   166 			return(NULL);
   167 			}
   168 		Mem::FillZ(seg,aSegmentSize+sizeof(TCacheSegment));
   169 		*seg=TCacheSegment();
   170 		lru->iQue.AddFirst(*seg);
   171 		}
   172 	return(lru);
   173 	}
   174 
   175 //***********************************************************
   176 //* Mount object
   177 //***********************************************************
   178 
   179 
   180 void CRofsMountCB::CacheReadL(TInt aPos, TInt aLength,const TAny* aDes,TInt anOffset, const RMessagePtr2& aMessage) const
   181 //
   182 //	Do a cached read if possible else read from media and insert to cache
   183 //
   184 	{
   185 
   186 	__PRINT2(_L("CRofsMountCB::CacheReadL TAny* Pos 0x%x, Len %d"),aPos,aLength);
   187 	// Don't cache anything more than a page long or if readinf into a file server cache buffer!
   188 	if (((KSizeOfSegment/2) < aLength) || (aMessage.Handle() == KLocalMessageHandle))
   189 		{
   190 		TInt ret = LocalDrive()->Read(aPos,aLength,aDes, aMessage.Handle(), anOffset);
   191 		if (ret!=KErrNone)
   192 			{
   193 			User::Leave(ret);
   194 			}
   195 		}
   196 	else
   197 		{
   198 		TUint8* data =iDataCache->ReadL(aPos, aLength);	//added length to enable cache to fill in the blanks
   199 		TPtrC8 buf(data,aLength);			//return buffer
   200 		aMessage.WriteL(0,buf,anOffset);
   201 		}
   202 	}
   203 
   204 #endif
   205 
   206 CRofsMountCB::CRofsMountCB()
   207 //
   208 // Constructor
   209 //
   210 	{
   211 	}
   212 
   213 void CRofsMountCB::Dismounted()
   214 //
   215 // Dummy implementation of pure virtual function
   216 //
   217 	{}
   218 
   219 
   220 void CRofsMountCB::MountL(TBool /*aForceMount*/)
   221 //
   222 // Mount a media. 
   223 // Only allowed to leave with KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
   224 //
   225 	{
   226 
   227 	// create the local drive
   228 	TInt r=CreateLocalDrive(GetLocalDrive(Drive().DriveNumber()));
   229 	User::LeaveIfError(r);
   230 	
   231 	iUniqueID=0;
   232 	
   233 	TLocalDriveCapsV2Buf caps;
   234 	User::LeaveIfError(LocalDrive()->Caps(caps));
   235 	iMediaSize = caps().iSize;
   236 
   237 	// Read ROFS image header
   238 	r = LocalDrive()->Read( 0, sizeof(TRofsHeader), iHeader );
   239 	__PRINT1(_L("CRofsMountCB::MountL, Reading Header %d"), r);
   240 	if( KErrNone != r )
   241 		{
   242 		User::Leave( KErrNotReady );
   243 		}
   244 
   245 	r = CheckHeader();
   246 	__PRINT1(_L("CRofsMountCB::MountL, Check Header %d"), r);
   247 	User::LeaveIfError( r );
   248 	
   249 	r=CheckExtension();
   250 	__PRINT1(_L("CRofsMountCB::MountL, Check Extension %d"), r);
   251 	if(r!=KErrNone && r!=KErrNotFound)
   252 		User::Leave(r);
   253 
   254 	//
   255 	// Construct the directory cache
   256 	//
   257 	iDirectoryCache = new(ELeave) CDirectoryCache( *this, *LocalDrive(), iHeader() );
   258 	iDirectoryCache->ConstructL();
   259 
   260 #ifdef _USE_TRUE_LRU_CACHE
   261 	//
   262 	// Construct the data cache
   263 	//
   264 	iDataCache = CRofsLruCache::New(KSizeOfSegment,this, iMediaSize);
   265 	if(!iDataCache)
   266 		User::Leave(KErrNoMemory);
   267 #endif
   268 
   269 	_LIT( KVolumeName, "Rofs" );
   270 	SetVolumeName( TPtrC(KVolumeName).AllocL() );
   271 	__PRINT(_L("CRofsMountCB::MountL, End of Mount"));
   272 	}
   273 
   274 
   275 LOCAL_D TBool IsOverlapping( TUint aBase1, TUint aSize1, TUint aBase2, TUint aSize2 )
   276 //
   277 //	Check files and directories are not overlapping
   278 //
   279 	{
   280 	TUint end1 = aBase1 + aSize1 - 1;
   281 	TUint end2 = aBase2 + aSize2 -1;
   282 
   283 	if( aBase1 == aBase2 || end1 < aBase1 || end2 < aBase2 )
   284 		{
   285 		return ETrue;	// not necessarily overlapping, but they wrap which is an error
   286 		}
   287 
   288 	if( end1 < aBase2 || end2 < aBase1 )
   289 		{
   290 		return EFalse;
   291 		}
   292 
   293 	return ETrue;
   294 	}
   295 
   296 TInt CRofsMountCB::CheckExtension() 
   297 //
   298 //	Check for a Rofs extension and the end of the primary rofs image
   299 //
   300 	{
   301 	__PRINT(_L("CRofsMountCB::CheckExtension, Looking for Extension"));
   302 	const TUint8 KRofsHeaderId[4] = {'R', 'O', 'F', 'x' };
   303 	const TRofsHeader& h = ((CRofsMountCB*)this)->iHeader();
   304 
   305 	//check there is possibly enough room to have an extension
   306 	if( MAKE_TINT64(0,h.iMaxImageSize) + sizeof(TRofsHeader) >= iMediaSize )
   307 		{
   308 		__PRINT1(_L("CRofsMountCB::CheckExtension, media size too small for extension %x"), I64LOW(iMediaSize) );
   309 		return KErrNotFound;
   310 		}
   311 	
   312 	TPckgBuf<TRofsHeader> phExt;
   313 	TInt r = LocalDrive()->Read((TInt)h.iMaxImageSize, sizeof(TRofsHeader), phExt);
   314 	if( KErrNone != r )
   315 		return r;		
   316 
   317 	const TRofsHeader& hExt = phExt();
   318 	if( 0 != Mem::Compare( KRofsHeaderId, 4, hExt.iIdentifier, 4 ) )
   319 		{
   320 		__PRINT(_L("CRofsMountCB::CheckExtension, [ROFx] ID missing"));
   321 		return KErrNotFound;
   322 		}
   323 
   324 	if( hExt.iRofsFormatVersion < KEarliestSupportedFormatVersion
   325 		|| hExt.iRofsFormatVersion > KLatestSupportedFormatVersion )
   326 		{
   327 		__PRINT1(_L("CRofsMountCB::CheckExtension, unsupported version %x"), h.iRofsFormatVersion );
   328 		return KErrNotSupported;
   329 		}
   330 
   331 	if( MAKE_TINT64(0,hExt.iImageSize) > iMediaSize )
   332 		{
   333 		__PRINT1(_L("CRofsMountCB::CheckExtension, image size overflow %x"), h.iImageSize );
   334 		return KErrCorrupt;
   335 		}
   336 
   337 	if( MAKE_TINT64(0,hExt.iDirTreeOffset) > iMediaSize )
   338 		{
   339 		__PRINT1(_L("CRofsMountCB::CheckExtension, dir tree offset %x out-of-range"), h.iDirTreeOffset );
   340 		return KErrCorrupt;
   341 		}
   342 
   343 	if( MAKE_TINT64(0,hExt.iDirTreeOffset) + hExt.iDirTreeSize > iMediaSize )
   344 		{
   345 		__PRINT1(_L("CRofsMountCB::CheckExtension, dir tree size %x overflow"), h.iDirTreeSize );
   346 		return KErrCorrupt;
   347 		}
   348 
   349 	if( MAKE_TINT64(0,hExt.iDirFileEntriesOffset) > iMediaSize )
   350 		{
   351 		__PRINT1(_L("CRofsMountCB::CheckExtension, file entries offset %x out-of-range"), h.iDirFileEntriesOffset );
   352 		return KErrCorrupt;
   353 		}
   354 
   355 	if( MAKE_TINT64(0,hExt.iDirFileEntriesOffset) + MAKE_TINT64(0,h.iDirFileEntriesSize) > iMediaSize )
   356 		{
   357 		__PRINT1(_L("CRofsMountCB::CheckExtension, file entries size %x overflow"), h.iDirFileEntriesSize );
   358 		return KErrCorrupt;
   359 		}
   360 
   361 	if( IsOverlapping( hExt.iDirTreeOffset, hExt.iDirTreeSize,
   362 		hExt.iDirFileEntriesOffset, hExt.iDirFileEntriesSize ) )
   363 		{
   364 		__PRINT1(_L("CRofsMountCB::CheckExtension, dir & file entries overlap"), h.iDirTreeSize );
   365 		return KErrCorrupt;
   366 		}
   367 	Mem::Copy(&iHeader, &phExt, sizeof(TRofsHeader));
   368 
   369 	__PRINT(_L("CRofsMountCB::CheckExtension, Valid Extension found"));
   370 	return KErrNone;
   371 	}
   372 
   373 TInt CRofsMountCB::CheckHeader() const
   374 //
   375 // Returns KErrNone if the TRofsHeader looks ok, KErrCorrupt if not
   376 //
   377 	{
   378 	const TUint8 KRofsHeaderId[4] = {'R', 'O', 'F', 'S' };
   379 
   380 	// nasty cast required until TPckgBuf gains a const accessor member
   381 	const TRofsHeader& h = ((CRofsMountCB*)this)->iHeader();
   382 	if( 0 != Mem::Compare( KRofsHeaderId, 4, h.iIdentifier, 4 ) )
   383 		{
   384 		__PRINT(_L("CRofsMountCB::CheckHeader, [ROFS] ID missing"));
   385 		return KErrCorrupt;
   386 		}
   387 
   388 	if( h.iRofsFormatVersion < KEarliestSupportedFormatVersion
   389 		|| h.iRofsFormatVersion > KLatestSupportedFormatVersion )
   390 		{
   391 		__PRINT1(_L("CRofsMountCB::CheckHeader, unsupported version %x"), h.iRofsFormatVersion );
   392 		return KErrNotSupported;
   393 		}
   394 
   395 	if( MAKE_TINT64(0,h.iImageSize) > iMediaSize )
   396 		{
   397 		__PRINT1(_L("CRofsMountCB::CheckHeader, image size overflow %x"), h.iImageSize );
   398 		return KErrCorrupt;
   399 		}
   400 
   401 	if( MAKE_TINT64(0,h.iDirTreeOffset) > iMediaSize )
   402 		{
   403 		__PRINT1(_L("CRofsMountCB::CheckHeader, dir tree offset %x out-of-range"), h.iDirTreeOffset );
   404 		return KErrCorrupt;
   405 		}
   406 
   407 	if(TInt64(h.iDirTreeOffset + h.iDirTreeSize) > iMediaSize )
   408 		{
   409 		__PRINT1(_L("CRofsMountCB::CheckHeader, dir tree size %x overflow"), h.iDirTreeSize );
   410 		return KErrCorrupt;
   411 		}
   412 
   413 	if( MAKE_TINT64(0,h.iDirFileEntriesOffset) > iMediaSize )
   414 		{
   415 		__PRINT1(_L("CRofsMountCB::CheckHeader, file entries offset %x out-of-range"), h.iDirFileEntriesOffset );
   416 		return KErrCorrupt;
   417 		}
   418 
   419 	if( TInt64(h.iDirFileEntriesOffset + h.iDirFileEntriesSize) > iMediaSize )
   420 		{
   421 		__PRINT1(_L("CRofsMountCB::CheckHeader, file entries size %x overflow"), h.iDirFileEntriesSize );
   422 		return KErrCorrupt;
   423 		}
   424 
   425 	if( IsOverlapping( h.iDirTreeOffset, h.iDirTreeSize,
   426 		h.iDirFileEntriesOffset, h.iDirFileEntriesSize ) )
   427 		{
   428 		__PRINT1(_L("CRofsMountCB::CheckHeader, dir & file entries overlap"), h.iDirTreeSize );
   429 		return KErrCorrupt;
   430 		}
   431 
   432 	return KErrNone;
   433 	}
   434 
   435 
   436 TInt CRofsMountCB::ReMount()
   437 //
   438 // Try and remount this media.
   439 //
   440 	{
   441 
   442 	CRofs::Panic( CRofs::EPanicRemountNotSupported );
   443 	return(0);
   444 	}
   445 
   446 void CRofsMountCB::VolumeL(TVolumeInfo& aVolume) const
   447 //
   448 // Return the volume info.
   449 //
   450 	{
   451 
   452 	aVolume.iFree=0;
   453 	}
   454 
   455 
   456 void CRofsMountCB::SetVolumeL(TDes& /*aName*/)
   457 //
   458 // Set the volume label.
   459 //
   460 	{
   461 
   462 	User::Leave(KErrAccessDenied);
   463 	}
   464 
   465 void CRofsMountCB::MkDirL(const TDesC& /*aName*/)
   466 //
   467 // Make a directory.
   468 //
   469 	{
   470 
   471 	User::Leave(KErrAccessDenied);
   472 	}
   473 
   474 void CRofsMountCB::RmDirL(const TDesC& /*aName*/)
   475 //
   476 // Remove a directory.
   477 //
   478 	{
   479 
   480 	User::Leave(KErrAccessDenied);
   481 	}
   482 
   483 void CRofsMountCB::DeleteL(const TDesC& /*aName*/)
   484 //
   485 // Delete a file.
   486 //
   487 	{
   488 
   489 	User::Leave(KErrAccessDenied);
   490 	}
   491 
   492 void CRofsMountCB::RenameL(const TDesC& /*anOldName*/,const TDesC& /*aNewName*/)
   493 //
   494 // Rename a file or directory.
   495 //
   496 	{
   497 
   498 	User::Leave(KErrAccessDenied);
   499 	}
   500 
   501 void CRofsMountCB::ReplaceL(const TDesC& /*anOldName*/,const TDesC& /*aNewName*/)
   502 //
   503 // Atomic replace.
   504 //
   505 	{
   506 
   507 	User::Leave(KErrAccessDenied);
   508 	}
   509 
   510 void CRofsMountCB::EntryL(const TDesC& aName,TEntry& aEntry) const
   511 //
   512 // Get entry details.
   513 //
   514 	{
   515 	const TRofsDir* dir;
   516 	const TRofsEntry* entry = NULL;
   517 	iDirectoryCache->FindGeneralEntryL( aName, KEntryAttMaskSupported, dir, entry);
   518 	aEntry.iAtt = entry->iAtt;
   519 	aEntry.iSize = entry->iFileSize;
   520 	aEntry.iModified = ((TPckgBuf<TRofsHeader>&)(iHeader))().iTime;
   521 	aEntry.iName.Des().Copy( CDirectoryCache::NameAddress(entry), entry->iNameLength);
   522 	ReadUidL( entry->iFileAddress, aEntry, (TRofsEntry*)entry );
   523 	}
   524 
   525 void CRofsMountCB::ReadUidL( TUint /*aMediaOffset*/, TEntry& aEntry, TRofsEntry* aRofsEntry) const
   526 //
   527 // Internal function to read a uid if present.
   528 //
   529 	{
   530 
   531 	TBuf8<sizeof(TCheckedUid)> uidBuf;
   532 	uidBuf.SetLength(sizeof(TCheckedUid));
   533 	Mem::Copy(&uidBuf[0], &aRofsEntry->iUids[0],sizeof(TCheckedUid));
   534 
   535 	TCheckedUid uid(uidBuf);
   536 	aEntry.iType = uid.UidType();
   537 	}
   538 
   539 void CRofsMountCB::SetEntryL(const TDesC& /*aName*/,const TTime& /*aTime*/,TUint /*aMask*/,TUint /*aVal*/)
   540 //
   541 // Set entry details.
   542 //
   543 	{
   544 
   545 	User::Leave(KErrAccessDenied);
   546 	}
   547 
   548 void CRofsMountCB::FileOpenL(const TDesC& aName,TUint aMode,TFileOpen aOpen,CFileCB* aFile)
   549 //
   550 // Open a file on the current mount.
   551 //
   552 	{
   553 
   554 	if ( aMode & EFileWrite )
   555 		{
   556 		User::Leave(KErrAccessDenied);
   557 		}
   558 
   559 	if( EFileOpen != aOpen )
   560 		{
   561 		User::Leave(KErrAccessDenied);
   562 		}
   563 
   564 	const TRofsEntry* entry;
   565 	iDirectoryCache->FindFileEntryL(aName, entry);
   566 
   567 	CRofsFileCB& file=(*((CRofsFileCB*)aFile));
   568 	file.SetSize( entry->iFileSize );
   569 	file.SetAtt( entry->iAtt );
   570 	file.SetAttExtra( entry->iAttExtra );
   571 	file.SetModified( iHeader().iTime );
   572 	file.SetMediaBase( entry->iFileAddress );
   573 	}
   574 
   575 void CRofsMountCB::DirOpenL(const TDesC& aName,CDirCB* aDir)
   576 //
   577 // Open a directory on the current mount.
   578 //
   579 	{
   580 
   581     TFileName fileName=aName;
   582     TInt namePos=aName.LocateReverse(KPathDelimiter)+1; // Exclude path delimiter
   583     if (namePos==aName.Length())
   584         {
   585 		fileName+=_L("*");
   586 		}
   587 
   588 	const TRofsDir* dir;
   589 	iDirectoryCache->FindDirectoryEntryL( fileName.Left(namePos), dir );
   590 	
   591 	CRofsDirCB& dirCB=(*((CRofsDirCB*)aDir));
   592 	dirCB.SetDir( dir, fileName.Mid(namePos), iHeader().iTime );
   593 	dirCB.SetCache( iDirectoryCache );
   594 	}
   595 
   596 void CRofsMountCB::RawReadL(TInt64 aPos,TInt aLength,const TAny* aTrg,TInt anOffset,const RMessagePtr2& aMessage) const
   597 //
   598 // Read up to aLength data directly from the media
   599 //
   600 	{
   601 	if (aPos >= iMediaSize || aPos < 0 )
   602 		{
   603 		if (aMessage.Handle() == KLocalMessageHandle)
   604 			((TPtr8* )aTrg)->SetLength(0);
   605 		else
   606 			aMessage.WriteL(0,TPtrC8(NULL,0),anOffset);
   607 		}
   608 	else
   609 		{
   610 		TInt len=Min( (TInt)(I64LOW(iMediaSize)-I64LOW(aPos)),aLength);
   611 
   612 #ifdef _USE_TRUE_LRU_CACHE
   613 
   614 		__PRINT2(_L("ROFS::RawReadL() pos=%d len=%d"),aPos, aLength);
   615 		CacheReadL( I64LOW(aPos), len, aTrg, anOffset, aMessage );
   616 #else
   617 		TInt r = LocalDrive()->Read( aPos, len, aTrg, aMessage.Handle(), anOffset );
   618 		User::LeaveIfError( r );
   619 #endif
   620 		}
   621 	}
   622 
   623 void CRofsMountCB::RawWriteL(TInt64 /*aPos*/,TInt /*aLength*/,const TAny* /*aSrc*/,TInt /*anOffset*/,const RMessagePtr2& /*aMessage*/)
   624 //
   625 // Write aLength data to ROM (?)
   626 //
   627 	{
   628 
   629 	User::Leave(KErrAccessDenied);
   630 	}
   631 
   632 
   633 void CRofsMountCB::ReadSectionL(const TDesC& aName,TInt aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage)
   634 	//
   635 	// Note: this function will need some modification to support compresed files
   636 	//
   637 	{
   638 
   639 	__PRINT(_L("CRofsMountCB::ReadSectionL"));
   640 			
   641 	const TRofsEntry* entry;
   642 	iDirectoryCache->FindFileEntryL(aName, entry);
   643 
   644 	TInt size = entry->iFileSize;
   645 	TInt len = 0;	// initialise to stop a warning
   646 	if ( size >= (aPos+aLength) )
   647 		{
   648 		len = aLength;
   649 		}
   650 	else if ( size > aPos )
   651 		{
   652 		len=(size-aPos);
   653 		}
   654 	else
   655 		{
   656 		User::Leave(KErrEof);
   657 		}
   658 	
   659 	TInt64 pos64( (TUint)entry->iFileAddress);
   660 	pos64 += aPos;
   661 
   662 #ifdef _USE_TRUE_LRU_CACHE
   663 
   664 	__PRINT2(_L("ROFS::ReadSectionL() pos=%d len=%d"),I64LOW(pos64), aLength);
   665 	CacheReadL( I64LOW(pos64), len, aTrg, 0, aMessage );
   666 #else
   667 	TInt r = LocalDrive()->Read( pos64, len, aTrg, aMessage.Handle(), 0 );
   668 	User::LeaveIfError( r );
   669 #endif
   670 	}
   671 
   672 
   673 void CRofsMountCB::GetShortNameL(const TDesC& /*aLongName*/,TDes& /*aShortName*/)
   674 //
   675 // Return the short name associated with aLongName
   676 // Assumes all rom names are 8.3
   677 //
   678 	{
   679 
   680 	User::Leave(KErrNotSupported);
   681 	}
   682 
   683 void CRofsMountCB::GetLongNameL(const TDesC& /*aShortName*/,TDes& /*aLongName*/)
   684 //
   685 // Return the short name associated with aLongName
   686 // Assumes all rom names are 8.3
   687 //
   688 	{
   689 
   690 	User::Leave(KErrNotSupported);
   691 	}	
   692 
   693 
   694 TInt CRofsMountCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput) 
   695 	{
   696 	TInt r= KErrNone;
   697 	switch(aInterfaceId)
   698 		{
   699 		case (CMountCB::EFileAccessor):
   700 			((CMountCB::MFileAccessor*&) aInterface) = this;
   701 			break;
   702 
   703 		case CMountCB::ELocalBufferSupport:
   704 			return LocalDrive()->LocalBufferSupport();
   705 
   706 		case (CMountCB::EAddToCompositeMount):
   707 			iMountId = (TUint8)((TInt)aInput);
   708 			break;
   709 
   710 		default:
   711 			r=KErrNotSupported;
   712 		}
   713 	return r;
   714 	}
   715 
   716 TInt CRofsMountCB::GetFileUniqueId(const TDesC& aName, TInt64& aUniqueId)
   717 	{
   718 	// Get unique identifier for the file
   719 	const TRofsEntry* entry=NULL;
   720 	TInt err;
   721 	TRAP(err,iDirectoryCache->FindFileEntryL(aName, entry));
   722 	if(err!=KErrNone)
   723 		return err;
   724 	aUniqueId = MAKE_TINT64(0,entry->iFileAddress);
   725 	return KErrNone;
   726 	}
   727 
   728 TInt CRofsMountCB::Spare3(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
   729 	{
   730 	return KErrNotSupported;
   731 	}
   732 
   733 TInt CRofsMountCB::Spare2(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
   734 	{
   735 	return KErrNotSupported;
   736 	}
   737 
   738 TInt CRofsMountCB::Spare1(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
   739 	{
   740 	return KErrNotSupported;
   741 	}
   742 
   743 
   744 //***********************************************************
   745 //* File object
   746 //***********************************************************
   747 
   748 
   749 
   750 CRofsFileCB::CRofsFileCB()
   751 //
   752 // Constructor
   753 //
   754 	{
   755 	}
   756 
   757 
   758 void CRofsFileCB::ReadL(TInt64 aPos,TInt& aLength,TDes8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
   759 //
   760 // Read from the file.
   761 //
   762 	{
   763 	__PRINT(_L("CRofsFileCB::ReadL"));
   764 
   765 	// for now, convert pos to a TInt
   766 	if (aPos > KMaxTInt)
   767 		User::Leave(KErrNotSupported);
   768 	TInt pos = (TInt) aPos;
   769 	
   770 	if (pos>=iSize)
   771 		{
   772 		if (aMessage.Handle() == KLocalMessageHandle)
   773 			((TPtr8* )aDes)->SetLength(0);
   774 		else
   775 			aMessage.WriteL(0,TPtrC8(NULL,0),aOffset);
   776 		aLength=0;
   777 		}
   778 	else
   779 		{
   780 		TInt len=Min((iSize-pos),aLength);
   781 
   782 #ifdef _USE_TRUE_LRU_CACHE
   783 
   784 		__PRINT2(_L("ROFS::ReadL() pos=%d len=%d"),pos, len);
   785 		RofsMount().CacheReadL( pos + iMediaBase, len, aDes, aOffset, aMessage );
   786 #else
   787 		TInt r = RofsMount().LocalDrive()->Read( pos + iMediaBase, len, aDes, aMessage.Handle(),aOffset) ;
   788 		User::LeaveIfError( r );
   789 #endif
   790 		aLength=len;
   791 		}
   792 	}
   793 
   794 void CRofsFileCB::ReadL(TInt aPos,TInt& aLength,const TAny* aDes,const RMessagePtr2& aMessage)
   795 	{
   796 	ReadL(TInt64(aPos),aLength,(TDes8*) aDes,aMessage, 0);
   797 	}
   798 
   799 void CRofsFileCB::WriteL(TInt64 /*aPos*/,TInt& /*aLength*/,const TDesC8* /*aDes*/,const RMessagePtr2& /*aMessage*/, TInt /*aOffset*/)
   800 //
   801 // Write to the file.
   802 //
   803 	{
   804 	User::Leave(KErrAccessDenied);
   805 	}
   806 
   807 void CRofsFileCB::WriteL(TInt /*aPos*/,TInt& /*aLength*/,const TAny* /*aDes*/,const RMessagePtr2& /*aMessage*/)
   808 	{
   809 	User::Leave(KErrAccessDenied);
   810 	}
   811 
   812 void CRofsFileCB::RenameL(const TDesC& /*aDes*/)
   813 //
   814 // Rename the file.
   815 //
   816 	{
   817 	User::Leave(KErrAccessDenied);
   818 	}
   819 
   820 void CRofsFileCB::SetSizeL(TInt64 /*aSize*/)
   821 //
   822 // Set the file size.
   823 //
   824 	{
   825 	User::Leave(KErrAccessDenied);
   826 	}
   827 
   828 void CRofsFileCB::SetSizeL(TInt /*aSize*/)
   829 //
   830 // Set the file size.
   831 //
   832 	{
   833 	User::Leave(KErrAccessDenied);
   834 	}
   835 
   836 void CRofsFileCB::SetEntryL(const TTime& /*aTime*/,TUint /*aMask*/,TUint /*aVal*/)
   837 //
   838 // Set the entry's attributes and modified time.
   839 //
   840 	{
   841 	User::Leave(KErrAccessDenied);
   842 	}
   843 
   844 void CRofsFileCB::FlushAllL()
   845 //
   846 // Commit any buffered date to the media.
   847 //
   848 	{
   849 	User::Leave(KErrAccessDenied);
   850 	}
   851 
   852 void CRofsFileCB::FlushDataL()
   853 //
   854 // Commit any buffered date to the media.
   855 //
   856 	{
   857 	User::Leave(KErrAccessDenied);
   858 	}
   859 
   860 
   861 
   862 //***********************************************************
   863 //* Directory object
   864 //***********************************************************
   865 
   866 
   867 CRofsDirCB::CRofsDirCB()
   868 //
   869 // Constructor
   870 //
   871 	{
   872 	}
   873 
   874 
   875 CRofsDirCB::~CRofsDirCB()
   876 //
   877 // Destruct
   878 //
   879 	{
   880 	delete iMatch;
   881 	}
   882 
   883 TBool CRofsDirCB::MatchUid()
   884 	{
   885 	return (iUidType[0]!=TUid::Null() || iUidType[1]!=TUid::Null() || iUidType[2]!=TUid::Null());
   886 	}
   887 
   888 LOCAL_C TBool CompareUid(const TUidType& aUidTrg, const TUidType& aUidSuitor)
   889 //
   890 // Compare the suitor to the target pattern
   891 //
   892 	{
   893 	
   894 	if (aUidTrg[0]!=TUid::Null() && aUidTrg[0]!=aUidSuitor[0])
   895 		return(EFalse);
   896 	if (aUidTrg[1]!=TUid::Null() && aUidTrg[1]!=aUidSuitor[1])
   897 		return(EFalse);
   898 	if (aUidTrg[2]!=TUid::Null() && aUidTrg[2]!=aUidSuitor[2])
   899 		return(EFalse);
   900 	return(ETrue);
   901 	}
   902 
   903 
   904 void CRofsDirCB::SetDir( const TRofsDir* aDir, const TDesC& aName, TInt64& aTimeStamp )
   905 //
   906 // Set the directory and entry that we are on after open.
   907 //
   908 	{
   909     iDir = aDir;
   910 	iTimeStamp = aTimeStamp;
   911 	iNext = NULL;
   912 	iMatch = aName.AllocL();
   913 	iPending = EFalse;
   914 	}
   915 
   916 
   917 
   918 void CRofsDirCB::ReadL(TEntry& aEntry)
   919 //
   920 // Read the next entry from the directory.
   921 //
   922 	{
   923 	__ASSERT_DEBUG( NULL != iCache, CRofs::Panic( CRofs::EPanicDirCacheNull ));
   924 
   925 	FOREVER
   926 		{
   927 		if (!iPending)
   928 			{
   929 			TInt err;
   930 			do
   931 				{
   932 				// skip past all hidden files so they don't appear in the directory listing
   933 				TRAP(err, iCache->GetNextMatchingL( *iMatch, iAtt, iDir, iNext, KErrEof, EFalse ));
   934 				}
   935 			while(KErrHidden == err);
   936 			User::LeaveIfError(err);
   937 			}
   938 		iPending=EFalse;
   939 
   940 		// copy out the entry data
   941 		if((~iNext->iAttExtra & (KEntryAttUnique >> 23))!=0)
   942 			{
   943 			iEntry.iName.Des().Copy( CDirectoryCache::NameAddress(iNext), iNext->iNameLength );
   944 			iEntry.iName.Des().AppendFormat(_L("[%02x-00]"), iCache->GetMountId());
   945 			}
   946 		else
   947 			{
   948 			iEntry.iName.Des().Copy( CDirectoryCache::NameAddress(iNext), iNext->iNameLength );
   949 			}
   950 		iEntry.iAtt = iNext->iAtt;
   951 		iEntry.iSize = iNext->iFileSize;
   952 		iEntry.iModified = iTimeStamp;
   953 		aEntry = iEntry;
   954 		if (MatchUid())
   955 			{
   956 			static_cast<CRofsMountCB&>(Mount()).ReadUidL(iNext->iFileAddress, aEntry, (TRofsEntry*)iNext );
   957 			if (CompareUid(iUidType, aEntry.iType))
   958 				{
   959 				break;
   960 				}
   961 			}
   962 		else
   963 			{
   964 			break;
   965 			}
   966 		}
   967 	if ( (iAtt & KEntryAttAllowUid) && (aEntry.iAtt & KEntryAttDir)==0 && !MatchUid() )
   968 		{
   969 		static_cast<CRofsMountCB&>(Mount()).ReadUidL( iNext->iFileAddress, aEntry, (TRofsEntry*)iNext );
   970 		}
   971 	}
   972 
   973 
   974 //***********************************************************
   975 //* Filesystem factory object
   976 //***********************************************************
   977 
   978 CRofs::CRofs()
   979 //
   980 // Constructor
   981 //
   982 	{
   983 	}
   984 
   985 CRofs::~CRofs()
   986 //
   987 // Destruct
   988 //
   989 	{
   990 	}
   991 
   992 TInt CRofs::Install()
   993 //
   994 // Install the file system.
   995 //
   996 	{
   997 	iVersion=TVersion(KF32MajorVersionNumber,KF32MinorVersionNumber,KF32BuildVersionNumber);
   998     _LIT( KFileSystemName, "rofs");
   999 
  1000 	TDriveInfoV1Buf driveInfo;
  1001 	TInt r=UserHal::DriveInfo(driveInfo);
  1002 	if( KErrNone == r )
  1003 		{
  1004 		iTotalSupportedDrives = driveInfo().iTotalSupportedDrives;
  1005 		r = SetName(&KFileSystemName);
  1006 		}
  1007 	return r;
  1008 	}
  1009 
  1010 CMountCB* CRofs::NewMountL() const
  1011 //
  1012 // Create a new mount control block.
  1013 //
  1014 	{
  1015 	return new(ELeave) CRofsMountCB();
  1016 	}
  1017 
  1018 CFileCB* CRofs::NewFileL() const
  1019 //
  1020 // Create a new file.
  1021 //
  1022 	{
  1023 	return new(ELeave) CRofsFileCB();
  1024 	}
  1025 
  1026 CDirCB* CRofs::NewDirL() const
  1027 //
  1028 // Create a new directory lister.
  1029 //
  1030 	{
  1031 	return new(ELeave) CRofsDirCB();
  1032 	}
  1033 
  1034 CFormatCB* CRofs::NewFormatL() const
  1035 //
  1036 // Create a new media formatter.
  1037 //
  1038 	{
  1039 	User::Leave(KErrAccessDenied);
  1040 	return(NULL);
  1041 	}
  1042 
  1043 
  1044 
  1045 void CRofs::DriveInfo(TDriveInfo& anInfo,TInt aDriveNumber) const
  1046 //
  1047 // Return the drive info. iDriveAtt is already set.
  1048 //
  1049 	{
  1050     TLocalDriveCapsV2Buf localDriveCaps;
  1051 	(void)GetLocalDrive(aDriveNumber).Caps(localDriveCaps);
  1052 	// ignore return as Caps always returns valid Media and Drive attributes
  1053 	anInfo.iMediaAtt = localDriveCaps().iMediaAtt | KMediaAttWriteProtected;
  1054 	anInfo.iType     = localDriveCaps().iType;
  1055     anInfo.iDriveAtt = localDriveCaps().iDriveAtt | KDriveAttInternal | KDriveAttLocal;
  1056 
  1057 	}
  1058 
  1059 
  1060 TInt CRofs::DefaultPath(TDes& aPath) const
  1061 //
  1062 // Return the initial default path.
  1063 //
  1064 	{
  1065 
  1066 	aPath=_L("?:\\");
  1067 	aPath[0] = (TUint8) RFs::GetSystemDriveChar();
  1068 	return(KErrNone);
  1069 	}
  1070 
  1071 
  1072 
  1073 CRofs* CRofs::New()
  1074 //
  1075 // Create a ROFS filesystem
  1076 //
  1077 	{
  1078 	CRofs* fsys=new CRofs();
  1079 	return fsys;
  1080 	}
  1081 
  1082 
  1083 
  1084 
  1085 extern "C" {
  1086 EXPORT_C CFileSystem* CreateFileSystem()
  1087 //
  1088 // Create a new file system
  1089 //
  1090 	{
  1091 	return(CRofs::New());
  1092 	}
  1093 }
  1094 
  1095 //***********************************************************
  1096 //* BlockMap interface
  1097 //***********************************************************
  1098 	
  1099 
  1100 TInt CRofsFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos)
  1101 //	
  1102 // Retrieves the block map of a given section of the file, in the ROFS file system.
  1103 //	
  1104 	{
  1105 	__PRINT2(_L("CRofsFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos);
  1106 	TInt64 mediaBase = iMediaBase;
  1107 	TInt size = iSize;
  1108 
  1109 	// Make a TBlockMapEntry object, copy the start position and the length of the blockmap entry
  1110 	TBlockMapEntry blockMapEntry;
  1111 	if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) )
  1112 		return KErrNotSupported;
  1113 
  1114     TInt startPos = I64LOW(aStartPos);
  1115 	TInt endPos = I64LOW(aEndPos);
  1116 
  1117 	if((endPos-startPos)>size)
  1118 		return KErrArgument;
  1119 
  1120 	TInt drvNo=-1;
  1121 	TBusLocalDrive* locDrv;
  1122 	if((RofsMount().LocalDrive()->GetLocalDrive(locDrv)==KErrNone) && ((drvNo=GetLocalDriveNumber(locDrv))>=0) && (drvNo<KMaxLocalDrives))
  1123 		aInfo.iLocalDriveNumber=drvNo;
  1124 	else
  1125 		return KErrNotSupported;
  1126 
  1127 	TLocalDriveCapsV4Buf caps;
  1128 	TUint blockSz = 0;
  1129 	if((RofsMount().LocalDrive()->Caps(caps)==KErrNone) && caps().iFileSystemId==KDriveFileSysROFS)
  1130 		blockSz = caps().iNumBytesMain;
  1131 	else
  1132 		return KErrNotSupported;
  1133 
  1134 	TUint len = 0;
  1135 	if ( endPos >= size )
  1136 		len = size-startPos;
  1137 	else
  1138 		len = endPos-startPos;
  1139 
  1140 	TUint numBlocks = 0;
  1141 	TUint stBlockNr = (TUint) ((mediaBase + startPos)/blockSz);		// start block number (counts from 0)
  1142 	TUint stBlockAddr = stBlockNr*blockSz;					// address of start block
  1143 	
  1144 	while((stBlockAddr + numBlocks*blockSz) < (mediaBase + startPos + len))		// accumulate contiguous blocks until we pass the end of the region
  1145 		numBlocks++;
  1146 
  1147 	blockMapEntry.SetNumberOfBlocks( numBlocks );
  1148 	blockMapEntry.SetStartBlock( stBlockNr );
  1149 	aInfo.iStartBlockAddress = 0;							// start of partition = block 0
  1150 	aInfo.iBlockGranularity = blockSz;
  1151 	aInfo.iBlockStartOffset = (TUint) ((mediaBase + startPos)%blockSz);	// offset within first block to start of region
  1152 	// Then put it into the descriptor iMap within the structure aInfo of type SBlockMapInfo
  1153 	TPckg<TBlockMapEntry> entry(blockMapEntry);
  1154 	aInfo.iMap.Append(entry);
  1155 
  1156 	return KErrCompletion;
  1157 	}
  1158 
  1159 TInt CRofsFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
  1160 //
  1161 // 
  1162 //
  1163 	{
  1164 	switch(aInterfaceId)
  1165 		{
  1166 		case EBlockMapInterface:
  1167 			aInterface = (CFileCB::MBlockMapInterface*) this;
  1168 			return KErrNone;
  1169 
  1170 		case EGetLocalDrive:
  1171 			return (RofsMount()).LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface);
  1172 
  1173 		default:
  1174 			return CFileCB::GetInterface(aInterfaceId,aInterface,aInput);
  1175 		}
  1176 	}