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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #include <e32std_private.h>
22 void CRofs::Panic( TPanic aPanic )
24 _LIT( KCategory, "ROFSFSY" );
25 User::Panic( KCategory, aPanic );
28 #ifdef _USE_TRUE_LRU_CACHE
31 //***********************************************************
32 //* Data Read Cache for Rofs
33 //***********************************************************
35 TCacheSegment::TCacheSegment()
42 void TCacheSegment::Set(TInt aPos)
44 // Set the diskPos of the data cached
50 //***********************************************************
51 CRofsLruCache::CRofsLruCache(CRofsMountCB* aMount, TInt64 aMediaSize)
53 // Least recently used data cache
55 : iQue(_FOFF(TCacheSegment,iLink)), iMediaSize(aMediaSize)
58 __PRINT(_L("CLruCache::CLruCache()"));
61 CRofsLruCache::~CRofsLruCache()
63 // Free all data segments
66 __PRINT(_L("CLruCache::~CLruCache()"));
68 TDblQueIter<TCacheSegment> iter(iQue);
69 while((TCacheSegment*)iter)
75 TUint8* CRofsLruCache::Find(TInt aPos, TInt aLength)
77 // Find aPos in the cache or return NULL
80 __PRINT(_L("CLruCache::Find()"));
82 TDblQueIter<TCacheSegment> iter(iQue);
84 while((data=iter++)!=NULL) //need to do a range check here
88 const TInt KEndOfSegment= data->iPos+ KSizeOfSegment;
89 if(data->iPos <= aPos && (KEndOfSegment >=aPos))
91 if((aPos+aLength) > (KEndOfSegment))
97 if(!iQue.IsFirst(data))
100 iQue.AddFirst(*data);
102 return(&data->Data()[aPos-data->iPos]);
105 // If we got here, it means that we don't have it in cache at all
111 TUint8* CRofsLruCache::ReadL(TInt aPos, TInt aLength)
113 // Find aPos in the cache or read the data
116 // Remember for Big size Nand the size of page can increase to 2K. Need to add this feature?
117 __PRINT(_L("CLruCache::ReadL()"));
121 TUint8* res=Find(aPos, aLength);
125 // Didn't find in the cache, read data from media
126 // Align to page boundaries
127 TInt pagePos = aPos & ~(KPageSize-1);
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();
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);
148 return(&dataBuf[aPos & (KPageSize-1)]);
151 CRofsLruCache* CRofsLruCache::New(TInt aSegmentSize, CRofsMountCB* aMount, TInt64 aMediaSize)
153 // Create an LruList and one segment
156 __PRINT(_L("CRofsLruCache::New()"));
157 CRofsLruCache* lru=new CRofsLruCache(aMount, aMediaSize);
160 for(TInt i=0; i<KSizeOfCacheInPages;i++)
162 TCacheSegment* seg=(TCacheSegment*)User::Alloc(aSegmentSize+sizeof(TCacheSegment));
168 Mem::FillZ(seg,aSegmentSize+sizeof(TCacheSegment));
169 *seg=TCacheSegment();
170 lru->iQue.AddFirst(*seg);
175 //***********************************************************
177 //***********************************************************
180 void CRofsMountCB::CacheReadL(TInt aPos, TInt aLength,const TAny* aDes,TInt anOffset, const RMessagePtr2& aMessage) const
182 // Do a cached read if possible else read from media and insert to cache
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))
190 TInt ret = LocalDrive()->Read(aPos,aLength,aDes, aMessage.Handle(), anOffset);
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);
206 CRofsMountCB::CRofsMountCB()
213 void CRofsMountCB::Dismounted()
215 // Dummy implementation of pure virtual function
220 void CRofsMountCB::MountL(TBool /*aForceMount*/)
223 // Only allowed to leave with KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
227 // create the local drive
228 TInt r=CreateLocalDrive(GetLocalDrive(Drive().DriveNumber()));
229 User::LeaveIfError(r);
233 TLocalDriveCapsV2Buf caps;
234 User::LeaveIfError(LocalDrive()->Caps(caps));
235 iMediaSize = caps().iSize;
237 // Read ROFS image header
238 r = LocalDrive()->Read( 0, sizeof(TRofsHeader), iHeader );
239 __PRINT1(_L("CRofsMountCB::MountL, Reading Header %d"), r);
242 User::Leave( KErrNotReady );
246 __PRINT1(_L("CRofsMountCB::MountL, Check Header %d"), r);
247 User::LeaveIfError( r );
250 __PRINT1(_L("CRofsMountCB::MountL, Check Extension %d"), r);
251 if(r!=KErrNone && r!=KErrNotFound)
255 // Construct the directory cache
257 iDirectoryCache = new(ELeave) CDirectoryCache( *this, *LocalDrive(), iHeader() );
258 iDirectoryCache->ConstructL();
260 #ifdef _USE_TRUE_LRU_CACHE
262 // Construct the data cache
264 iDataCache = CRofsLruCache::New(KSizeOfSegment,this, iMediaSize);
266 User::Leave(KErrNoMemory);
269 _LIT( KVolumeName, "Rofs" );
270 SetVolumeName( TPtrC(KVolumeName).AllocL() );
271 __PRINT(_L("CRofsMountCB::MountL, End of Mount"));
275 LOCAL_D TBool IsOverlapping( TUint aBase1, TUint aSize1, TUint aBase2, TUint aSize2 )
277 // Check files and directories are not overlapping
280 TUint end1 = aBase1 + aSize1 - 1;
281 TUint end2 = aBase2 + aSize2 -1;
283 if( aBase1 == aBase2 || end1 < aBase1 || end2 < aBase2 )
285 return ETrue; // not necessarily overlapping, but they wrap which is an error
288 if( end1 < aBase2 || end2 < aBase1 )
296 TInt CRofsMountCB::CheckExtension()
298 // Check for a Rofs extension and the end of the primary rofs image
301 __PRINT(_L("CRofsMountCB::CheckExtension, Looking for Extension"));
302 const TUint8 KRofsHeaderId[4] = {'R', 'O', 'F', 'x' };
303 const TRofsHeader& h = ((CRofsMountCB*)this)->iHeader();
305 //check there is possibly enough room to have an extension
306 if( MAKE_TINT64(0,h.iMaxImageSize) + sizeof(TRofsHeader) >= iMediaSize )
308 __PRINT1(_L("CRofsMountCB::CheckExtension, media size too small for extension %x"), I64LOW(iMediaSize) );
312 TPckgBuf<TRofsHeader> phExt;
313 TInt r = LocalDrive()->Read((TInt)h.iMaxImageSize, sizeof(TRofsHeader), phExt);
317 const TRofsHeader& hExt = phExt();
318 if( 0 != Mem::Compare( KRofsHeaderId, 4, hExt.iIdentifier, 4 ) )
320 __PRINT(_L("CRofsMountCB::CheckExtension, [ROFx] ID missing"));
324 if( hExt.iRofsFormatVersion < KEarliestSupportedFormatVersion
325 || hExt.iRofsFormatVersion > KLatestSupportedFormatVersion )
327 __PRINT1(_L("CRofsMountCB::CheckExtension, unsupported version %x"), h.iRofsFormatVersion );
328 return KErrNotSupported;
331 if( MAKE_TINT64(0,hExt.iImageSize) > iMediaSize )
333 __PRINT1(_L("CRofsMountCB::CheckExtension, image size overflow %x"), h.iImageSize );
337 if( MAKE_TINT64(0,hExt.iDirTreeOffset) > iMediaSize )
339 __PRINT1(_L("CRofsMountCB::CheckExtension, dir tree offset %x out-of-range"), h.iDirTreeOffset );
343 if( MAKE_TINT64(0,hExt.iDirTreeOffset) + hExt.iDirTreeSize > iMediaSize )
345 __PRINT1(_L("CRofsMountCB::CheckExtension, dir tree size %x overflow"), h.iDirTreeSize );
349 if( MAKE_TINT64(0,hExt.iDirFileEntriesOffset) > iMediaSize )
351 __PRINT1(_L("CRofsMountCB::CheckExtension, file entries offset %x out-of-range"), h.iDirFileEntriesOffset );
355 if( MAKE_TINT64(0,hExt.iDirFileEntriesOffset) + MAKE_TINT64(0,h.iDirFileEntriesSize) > iMediaSize )
357 __PRINT1(_L("CRofsMountCB::CheckExtension, file entries size %x overflow"), h.iDirFileEntriesSize );
361 if( IsOverlapping( hExt.iDirTreeOffset, hExt.iDirTreeSize,
362 hExt.iDirFileEntriesOffset, hExt.iDirFileEntriesSize ) )
364 __PRINT1(_L("CRofsMountCB::CheckExtension, dir & file entries overlap"), h.iDirTreeSize );
367 Mem::Copy(&iHeader, &phExt, sizeof(TRofsHeader));
369 __PRINT(_L("CRofsMountCB::CheckExtension, Valid Extension found"));
373 TInt CRofsMountCB::CheckHeader() const
375 // Returns KErrNone if the TRofsHeader looks ok, KErrCorrupt if not
378 const TUint8 KRofsHeaderId[4] = {'R', 'O', 'F', 'S' };
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 ) )
384 __PRINT(_L("CRofsMountCB::CheckHeader, [ROFS] ID missing"));
388 if( h.iRofsFormatVersion < KEarliestSupportedFormatVersion
389 || h.iRofsFormatVersion > KLatestSupportedFormatVersion )
391 __PRINT1(_L("CRofsMountCB::CheckHeader, unsupported version %x"), h.iRofsFormatVersion );
392 return KErrNotSupported;
395 if( MAKE_TINT64(0,h.iImageSize) > iMediaSize )
397 __PRINT1(_L("CRofsMountCB::CheckHeader, image size overflow %x"), h.iImageSize );
401 if( MAKE_TINT64(0,h.iDirTreeOffset) > iMediaSize )
403 __PRINT1(_L("CRofsMountCB::CheckHeader, dir tree offset %x out-of-range"), h.iDirTreeOffset );
407 if(TInt64(h.iDirTreeOffset + h.iDirTreeSize) > iMediaSize )
409 __PRINT1(_L("CRofsMountCB::CheckHeader, dir tree size %x overflow"), h.iDirTreeSize );
413 if( MAKE_TINT64(0,h.iDirFileEntriesOffset) > iMediaSize )
415 __PRINT1(_L("CRofsMountCB::CheckHeader, file entries offset %x out-of-range"), h.iDirFileEntriesOffset );
419 if( TInt64(h.iDirFileEntriesOffset + h.iDirFileEntriesSize) > iMediaSize )
421 __PRINT1(_L("CRofsMountCB::CheckHeader, file entries size %x overflow"), h.iDirFileEntriesSize );
425 if( IsOverlapping( h.iDirTreeOffset, h.iDirTreeSize,
426 h.iDirFileEntriesOffset, h.iDirFileEntriesSize ) )
428 __PRINT1(_L("CRofsMountCB::CheckHeader, dir & file entries overlap"), h.iDirTreeSize );
436 TInt CRofsMountCB::ReMount()
438 // Try and remount this media.
442 CRofs::Panic( CRofs::EPanicRemountNotSupported );
446 void CRofsMountCB::VolumeL(TVolumeInfo& aVolume) const
448 // Return the volume info.
456 void CRofsMountCB::SetVolumeL(TDes& /*aName*/)
458 // Set the volume label.
462 User::Leave(KErrAccessDenied);
465 void CRofsMountCB::MkDirL(const TDesC& /*aName*/)
471 User::Leave(KErrAccessDenied);
474 void CRofsMountCB::RmDirL(const TDesC& /*aName*/)
476 // Remove a directory.
480 User::Leave(KErrAccessDenied);
483 void CRofsMountCB::DeleteL(const TDesC& /*aName*/)
489 User::Leave(KErrAccessDenied);
492 void CRofsMountCB::RenameL(const TDesC& /*anOldName*/,const TDesC& /*aNewName*/)
494 // Rename a file or directory.
498 User::Leave(KErrAccessDenied);
501 void CRofsMountCB::ReplaceL(const TDesC& /*anOldName*/,const TDesC& /*aNewName*/)
507 User::Leave(KErrAccessDenied);
510 void CRofsMountCB::EntryL(const TDesC& aName,TEntry& aEntry) const
512 // Get entry details.
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 );
525 void CRofsMountCB::ReadUidL( TUint /*aMediaOffset*/, TEntry& aEntry, TRofsEntry* aRofsEntry) const
527 // Internal function to read a uid if present.
531 TBuf8<sizeof(TCheckedUid)> uidBuf;
532 uidBuf.SetLength(sizeof(TCheckedUid));
533 Mem::Copy(&uidBuf[0], &aRofsEntry->iUids[0],sizeof(TCheckedUid));
535 TCheckedUid uid(uidBuf);
536 aEntry.iType = uid.UidType();
539 void CRofsMountCB::SetEntryL(const TDesC& /*aName*/,const TTime& /*aTime*/,TUint /*aMask*/,TUint /*aVal*/)
541 // Set entry details.
545 User::Leave(KErrAccessDenied);
548 void CRofsMountCB::FileOpenL(const TDesC& aName,TUint aMode,TFileOpen aOpen,CFileCB* aFile)
550 // Open a file on the current mount.
554 if ( aMode & EFileWrite )
556 User::Leave(KErrAccessDenied);
559 if( EFileOpen != aOpen )
561 User::Leave(KErrAccessDenied);
564 const TRofsEntry* entry;
565 iDirectoryCache->FindFileEntryL(aName, entry);
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 );
575 void CRofsMountCB::DirOpenL(const TDesC& aName,CDirCB* aDir)
577 // Open a directory on the current mount.
581 TFileName fileName=aName;
582 TInt namePos=aName.LocateReverse(KPathDelimiter)+1; // Exclude path delimiter
583 if (namePos==aName.Length())
589 iDirectoryCache->FindDirectoryEntryL( fileName.Left(namePos), dir );
591 CRofsDirCB& dirCB=(*((CRofsDirCB*)aDir));
592 dirCB.SetDir( dir, fileName.Mid(namePos), iHeader().iTime );
593 dirCB.SetCache( iDirectoryCache );
596 void CRofsMountCB::RawReadL(TInt64 aPos,TInt aLength,const TAny* aTrg,TInt anOffset,const RMessagePtr2& aMessage) const
598 // Read up to aLength data directly from the media
601 if (aPos >= iMediaSize || aPos < 0 )
603 if (aMessage.Handle() == KLocalMessageHandle)
604 ((TPtr8* )aTrg)->SetLength(0);
606 aMessage.WriteL(0,TPtrC8(NULL,0),anOffset);
610 TInt len=Min( (TInt)(I64LOW(iMediaSize)-I64LOW(aPos)),aLength);
612 #ifdef _USE_TRUE_LRU_CACHE
614 __PRINT2(_L("ROFS::RawReadL() pos=%d len=%d"),aPos, aLength);
615 CacheReadL( I64LOW(aPos), len, aTrg, anOffset, aMessage );
617 TInt r = LocalDrive()->Read( aPos, len, aTrg, aMessage.Handle(), anOffset );
618 User::LeaveIfError( r );
623 void CRofsMountCB::RawWriteL(TInt64 /*aPos*/,TInt /*aLength*/,const TAny* /*aSrc*/,TInt /*anOffset*/,const RMessagePtr2& /*aMessage*/)
625 // Write aLength data to ROM (?)
629 User::Leave(KErrAccessDenied);
633 void CRofsMountCB::ReadSectionL(const TDesC& aName,TInt aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage)
635 // Note: this function will need some modification to support compresed files
639 __PRINT(_L("CRofsMountCB::ReadSectionL"));
641 const TRofsEntry* entry;
642 iDirectoryCache->FindFileEntryL(aName, entry);
644 TInt size = entry->iFileSize;
645 TInt len = 0; // initialise to stop a warning
646 if ( size >= (aPos+aLength) )
650 else if ( size > aPos )
656 User::Leave(KErrEof);
659 TInt64 pos64( (TUint)entry->iFileAddress);
662 #ifdef _USE_TRUE_LRU_CACHE
664 __PRINT2(_L("ROFS::ReadSectionL() pos=%d len=%d"),I64LOW(pos64), aLength);
665 CacheReadL( I64LOW(pos64), len, aTrg, 0, aMessage );
667 TInt r = LocalDrive()->Read( pos64, len, aTrg, aMessage.Handle(), 0 );
668 User::LeaveIfError( r );
673 void CRofsMountCB::GetShortNameL(const TDesC& /*aLongName*/,TDes& /*aShortName*/)
675 // Return the short name associated with aLongName
676 // Assumes all rom names are 8.3
680 User::Leave(KErrNotSupported);
683 void CRofsMountCB::GetLongNameL(const TDesC& /*aShortName*/,TDes& /*aLongName*/)
685 // Return the short name associated with aLongName
686 // Assumes all rom names are 8.3
690 User::Leave(KErrNotSupported);
694 TInt CRofsMountCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
699 case (CMountCB::EFileAccessor):
700 ((CMountCB::MFileAccessor*&) aInterface) = this;
703 case CMountCB::ELocalBufferSupport:
704 return LocalDrive()->LocalBufferSupport();
706 case (CMountCB::EAddToCompositeMount):
707 iMountId = (TUint8)((TInt)aInput);
716 TInt CRofsMountCB::GetFileUniqueId(const TDesC& aName, TInt64& aUniqueId)
718 // Get unique identifier for the file
719 const TRofsEntry* entry=NULL;
721 TRAP(err,iDirectoryCache->FindFileEntryL(aName, entry));
724 aUniqueId = MAKE_TINT64(0,entry->iFileAddress);
728 TInt CRofsMountCB::Spare3(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
730 return KErrNotSupported;
733 TInt CRofsMountCB::Spare2(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
735 return KErrNotSupported;
738 TInt CRofsMountCB::Spare1(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
740 return KErrNotSupported;
744 //***********************************************************
746 //***********************************************************
750 CRofsFileCB::CRofsFileCB()
758 void CRofsFileCB::ReadL(TInt64 aPos,TInt& aLength,TDes8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
760 // Read from the file.
763 __PRINT(_L("CRofsFileCB::ReadL"));
765 // for now, convert pos to a TInt
767 User::Leave(KErrNotSupported);
768 TInt pos = (TInt) aPos;
772 if (aMessage.Handle() == KLocalMessageHandle)
773 ((TPtr8* )aDes)->SetLength(0);
775 aMessage.WriteL(0,TPtrC8(NULL,0),aOffset);
780 TInt len=Min((iSize-pos),aLength);
782 #ifdef _USE_TRUE_LRU_CACHE
784 __PRINT2(_L("ROFS::ReadL() pos=%d len=%d"),pos, len);
785 RofsMount().CacheReadL( pos + iMediaBase, len, aDes, aOffset, aMessage );
787 TInt r = RofsMount().LocalDrive()->Read( pos + iMediaBase, len, aDes, aMessage.Handle(),aOffset) ;
788 User::LeaveIfError( r );
794 void CRofsFileCB::ReadL(TInt aPos,TInt& aLength,const TAny* aDes,const RMessagePtr2& aMessage)
796 ReadL(TInt64(aPos),aLength,(TDes8*) aDes,aMessage, 0);
799 void CRofsFileCB::WriteL(TInt64 /*aPos*/,TInt& /*aLength*/,const TDesC8* /*aDes*/,const RMessagePtr2& /*aMessage*/, TInt /*aOffset*/)
801 // Write to the file.
804 User::Leave(KErrAccessDenied);
807 void CRofsFileCB::WriteL(TInt /*aPos*/,TInt& /*aLength*/,const TAny* /*aDes*/,const RMessagePtr2& /*aMessage*/)
809 User::Leave(KErrAccessDenied);
812 void CRofsFileCB::RenameL(const TDesC& /*aDes*/)
817 User::Leave(KErrAccessDenied);
820 void CRofsFileCB::SetSizeL(TInt64 /*aSize*/)
822 // Set the file size.
825 User::Leave(KErrAccessDenied);
828 void CRofsFileCB::SetSizeL(TInt /*aSize*/)
830 // Set the file size.
833 User::Leave(KErrAccessDenied);
836 void CRofsFileCB::SetEntryL(const TTime& /*aTime*/,TUint /*aMask*/,TUint /*aVal*/)
838 // Set the entry's attributes and modified time.
841 User::Leave(KErrAccessDenied);
844 void CRofsFileCB::FlushAllL()
846 // Commit any buffered date to the media.
849 User::Leave(KErrAccessDenied);
852 void CRofsFileCB::FlushDataL()
854 // Commit any buffered date to the media.
857 User::Leave(KErrAccessDenied);
862 //***********************************************************
864 //***********************************************************
867 CRofsDirCB::CRofsDirCB()
875 CRofsDirCB::~CRofsDirCB()
883 TBool CRofsDirCB::MatchUid()
885 return (iUidType[0]!=TUid::Null() || iUidType[1]!=TUid::Null() || iUidType[2]!=TUid::Null());
888 LOCAL_C TBool CompareUid(const TUidType& aUidTrg, const TUidType& aUidSuitor)
890 // Compare the suitor to the target pattern
894 if (aUidTrg[0]!=TUid::Null() && aUidTrg[0]!=aUidSuitor[0])
896 if (aUidTrg[1]!=TUid::Null() && aUidTrg[1]!=aUidSuitor[1])
898 if (aUidTrg[2]!=TUid::Null() && aUidTrg[2]!=aUidSuitor[2])
904 void CRofsDirCB::SetDir( const TRofsDir* aDir, const TDesC& aName, TInt64& aTimeStamp )
906 // Set the directory and entry that we are on after open.
910 iTimeStamp = aTimeStamp;
912 iMatch = aName.AllocL();
918 void CRofsDirCB::ReadL(TEntry& aEntry)
920 // Read the next entry from the directory.
923 __ASSERT_DEBUG( NULL != iCache, CRofs::Panic( CRofs::EPanicDirCacheNull ));
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 ));
935 while(KErrHidden == err);
936 User::LeaveIfError(err);
940 // copy out the entry data
941 if((~iNext->iAttExtra & (KEntryAttUnique >> 23))!=0)
943 iEntry.iName.Des().Copy( CDirectoryCache::NameAddress(iNext), iNext->iNameLength );
944 iEntry.iName.Des().AppendFormat(_L("[%02x-00]"), iCache->GetMountId());
948 iEntry.iName.Des().Copy( CDirectoryCache::NameAddress(iNext), iNext->iNameLength );
950 iEntry.iAtt = iNext->iAtt;
951 iEntry.iSize = iNext->iFileSize;
952 iEntry.iModified = iTimeStamp;
956 static_cast<CRofsMountCB&>(Mount()).ReadUidL(iNext->iFileAddress, aEntry, (TRofsEntry*)iNext );
957 if (CompareUid(iUidType, aEntry.iType))
967 if ( (iAtt & KEntryAttAllowUid) && (aEntry.iAtt & KEntryAttDir)==0 && !MatchUid() )
969 static_cast<CRofsMountCB&>(Mount()).ReadUidL( iNext->iFileAddress, aEntry, (TRofsEntry*)iNext );
974 //***********************************************************
975 //* Filesystem factory object
976 //***********************************************************
992 TInt CRofs::Install()
994 // Install the file system.
997 iVersion=TVersion(KF32MajorVersionNumber,KF32MinorVersionNumber,KF32BuildVersionNumber);
998 _LIT( KFileSystemName, "rofs");
1000 TDriveInfoV1Buf driveInfo;
1001 TInt r=UserHal::DriveInfo(driveInfo);
1004 iTotalSupportedDrives = driveInfo().iTotalSupportedDrives;
1005 r = SetName(&KFileSystemName);
1010 CMountCB* CRofs::NewMountL() const
1012 // Create a new mount control block.
1015 return new(ELeave) CRofsMountCB();
1018 CFileCB* CRofs::NewFileL() const
1020 // Create a new file.
1023 return new(ELeave) CRofsFileCB();
1026 CDirCB* CRofs::NewDirL() const
1028 // Create a new directory lister.
1031 return new(ELeave) CRofsDirCB();
1034 CFormatCB* CRofs::NewFormatL() const
1036 // Create a new media formatter.
1039 User::Leave(KErrAccessDenied);
1045 void CRofs::DriveInfo(TDriveInfo& anInfo,TInt aDriveNumber) const
1047 // Return the drive info. iDriveAtt is already set.
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;
1060 TInt CRofs::DefaultPath(TDes& aPath) const
1062 // Return the initial default path.
1067 aPath[0] = (TUint8) RFs::GetSystemDriveChar();
1075 // Create a ROFS filesystem
1078 CRofs* fsys=new CRofs();
1086 EXPORT_C CFileSystem* CreateFileSystem()
1088 // Create a new file system
1091 return(CRofs::New());
1095 //***********************************************************
1096 //* BlockMap interface
1097 //***********************************************************
1100 TInt CRofsFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos)
1102 // Retrieves the block map of a given section of the file, in the ROFS file system.
1105 __PRINT2(_L("CRofsFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos);
1106 TInt64 mediaBase = iMediaBase;
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;
1114 TInt startPos = I64LOW(aStartPos);
1115 TInt endPos = I64LOW(aEndPos);
1117 if((endPos-startPos)>size)
1118 return KErrArgument;
1121 TBusLocalDrive* locDrv;
1122 if((RofsMount().LocalDrive()->GetLocalDrive(locDrv)==KErrNone) && ((drvNo=GetLocalDriveNumber(locDrv))>=0) && (drvNo<KMaxLocalDrives))
1123 aInfo.iLocalDriveNumber=drvNo;
1125 return KErrNotSupported;
1127 TLocalDriveCapsV4Buf caps;
1129 if((RofsMount().LocalDrive()->Caps(caps)==KErrNone) && caps().iFileSystemId==KDriveFileSysROFS)
1130 blockSz = caps().iNumBytesMain;
1132 return KErrNotSupported;
1135 if ( endPos >= size )
1136 len = size-startPos;
1138 len = endPos-startPos;
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
1144 while((stBlockAddr + numBlocks*blockSz) < (mediaBase + startPos + len)) // accumulate contiguous blocks until we pass the end of the region
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);
1156 return KErrCompletion;
1159 TInt CRofsFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
1164 switch(aInterfaceId)
1166 case EBlockMapInterface:
1167 aInterface = (CFileCB::MBlockMapInterface*) this;
1170 case EGetLocalDrive:
1171 return (RofsMount()).LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface);
1174 return CFileCB::GetInterface(aInterfaceId,aInterface,aInput);