--- /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<FrameDes::First || uid!=PermanentFileStoreUid)
+ {
+ if(aOptions.CBasedWritableCertstore() || aOptions.ROMCertstore())
+ {
+ if(!aOptions.CreateCCIFile() && !aOptions.CreateDetailCCIFile())
+ {
+ cout << aFile <<": Is not a dat file \nor is a corrupt file" << endl << endl;
+ }
+ return false;
+ }
+ }
+
+ else
+ {
+ if(aOptions.CBasedWritableCertstore() || aOptions.ROMCertstore())
+ {
+ if(!aOptions.CreateCCIFile() && !aOptions.CreateDetailCCIFile())
+ {
+ cout << aFile <<":" << endl;
+ }
+ }
+ }
+
+ iSize = size;
+ int width = 0;
+ while (size)
+ {
+ ++width;
+ 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::Size<iSize)
+ {
+ if (offset==full)
+ {
+ full+=FrameDes::Interval;
+ diff+=FrameDes::Size;
+ }
+ if (offset>iSize)
+ {
+ 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 (--f<first)
+ {
+ throw ENotAPermanentFileStore;
+ }
+ } while (f->iDes.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();iter<end;++iter)
+ {
+ if (iter->iHandle.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();iter<end;++iter)
+ {
+ if (!iter->iHandle.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<char*>(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<Entry*>(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<char*>(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;i<n;++i)
+ {
+ if (iRep[i].iHandle.Avail())
+ ++avail;
+ }
+ iAvail=avail;
+ // verify the available list
+ Handle link=iHeader.iAvail;
+ if (!link.IsNull())
+ {
+ int ix=link.Index();
+ if (!link.Avail() || ix<=0 || ix >iHeader.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<char*>(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<FramePos const*>(aLeft)->Pos();
+ int right=static_cast<Element const*>(aRight)->iPos.Pos();
+ if (left<right)
+ {
+ return -1;
+ }
+ if (left>right)
+ {
+ 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<Reloc const*>(&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 << ')';
+ }
+