|
1 /* |
|
2 * Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * Copy of pfsdump.h from syslibs code (syslibs/development/common/syslibs/store/HTOOLS/).Added CheckFileValidity() method. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include "pfsdump.h" |
|
21 |
|
22 // Class StoreFile |
|
23 int StoreFile::OutWidth; |
|
24 |
|
25 StoreFile::StoreFile() |
|
26 { |
|
27 } |
|
28 |
|
29 bool StoreFile::CheckFileValidity(char const* aFile,const Options& aOptions) |
|
30 { |
|
31 DumpSWICertstoreTool Tool; |
|
32 iFile.open(aFile, ios::binary); |
|
33 if(!iFile) |
|
34 { |
|
35 throw ECannotOpenFile; |
|
36 } |
|
37 else |
|
38 { |
|
39 unsigned long uid; |
|
40 iFile.read((char*)&uid,sizeof(uid)); |
|
41 iFile.seekg(0,ios::end); |
|
42 int size = iFile.tellg(); |
|
43 if(size <= 0) |
|
44 { |
|
45 if(!aOptions.CreateCCIFile() && !aOptions.CreateDetailCCIFile()) |
|
46 { |
|
47 cout << aFile <<" : File is Empty" << endl << endl; |
|
48 } |
|
49 return false; |
|
50 } |
|
51 |
|
52 if (size<FrameDes::First || uid!=PermanentFileStoreUid) |
|
53 { |
|
54 if(aOptions.CBasedWritableCertstore() || aOptions.ROMCertstore()) |
|
55 { |
|
56 if(!aOptions.CreateCCIFile() && !aOptions.CreateDetailCCIFile()) |
|
57 { |
|
58 cout << aFile <<": Is not a dat file \nor is a corrupt file" << endl << endl; |
|
59 } |
|
60 return false; |
|
61 } |
|
62 } |
|
63 |
|
64 else |
|
65 { |
|
66 if(aOptions.CBasedWritableCertstore() || aOptions.ROMCertstore()) |
|
67 { |
|
68 if(!aOptions.CreateCCIFile() && !aOptions.CreateDetailCCIFile()) |
|
69 { |
|
70 cout << aFile <<":" << endl; |
|
71 } |
|
72 } |
|
73 } |
|
74 |
|
75 iSize = size; |
|
76 int width = 0; |
|
77 while (size) |
|
78 { |
|
79 ++width; |
|
80 size >>= 4; |
|
81 } |
|
82 OutWidth = width; |
|
83 iFile.seekg(Header::Offset,ios::beg); |
|
84 iFile.read((char*)&iHeader,Header::Size); |
|
85 if (Empty()) |
|
86 { |
|
87 return false; |
|
88 } |
|
89 LoadFrames(); |
|
90 LoadToc(); |
|
91 } |
|
92 return true; |
|
93 } |
|
94 |
|
95 StoreFile::~StoreFile() |
|
96 { |
|
97 iFile.close(); |
|
98 } |
|
99 |
|
100 void StoreFile::LoadFrames() |
|
101 { |
|
102 FrameDes frame; |
|
103 int offset = FrameDes::First; |
|
104 int full = FrameDes::First+FrameDes::Interval; |
|
105 int diff = FrameDes::First; |
|
106 while (offset-FrameDes::Size<iSize) |
|
107 { |
|
108 if (offset==full) |
|
109 { |
|
110 full+=FrameDes::Interval; |
|
111 diff+=FrameDes::Size; |
|
112 } |
|
113 if (offset>iSize) |
|
114 { |
|
115 DumpSWICertstoreTool::Warning() << "in-complete link at " << FramePos(offset-diff) << endl; |
|
116 break; |
|
117 } |
|
118 iFile.seekg(offset-FrameDes::Size,ios::beg); |
|
119 iFile >> frame; |
|
120 iFrames.Add(FramePos(offset-diff),frame); |
|
121 int length = frame.Length(); |
|
122 if (length == 0) |
|
123 { |
|
124 if (full>iSize && offset>iSize) |
|
125 { |
|
126 DumpSWICertstoreTool::Warning() << "in-complete frame at " << FramePos(offset-diff) << endl; |
|
127 } |
|
128 offset = full; |
|
129 } |
|
130 else |
|
131 { |
|
132 int newoffset = offset+length+FrameDes::Size; |
|
133 if (newoffset>=full || newoffset-FrameDes::Size>iSize) |
|
134 { |
|
135 DumpSWICertstoreTool::Error() << "bad link at " << FramePos(offset-diff) << ", skipping to next anchor link" << endl; |
|
136 offset=full; |
|
137 } |
|
138 else |
|
139 { |
|
140 offset = newoffset; |
|
141 if (full-offset<=FrameDes::Size) |
|
142 { |
|
143 offset=full; |
|
144 } |
|
145 } |
|
146 } |
|
147 } |
|
148 iFrames.Complete(); |
|
149 } |
|
150 |
|
151 void StoreFile::LoadToc() |
|
152 { |
|
153 FramePos toc=iHeader.Toc(); |
|
154 Stream stream(iFrames,toc); |
|
155 if (!stream.IsGood()) |
|
156 { |
|
157 DumpSWICertstoreTool::Error() << "invalid toc address " << toc << endl; |
|
158 return; |
|
159 } |
|
160 if (stream.Type()!=FrameDes::Toc) |
|
161 { |
|
162 DumpSWICertstoreTool::Error() << "toc address " << toc << ": refers to non-toc frame"<< endl; |
|
163 return; |
|
164 } |
|
165 // find the requested store revision |
|
166 Frames::Iterator f=stream.Frame(); |
|
167 Frames::Iterator const first=iFrames.Begin(); |
|
168 for (int rev=Tool.TocRevision();rev;--rev) |
|
169 { |
|
170 do{ |
|
171 if (--f<first) |
|
172 { |
|
173 throw ENotAPermanentFileStore; |
|
174 } |
|
175 } while (f->iDes.Type()!=FrameDes::Toc); |
|
176 } |
|
177 iToc.Load(iFile,iFrames,f,iHeader.GetReloc()); |
|
178 |
|
179 // verify the Toc stream references |
|
180 Toc::Iterator const end=iToc.End(); |
|
181 for (Toc::Iterator iter=iToc.Begin();iter<end;++iter) |
|
182 { |
|
183 if (iter->iHandle.IsNull()) |
|
184 { |
|
185 DumpSWICertstoreTool::Error() << "missing entry in toc-delta for index " << (1+iter-iToc.Begin()) << endl; |
|
186 } |
|
187 else if (!iter->iHandle.Avail() && iter->Pos().Pos()>=0) |
|
188 { |
|
189 f=iFrames.Find(iter->Pos()); |
|
190 if (f==NULL) |
|
191 { |
|
192 DumpSWICertstoreTool::Error() << "invalid stream reference in toc entry " << iter->iHandle << endl; |
|
193 } |
|
194 else if (iter->Pos().Pos()>=toc.Pos()) |
|
195 { |
|
196 DumpSWICertstoreTool::Error() << "virtual stream reference in toc entry " << iter->iHandle << endl; |
|
197 } |
|
198 else if (f->iDes.Type()!=FrameDes::Data) |
|
199 { |
|
200 DumpSWICertstoreTool::Error() << "toc entry " << iter->iHandle << ": refers to non-data frame" << endl; |
|
201 } |
|
202 } |
|
203 } |
|
204 } |
|
205 |
|
206 Stream StoreFile::RootStream() |
|
207 { |
|
208 Toc::Head const& head=iToc.Header(); |
|
209 return FindStream(head.Root()); |
|
210 } |
|
211 |
|
212 Stream StoreFile::FindStream(Handle& aHandle) |
|
213 { |
|
214 Toc::Iterator const end=iToc.End(); |
|
215 Toc::Head const& head=iToc.Header(); |
|
216 for (Toc::Iterator iter=iToc.Begin();iter<end;++iter) |
|
217 { |
|
218 if (!iter->iHandle.Avail()) |
|
219 { |
|
220 if (iter->Pos().Pos() == -1) |
|
221 { |
|
222 continue; |
|
223 } |
|
224 if (iter->iHandle == aHandle) |
|
225 { |
|
226 return Stream(iFrames, iter->Pos()); |
|
227 } |
|
228 } |
|
229 } |
|
230 throw ENotAPermanentFileStore; |
|
231 } |
|
232 |
|
233 ifstream& StoreFile::File() |
|
234 { |
|
235 return iFile; |
|
236 } |
|
237 |
|
238 // Class Toc |
|
239 Toc::Toc() |
|
240 : iPos(0), iRep(NULL), iAvail(0) |
|
241 { |
|
242 memset(&iHeader,0,sizeof(iHeader)); |
|
243 } |
|
244 |
|
245 Toc::~Toc() |
|
246 { |
|
247 free(iRep); |
|
248 } |
|
249 |
|
250 void Toc::Base(const char* aPtr,int aCount) |
|
251 { |
|
252 Entry* e=iRep; |
|
253 for (int i=1;i<=aCount;++e,++i) |
|
254 { |
|
255 e->iHandle=i; // set the index part |
|
256 memcpy((char*)e+Entry::BaseRedundant,aPtr,Entry::BaseSize); |
|
257 aPtr+=Entry::BaseSize; |
|
258 } |
|
259 } |
|
260 |
|
261 void Toc::Load(istream& aStream,Frames const& aFrames,Frames::Iterator aFrame,Header::Reloc const* aReloc) |
|
262 { |
|
263 iPos = aFrame->iPos; |
|
264 Stream toc1(aFrame); |
|
265 void* toc = toc1.Load(aStream); |
|
266 const char* p = reinterpret_cast<char*>(toc); |
|
267 memcpy(&iHeader,p,Head::Size); |
|
268 p+=Head::Size; |
|
269 int n = iHeader.iCount; |
|
270 if (n < 0) |
|
271 { |
|
272 memset(&iHeader,0,Head::Size); |
|
273 DumpSWICertstoreTool::Error() << "corrupt toc" << endl; |
|
274 return; |
|
275 } |
|
276 iRep=static_cast<Entry*>(malloc(n*sizeof(Entry))); |
|
277 if (iRep==NULL) |
|
278 { |
|
279 throw ENotAPermanentFileStore; |
|
280 } |
|
281 if (iHeader.IsDelta()) |
|
282 { |
|
283 // verify the delta header |
|
284 memcpy(&iDelta,p,DeltaHead::Size); |
|
285 p+=DeltaHead::Size; |
|
286 int dn = iDelta.iCount; |
|
287 if (toc1.Length() != Head::Size + DeltaHead::Size + dn * Entry::DeltaSize) |
|
288 { |
|
289 memset(&iHeader,0,Head::Size); |
|
290 DumpSWICertstoreTool::Error() << "in-complete toc" << endl; |
|
291 return; |
|
292 } |
|
293 // find the toc-base |
|
294 FramePos tocbase(iDelta.iBase + Header::tocoffset); |
|
295 if (aReloc && aReloc->iHandle.IsTocBase()) |
|
296 { |
|
297 tocbase = aReloc->iPos; |
|
298 } |
|
299 Stream toc2(aFrames,tocbase); |
|
300 if (!toc2.IsGood()) |
|
301 { |
|
302 memset(&iHeader,0,Head::Size); |
|
303 DumpSWICertstoreTool::Error() << "invalid toc-base address " << tocbase << endl; |
|
304 return; |
|
305 } |
|
306 if (toc2.Type()!=FrameDes::Toc) |
|
307 { |
|
308 memset(&iHeader,0,Head::Size); |
|
309 DumpSWICertstoreTool::Error() << "toc-base address " << tocbase << ": refers to non-toc frame"<< endl; |
|
310 return; |
|
311 } |
|
312 // validate and load the toc-base |
|
313 void* tocb = toc2.Load(aStream); |
|
314 const char* p2 = reinterpret_cast<char*>(tocb); |
|
315 Head headbase; |
|
316 memcpy(&headbase,p2,Head::Size); |
|
317 p2+=Head::Size; |
|
318 if (headbase.IsDelta()) |
|
319 { |
|
320 memset(&iHeader,0,Head::Size); |
|
321 DumpSWICertstoreTool::Error() << "toc-base is a toc-delta"<< endl; |
|
322 return; |
|
323 } |
|
324 int bn = headbase.iCount; |
|
325 if (bn > n) |
|
326 { |
|
327 memset(&iHeader,0,Head::Size); |
|
328 DumpSWICertstoreTool::Error() << "toc-base is larger than toc"<< endl; |
|
329 return; |
|
330 } |
|
331 Base(p2,bn); |
|
332 free(tocb); |
|
333 // validate and update with the toc-delta |
|
334 int last = 0; |
|
335 while (--dn>=0) |
|
336 { |
|
337 Entry e; |
|
338 memcpy(&e,p,Entry::DeltaSize); |
|
339 p+=Entry::DeltaSize; |
|
340 int ix = e.iHandle.Index(); |
|
341 if (ix<=0 || ix > n) |
|
342 { |
|
343 memset(&iHeader,0,Head::Size); |
|
344 DumpSWICertstoreTool::Error() << "toc-delta entry " << e.iHandle << " is outside toc"<< endl; |
|
345 return; |
|
346 } |
|
347 if (ix <= last) |
|
348 { |
|
349 memset(&iHeader,0,Head::Size); |
|
350 DumpSWICertstoreTool::Error() << "toc-delta entry " << e.iHandle << " is out of order"<< endl; |
|
351 return; |
|
352 } |
|
353 iRep[ix-1] = e; |
|
354 last = ix; |
|
355 } |
|
356 } |
|
357 else |
|
358 { |
|
359 if (toc1.Length() != Head::Size + n * Entry::BaseSize) |
|
360 { |
|
361 memset(&iHeader,0,Head::Size); |
|
362 DumpSWICertstoreTool::Error() << "in-complete toc" << endl; |
|
363 return; |
|
364 } |
|
365 Base(p,n); |
|
366 } |
|
367 free(toc); |
|
368 |
|
369 // apply the relocation |
|
370 if (aReloc && !aReloc->iHandle.IsTocBase()) |
|
371 { |
|
372 int ix=aReloc->iHandle.Index(); |
|
373 if (ix<=0 || ix>n) |
|
374 { |
|
375 throw ENotAPermanentFileStore; |
|
376 } |
|
377 Entry& e=iRep[ix-1]; |
|
378 if (e.iHandle.Generation()!=aReloc->iHandle.Generation()) |
|
379 { |
|
380 throw ENotAPermanentFileStore; |
|
381 } |
|
382 e.iPos=aReloc->iPos.Pos(); |
|
383 } |
|
384 // count the available entries |
|
385 int avail=0; |
|
386 for (int i=0;i<n;++i) |
|
387 { |
|
388 if (iRep[i].iHandle.Avail()) |
|
389 ++avail; |
|
390 } |
|
391 iAvail=avail; |
|
392 // verify the available list |
|
393 Handle link=iHeader.iAvail; |
|
394 if (!link.IsNull()) |
|
395 { |
|
396 int ix=link.Index(); |
|
397 if (!link.Avail() || ix<=0 || ix >iHeader.iCount) |
|
398 { |
|
399 DumpSWICertstoreTool::Error() << "corrupt available link in toc header " << link << endl; |
|
400 return; |
|
401 } |
|
402 Entry const* en=&(*this)[ix]; |
|
403 if (en->iHandle!=link) |
|
404 { |
|
405 DumpSWICertstoreTool::Error() << "corrupt available link in toc header " << link << endl; |
|
406 return; |
|
407 } |
|
408 for (;;) |
|
409 { |
|
410 if (--avail<0) |
|
411 { |
|
412 DumpSWICertstoreTool::Error() << "corrupt available list, possible circular reference" << endl; |
|
413 return; |
|
414 } |
|
415 Handle next=en->Link(); |
|
416 if (next.IsNull()) |
|
417 { |
|
418 break; |
|
419 } |
|
420 ix=next.Index(); |
|
421 if (!next.Avail() || ix<=0 || ix >iHeader.iCount) |
|
422 { |
|
423 DumpSWICertstoreTool::Error() << "corrupt link in toc entry " << link << endl; |
|
424 return; |
|
425 } |
|
426 en=&(*this)[ix]; |
|
427 if (en->iHandle!=next) |
|
428 { |
|
429 DumpSWICertstoreTool::Error() << "corrupt link in toc entry " << link << endl; |
|
430 return; |
|
431 } |
|
432 link=next; |
|
433 } |
|
434 } |
|
435 if (avail!=0) |
|
436 { |
|
437 DumpSWICertstoreTool::Error() << "corrupt available list: free index leakage" << endl; |
|
438 } |
|
439 } |
|
440 |
|
441 ostream& operator<<(ostream& aStream,Toc const& aToc) |
|
442 { |
|
443 Toc::Head const& head=aToc.iHeader; |
|
444 aStream << "Toc at " << aToc.iPos << " with "; |
|
445 aStream << dec << head.iCount << (head.iCount==1 ? " entry: " : " entries: ") \ |
|
446 << head.iCount-aToc.iAvail << " allocated, " << aToc.iAvail << " free\n" << hex; |
|
447 return aStream << flush; |
|
448 } |
|
449 |
|
450 // Class Stream |
|
451 int Stream::Length() const |
|
452 { |
|
453 int total=0; |
|
454 Frames::Iterator f=iFrame; |
|
455 do { |
|
456 int len=f->iDes.Length(); |
|
457 if (len==0) |
|
458 len=f[1].iPos.Pos()-f[0].iPos.Pos(); |
|
459 total+=len; |
|
460 } while ((++f)->iDes.Type()==FrameDes::Continuation); |
|
461 return total; |
|
462 } |
|
463 |
|
464 void* Stream::Load(istream& aStream) const |
|
465 { |
|
466 int size = Length(); |
|
467 void* data = malloc(size); |
|
468 if (data==NULL) |
|
469 { |
|
470 throw ENotAPermanentFileStore; |
|
471 } |
|
472 char* read=reinterpret_cast<char*>(data); |
|
473 Frames::Iterator f = iFrame; |
|
474 do |
|
475 { |
|
476 FramePos pos=f->iPos; |
|
477 int len=f++->iDes.Length(); |
|
478 if (len==0) |
|
479 { |
|
480 len=f->iPos.Pos()-pos.Pos(); |
|
481 } |
|
482 aStream.seekg(FileOffset(pos).Offset(),ios::beg); |
|
483 aStream.read(read,len); |
|
484 read+=len; |
|
485 } while (f->iDes.Type()==FrameDes::Continuation); |
|
486 return data; |
|
487 } |
|
488 |
|
489 // Class Frames |
|
490 Frames::Frames() |
|
491 : iSize(0),iElements(0),iRep(NULL) |
|
492 {} |
|
493 |
|
494 Frames::~Frames() |
|
495 { |
|
496 free(iRep); |
|
497 } |
|
498 |
|
499 void Frames::Add(FramePos aPos,FrameDes aDes) |
|
500 { |
|
501 if (iElements==iSize) |
|
502 { |
|
503 iSize=iSize==0 ? 128 : iSize+iSize; |
|
504 void* rep=realloc(iRep,iSize*sizeof(*iRep)); |
|
505 if (rep==NULL) |
|
506 { |
|
507 throw ENotAPermanentFileStore; |
|
508 } |
|
509 iRep=(Element*)rep; |
|
510 } |
|
511 Element& element=iRep[iElements++]; |
|
512 element.iPos=aPos; |
|
513 element.iDes=aDes; |
|
514 } |
|
515 |
|
516 void Frames::Complete() |
|
517 // add a terminating entry |
|
518 { |
|
519 Add(0,0); |
|
520 --iElements; |
|
521 } |
|
522 |
|
523 Frames::Iterator Frames::Find(FramePos aPos) const |
|
524 { |
|
525 return (Element const*)bsearch(&aPos,iRep,iElements,sizeof(*iRep),Compare); |
|
526 } |
|
527 |
|
528 int Frames::Compare(void const* aLeft,void const* aRight) |
|
529 { |
|
530 int left=static_cast<FramePos const*>(aLeft)->Pos(); |
|
531 int right=static_cast<Element const*>(aRight)->iPos.Pos(); |
|
532 if (left<right) |
|
533 { |
|
534 return -1; |
|
535 } |
|
536 if (left>right) |
|
537 { |
|
538 return 1; |
|
539 } |
|
540 return 0; |
|
541 } |
|
542 |
|
543 // Header |
|
544 FramePos Header::Toc() const |
|
545 { |
|
546 return tocoffset+(!Dirty() && iToc.iZero==0 ? iToc.iPos : iBackupToc>>backupshift); |
|
547 } |
|
548 |
|
549 Header::Reloc const* Header::GetReloc() const |
|
550 { |
|
551 return (Dirty() || iToc.iZero==0) ? NULL : reinterpret_cast<Reloc const*>(&iReloc); |
|
552 } |
|
553 |
|
554 ostream& operator<<(ostream& aStream,Header const& aHeader) |
|
555 { |
|
556 aStream << "Header is " << (aHeader.Dirty() ? "dirty" : "clean"); |
|
557 Header::Reloc const* reloc=aHeader.GetReloc(); |
|
558 if (reloc!=NULL) |
|
559 { |
|
560 aStream << "\npending relocation of "; |
|
561 if (reloc->iHandle.IsTocBase()) |
|
562 { |
|
563 aStream << "toc-base"; |
|
564 } |
|
565 else |
|
566 { |
|
567 aStream << "stream " << StreamId(reloc->iHandle); |
|
568 } |
|
569 aStream << " to " << reloc->iPos; |
|
570 } |
|
571 return aStream << "\n\n" << flush; |
|
572 } |
|
573 |
|
574 // FileOffset |
|
575 FileOffset::FileOffset(FramePos aPos) |
|
576 // calculate the file offset for a streampos |
|
577 { |
|
578 int pos=aPos.Pos(); |
|
579 int n=pos>>FrameDes::FullShift; |
|
580 pos+=FrameDes::Size*n+FrameDes::First; |
|
581 iValue=pos; |
|
582 } |
|
583 |
|
584 FileOffset::operator FramePos() const |
|
585 { |
|
586 int pos=iValue-FrameDes::First; |
|
587 int n=pos/FrameDes::Interval; |
|
588 pos-=n*FrameDes::Size; |
|
589 return FramePos(pos); |
|
590 } |
|
591 |
|
592 ostream& operator<<(ostream& aStream,FileOffset anOffset) |
|
593 { |
|
594 return aStream << setw(StoreFile::OutWidth) << anOffset.iValue; |
|
595 } |
|
596 |
|
597 // Handle |
|
598 ostream& operator<<(ostream& aStream,Handle aHandle) |
|
599 { |
|
600 if (aHandle.IsNull()) |
|
601 { |
|
602 aStream << "Null"; |
|
603 } |
|
604 else |
|
605 { |
|
606 aStream << setw(6) << aHandle.Index() << ':' << aHandle.Generation(); |
|
607 } |
|
608 return aStream; |
|
609 } |
|
610 |
|
611 // FramePos |
|
612 ostream& operator<<(ostream& aStream,FramePos aPos) |
|
613 { |
|
614 return aStream << setw(StoreFile::OutWidth) << aPos.iValue << '[' << FileOffset(aPos) << ']'; |
|
615 } |
|
616 |
|
617 // FrameDes |
|
618 istream& operator>>(istream& aStream,FrameDes& aFrame) |
|
619 { |
|
620 return aStream.read((char*)&aFrame,FrameDes::Size); |
|
621 } |
|
622 |
|
623 ostream& operator<<(ostream& aStream,FrameDes aFrame) |
|
624 { |
|
625 static char const* FrameType[]={"free","data","toc","continuation"}; |
|
626 aStream << FrameType[aFrame.Type()] << " ("; |
|
627 int length=aFrame.Length(); |
|
628 if (length==0) |
|
629 { |
|
630 aStream << "full"; |
|
631 } |
|
632 else |
|
633 { |
|
634 aStream << dec << length << hex; |
|
635 } |
|
636 return aStream << ')'; |
|
637 } |
|
638 |