diff -r 000000000000 -r ba25891c3a9e secureswitools/swianalysistoolkit/source/dumpswicertstoretool/pfsdump.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/secureswitools/swianalysistoolkit/source/dumpswicertstoretool/pfsdump.cpp Thu Dec 17 08:51:10 2009 +0200 @@ -0,0 +1,638 @@ +/* +* Copyright (c) 1998-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: +* Copy of pfsdump.h from syslibs code (syslibs/development/common/syslibs/store/HTOOLS/).Added CheckFileValidity() method. +* +*/ + + +#include "pfsdump.h" + +// Class StoreFile +int StoreFile::OutWidth; + +StoreFile::StoreFile() + { + } + +bool StoreFile::CheckFileValidity(char const* aFile,const Options& aOptions) + { + DumpSWICertstoreTool Tool; + iFile.open(aFile, ios::binary); + if(!iFile) + { + throw ECannotOpenFile; + } + else + { + unsigned long uid; + iFile.read((char*)&uid,sizeof(uid)); + iFile.seekg(0,ios::end); + int size = iFile.tellg(); + if(size <= 0) + { + if(!aOptions.CreateCCIFile() && !aOptions.CreateDetailCCIFile()) + { + cout << aFile <<" : File is Empty" << endl << endl; + } + return false; + } + + if (size>= 4; + } + OutWidth = width; + iFile.seekg(Header::Offset,ios::beg); + iFile.read((char*)&iHeader,Header::Size); + if (Empty()) + { + return false; + } + LoadFrames(); + LoadToc(); + } + return true; + } + +StoreFile::~StoreFile() + { + iFile.close(); + } + +void StoreFile::LoadFrames() + { + FrameDes frame; + int offset = FrameDes::First; + int full = FrameDes::First+FrameDes::Interval; + int diff = FrameDes::First; + while (offset-FrameDes::SizeiSize) + { + DumpSWICertstoreTool::Warning() << "in-complete link at " << FramePos(offset-diff) << endl; + break; + } + iFile.seekg(offset-FrameDes::Size,ios::beg); + iFile >> frame; + iFrames.Add(FramePos(offset-diff),frame); + int length = frame.Length(); + if (length == 0) + { + if (full>iSize && offset>iSize) + { + DumpSWICertstoreTool::Warning() << "in-complete frame at " << FramePos(offset-diff) << endl; + } + offset = full; + } + else + { + int newoffset = offset+length+FrameDes::Size; + if (newoffset>=full || newoffset-FrameDes::Size>iSize) + { + DumpSWICertstoreTool::Error() << "bad link at " << FramePos(offset-diff) << ", skipping to next anchor link" << endl; + offset=full; + } + else + { + offset = newoffset; + if (full-offset<=FrameDes::Size) + { + offset=full; + } + } + } + } + iFrames.Complete(); + } + +void StoreFile::LoadToc() + { + FramePos toc=iHeader.Toc(); + Stream stream(iFrames,toc); + if (!stream.IsGood()) + { + DumpSWICertstoreTool::Error() << "invalid toc address " << toc << endl; + return; + } + if (stream.Type()!=FrameDes::Toc) + { + DumpSWICertstoreTool::Error() << "toc address " << toc << ": refers to non-toc frame"<< endl; + return; + } + // find the requested store revision + Frames::Iterator f=stream.Frame(); + Frames::Iterator const first=iFrames.Begin(); + for (int rev=Tool.TocRevision();rev;--rev) + { + do{ + if (--fiDes.Type()!=FrameDes::Toc); + } + iToc.Load(iFile,iFrames,f,iHeader.GetReloc()); + + // verify the Toc stream references + Toc::Iterator const end=iToc.End(); + for (Toc::Iterator iter=iToc.Begin();iteriHandle.IsNull()) + { + DumpSWICertstoreTool::Error() << "missing entry in toc-delta for index " << (1+iter-iToc.Begin()) << endl; + } + else if (!iter->iHandle.Avail() && iter->Pos().Pos()>=0) + { + f=iFrames.Find(iter->Pos()); + if (f==NULL) + { + DumpSWICertstoreTool::Error() << "invalid stream reference in toc entry " << iter->iHandle << endl; + } + else if (iter->Pos().Pos()>=toc.Pos()) + { + DumpSWICertstoreTool::Error() << "virtual stream reference in toc entry " << iter->iHandle << endl; + } + else if (f->iDes.Type()!=FrameDes::Data) + { + DumpSWICertstoreTool::Error() << "toc entry " << iter->iHandle << ": refers to non-data frame" << endl; + } + } + } + } + +Stream StoreFile::RootStream() + { + Toc::Head const& head=iToc.Header(); + return FindStream(head.Root()); + } + +Stream StoreFile::FindStream(Handle& aHandle) + { + Toc::Iterator const end=iToc.End(); + Toc::Head const& head=iToc.Header(); + for (Toc::Iterator iter=iToc.Begin();iteriHandle.Avail()) + { + if (iter->Pos().Pos() == -1) + { + continue; + } + if (iter->iHandle == aHandle) + { + return Stream(iFrames, iter->Pos()); + } + } + } + throw ENotAPermanentFileStore; + } + +ifstream& StoreFile::File() + { + return iFile; + } + +// Class Toc +Toc::Toc() + : iPos(0), iRep(NULL), iAvail(0) + { + memset(&iHeader,0,sizeof(iHeader)); + } + +Toc::~Toc() + { + free(iRep); + } + +void Toc::Base(const char* aPtr,int aCount) + { + Entry* e=iRep; + for (int i=1;i<=aCount;++e,++i) + { + e->iHandle=i; // set the index part + memcpy((char*)e+Entry::BaseRedundant,aPtr,Entry::BaseSize); + aPtr+=Entry::BaseSize; + } + } + +void Toc::Load(istream& aStream,Frames const& aFrames,Frames::Iterator aFrame,Header::Reloc const* aReloc) + { + iPos = aFrame->iPos; + Stream toc1(aFrame); + void* toc = toc1.Load(aStream); + const char* p = reinterpret_cast(toc); + memcpy(&iHeader,p,Head::Size); + p+=Head::Size; + int n = iHeader.iCount; + if (n < 0) + { + memset(&iHeader,0,Head::Size); + DumpSWICertstoreTool::Error() << "corrupt toc" << endl; + return; + } + iRep=static_cast(malloc(n*sizeof(Entry))); + if (iRep==NULL) + { + throw ENotAPermanentFileStore; + } + if (iHeader.IsDelta()) + { + // verify the delta header + memcpy(&iDelta,p,DeltaHead::Size); + p+=DeltaHead::Size; + int dn = iDelta.iCount; + if (toc1.Length() != Head::Size + DeltaHead::Size + dn * Entry::DeltaSize) + { + memset(&iHeader,0,Head::Size); + DumpSWICertstoreTool::Error() << "in-complete toc" << endl; + return; + } + // find the toc-base + FramePos tocbase(iDelta.iBase + Header::tocoffset); + if (aReloc && aReloc->iHandle.IsTocBase()) + { + tocbase = aReloc->iPos; + } + Stream toc2(aFrames,tocbase); + if (!toc2.IsGood()) + { + memset(&iHeader,0,Head::Size); + DumpSWICertstoreTool::Error() << "invalid toc-base address " << tocbase << endl; + return; + } + if (toc2.Type()!=FrameDes::Toc) + { + memset(&iHeader,0,Head::Size); + DumpSWICertstoreTool::Error() << "toc-base address " << tocbase << ": refers to non-toc frame"<< endl; + return; + } + // validate and load the toc-base + void* tocb = toc2.Load(aStream); + const char* p2 = reinterpret_cast(tocb); + Head headbase; + memcpy(&headbase,p2,Head::Size); + p2+=Head::Size; + if (headbase.IsDelta()) + { + memset(&iHeader,0,Head::Size); + DumpSWICertstoreTool::Error() << "toc-base is a toc-delta"<< endl; + return; + } + int bn = headbase.iCount; + if (bn > n) + { + memset(&iHeader,0,Head::Size); + DumpSWICertstoreTool::Error() << "toc-base is larger than toc"<< endl; + return; + } + Base(p2,bn); + free(tocb); + // validate and update with the toc-delta + int last = 0; + while (--dn>=0) + { + Entry e; + memcpy(&e,p,Entry::DeltaSize); + p+=Entry::DeltaSize; + int ix = e.iHandle.Index(); + if (ix<=0 || ix > n) + { + memset(&iHeader,0,Head::Size); + DumpSWICertstoreTool::Error() << "toc-delta entry " << e.iHandle << " is outside toc"<< endl; + return; + } + if (ix <= last) + { + memset(&iHeader,0,Head::Size); + DumpSWICertstoreTool::Error() << "toc-delta entry " << e.iHandle << " is out of order"<< endl; + return; + } + iRep[ix-1] = e; + last = ix; + } + } + else + { + if (toc1.Length() != Head::Size + n * Entry::BaseSize) + { + memset(&iHeader,0,Head::Size); + DumpSWICertstoreTool::Error() << "in-complete toc" << endl; + return; + } + Base(p,n); + } + free(toc); + + // apply the relocation + if (aReloc && !aReloc->iHandle.IsTocBase()) + { + int ix=aReloc->iHandle.Index(); + if (ix<=0 || ix>n) + { + throw ENotAPermanentFileStore; + } + Entry& e=iRep[ix-1]; + if (e.iHandle.Generation()!=aReloc->iHandle.Generation()) + { + throw ENotAPermanentFileStore; + } + e.iPos=aReloc->iPos.Pos(); + } + // count the available entries + int avail=0; + for (int i=0;iiHeader.iCount) + { + DumpSWICertstoreTool::Error() << "corrupt available link in toc header " << link << endl; + return; + } + Entry const* en=&(*this)[ix]; + if (en->iHandle!=link) + { + DumpSWICertstoreTool::Error() << "corrupt available link in toc header " << link << endl; + return; + } + for (;;) + { + if (--avail<0) + { + DumpSWICertstoreTool::Error() << "corrupt available list, possible circular reference" << endl; + return; + } + Handle next=en->Link(); + if (next.IsNull()) + { + break; + } + ix=next.Index(); + if (!next.Avail() || ix<=0 || ix >iHeader.iCount) + { + DumpSWICertstoreTool::Error() << "corrupt link in toc entry " << link << endl; + return; + } + en=&(*this)[ix]; + if (en->iHandle!=next) + { + DumpSWICertstoreTool::Error() << "corrupt link in toc entry " << link << endl; + return; + } + link=next; + } + } + if (avail!=0) + { + DumpSWICertstoreTool::Error() << "corrupt available list: free index leakage" << endl; + } + } + +ostream& operator<<(ostream& aStream,Toc const& aToc) + { + Toc::Head const& head=aToc.iHeader; + aStream << "Toc at " << aToc.iPos << " with "; + aStream << dec << head.iCount << (head.iCount==1 ? " entry: " : " entries: ") \ + << head.iCount-aToc.iAvail << " allocated, " << aToc.iAvail << " free\n" << hex; + return aStream << flush; + } + +// Class Stream +int Stream::Length() const + { + int total=0; + Frames::Iterator f=iFrame; + do { + int len=f->iDes.Length(); + if (len==0) + len=f[1].iPos.Pos()-f[0].iPos.Pos(); + total+=len; + } while ((++f)->iDes.Type()==FrameDes::Continuation); + return total; + } + +void* Stream::Load(istream& aStream) const + { + int size = Length(); + void* data = malloc(size); + if (data==NULL) + { + throw ENotAPermanentFileStore; + } + char* read=reinterpret_cast(data); + Frames::Iterator f = iFrame; + do + { + FramePos pos=f->iPos; + int len=f++->iDes.Length(); + if (len==0) + { + len=f->iPos.Pos()-pos.Pos(); + } + aStream.seekg(FileOffset(pos).Offset(),ios::beg); + aStream.read(read,len); + read+=len; + } while (f->iDes.Type()==FrameDes::Continuation); + return data; + } + +// Class Frames +Frames::Frames() + : iSize(0),iElements(0),iRep(NULL) + {} + +Frames::~Frames() + { + free(iRep); + } + +void Frames::Add(FramePos aPos,FrameDes aDes) + { + if (iElements==iSize) + { + iSize=iSize==0 ? 128 : iSize+iSize; + void* rep=realloc(iRep,iSize*sizeof(*iRep)); + if (rep==NULL) + { + throw ENotAPermanentFileStore; + } + iRep=(Element*)rep; + } + Element& element=iRep[iElements++]; + element.iPos=aPos; + element.iDes=aDes; + } + +void Frames::Complete() +// add a terminating entry + { + Add(0,0); + --iElements; + } + +Frames::Iterator Frames::Find(FramePos aPos) const + { + return (Element const*)bsearch(&aPos,iRep,iElements,sizeof(*iRep),Compare); + } + +int Frames::Compare(void const* aLeft,void const* aRight) + { + int left=static_cast(aLeft)->Pos(); + int right=static_cast(aRight)->iPos.Pos(); + if (leftright) + { + return 1; + } + return 0; + } + +// Header +FramePos Header::Toc() const + { + return tocoffset+(!Dirty() && iToc.iZero==0 ? iToc.iPos : iBackupToc>>backupshift); + } + +Header::Reloc const* Header::GetReloc() const + { + return (Dirty() || iToc.iZero==0) ? NULL : reinterpret_cast(&iReloc); + } + +ostream& operator<<(ostream& aStream,Header const& aHeader) + { + aStream << "Header is " << (aHeader.Dirty() ? "dirty" : "clean"); + Header::Reloc const* reloc=aHeader.GetReloc(); + if (reloc!=NULL) + { + aStream << "\npending relocation of "; + if (reloc->iHandle.IsTocBase()) + { + aStream << "toc-base"; + } + else + { + aStream << "stream " << StreamId(reloc->iHandle); + } + aStream << " to " << reloc->iPos; + } + return aStream << "\n\n" << flush; + } + +// FileOffset +FileOffset::FileOffset(FramePos aPos) + // calculate the file offset for a streampos + { + int pos=aPos.Pos(); + int n=pos>>FrameDes::FullShift; + pos+=FrameDes::Size*n+FrameDes::First; + iValue=pos; + } + +FileOffset::operator FramePos() const + { + int pos=iValue-FrameDes::First; + int n=pos/FrameDes::Interval; + pos-=n*FrameDes::Size; + return FramePos(pos); + } + +ostream& operator<<(ostream& aStream,FileOffset anOffset) + { + return aStream << setw(StoreFile::OutWidth) << anOffset.iValue; + } + +// Handle +ostream& operator<<(ostream& aStream,Handle aHandle) + { + if (aHandle.IsNull()) + { + aStream << "Null"; + } + else + { + aStream << setw(6) << aHandle.Index() << ':' << aHandle.Generation(); + } + return aStream; + } + +// FramePos +ostream& operator<<(ostream& aStream,FramePos aPos) + { + return aStream << setw(StoreFile::OutWidth) << aPos.iValue << '[' << FileOffset(aPos) << ']'; + } + +// FrameDes +istream& operator>>(istream& aStream,FrameDes& aFrame) + { + return aStream.read((char*)&aFrame,FrameDes::Size); + } + +ostream& operator<<(ostream& aStream,FrameDes aFrame) + { + static char const* FrameType[]={"free","data","toc","continuation"}; + aStream << FrameType[aFrame.Type()] << " ("; + int length=aFrame.Length(); + if (length==0) + { + aStream << "full"; + } + else + { + aStream << dec << length << hex; + } + return aStream << ')'; + } +