secureswitools/swianalysistoolkit/source/dumpswicertstoretool/pfsdump.cpp
changeset 0 ba25891c3a9e
child 25 7333d7932ef7
--- /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 << ')';
+	}
+