Annotation of elwix/tools/oldlzma/SRC/7zip/Archive/7z_C/7zIn.c, revision 1.1.1.1
1.1 misho 1: /* 7zIn.c */
2:
3: #include "7zIn.h"
4: #include "7zCrc.h"
5: #include "7zDecode.h"
6:
7: #define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; }
8:
9: void SzArDbExInit(CArchiveDatabaseEx *db)
10: {
11: SzArchiveDatabaseInit(&db->Database);
12: db->FolderStartPackStreamIndex = 0;
13: db->PackStreamStartPositions = 0;
14: db->FolderStartFileIndex = 0;
15: db->FileIndexToFolderIndexMap = 0;
16: }
17:
18: void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *))
19: {
20: freeFunc(db->FolderStartPackStreamIndex);
21: freeFunc(db->PackStreamStartPositions);
22: freeFunc(db->FolderStartFileIndex);
23: freeFunc(db->FileIndexToFolderIndexMap);
24: SzArchiveDatabaseFree(&db->Database, freeFunc);
25: SzArDbExInit(db);
26: }
27:
28: /*
29: CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const
30: {
31: return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
32: }
33:
34: CFileSize GetFilePackSize(int fileIndex) const
35: {
36: int folderIndex = FileIndexToFolderIndexMap[fileIndex];
37: if (folderIndex >= 0)
38: {
39: const CFolder &folderInfo = Folders[folderIndex];
40: if (FolderStartFileIndex[folderIndex] == fileIndex)
41: return GetFolderFullPackSize(folderIndex);
42: }
43: return 0;
44: }
45: */
46:
47:
48: SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size))
49: {
50: UInt32 startPos = 0;
51: CFileSize startPosSize = 0;
52: UInt32 i;
53: UInt32 folderIndex = 0;
54: UInt32 indexInFolder = 0;
55: db->FolderStartPackStreamIndex = (UInt32 *)allocFunc(db->Database.NumFolders * sizeof(UInt32));
56: RINOM(db->FolderStartPackStreamIndex);
57: for(i = 0; i < db->Database.NumFolders; i++)
58: {
59: db->FolderStartPackStreamIndex[i] = startPos;
60: startPos += db->Database.Folders[i].NumPackStreams;
61: }
62:
63: db->PackStreamStartPositions = (CFileSize *)allocFunc(db->Database.NumPackStreams * sizeof(CFileSize));
64: RINOM(db->PackStreamStartPositions);
65:
66: for(i = 0; i < db->Database.NumPackStreams; i++)
67: {
68: db->PackStreamStartPositions[i] = startPosSize;
69: startPosSize += db->Database.PackSizes[i];
70: }
71:
72: db->FolderStartFileIndex = (UInt32 *)allocFunc(db->Database.NumFolders * sizeof(UInt32));
73: RINOM(db->FolderStartFileIndex);
74:
75: db->FileIndexToFolderIndexMap = (UInt32 *)allocFunc(db->Database.NumFiles * sizeof(UInt32));
76: RINOM(db->FileIndexToFolderIndexMap);
77:
78: for (i = 0; i < db->Database.NumFiles; i++)
79: {
80: CFileItem *file = db->Database.Files + i;
81: int emptyStream = !file->HasStream;
82: if (emptyStream && indexInFolder == 0)
83: {
84: db->FileIndexToFolderIndexMap[i] = (UInt32)-1;
85: continue;
86: }
87: if (indexInFolder == 0)
88: {
89: /*
90: v3.13 incorrectly worked with empty folders
91: v4.07: Loop for skipping empty folders
92: */
93: while(1)
94: {
95: if (folderIndex >= db->Database.NumFolders)
96: return SZE_ARCHIVE_ERROR;
97: db->FolderStartFileIndex[folderIndex] = i;
98: if (db->Database.Folders[folderIndex].NumUnPackStreams != 0)
99: break;
100: folderIndex++;
101: }
102: }
103: db->FileIndexToFolderIndexMap[i] = folderIndex;
104: if (emptyStream)
105: continue;
106: indexInFolder++;
107: if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams)
108: {
109: folderIndex++;
110: indexInFolder = 0;
111: }
112: }
113: return SZ_OK;
114: }
115:
116:
117: CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder)
118: {
119: return db->ArchiveInfo.DataStartPosition +
120: db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder];
121: }
122:
123: CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex)
124: {
125: UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex];
126: CFolder *folder = db->Database.Folders + folderIndex;
127: CFileSize size = 0;
128: UInt32 i;
129: for (i = 0; i < folder->NumPackStreams; i++)
130: size += db->Database.PackSizes[packStreamIndex + i];
131: return size;
132: }
133:
134:
135: /*
136: SZ_RESULT SzReadTime(const CObjectVector<CSzByteBuffer> &dataVector,
137: CObjectVector<CFileItem> &files, UInt64 type)
138: {
139: CBoolVector boolVector;
140: RINOK(ReadBoolVector2(files.Size(), boolVector))
141:
142: CStreamSwitch streamSwitch;
143: RINOK(streamSwitch.Set(this, &dataVector));
144:
145: for(int i = 0; i < files.Size(); i++)
146: {
147: CFileItem &file = files[i];
148: CArchiveFileTime fileTime;
149: bool defined = boolVector[i];
150: if (defined)
151: {
152: UInt32 low, high;
153: RINOK(SzReadUInt32(low));
154: RINOK(SzReadUInt32(high));
155: fileTime.dwLowDateTime = low;
156: fileTime.dwHighDateTime = high;
157: }
158: switch(type)
159: {
160: case k7zIdCreationTime:
161: file.IsCreationTimeDefined = defined;
162: if (defined)
163: file.CreationTime = fileTime;
164: break;
165: case k7zIdLastWriteTime:
166: file.IsLastWriteTimeDefined = defined;
167: if (defined)
168: file.LastWriteTime = fileTime;
169: break;
170: case k7zIdLastAccessTime:
171: file.IsLastAccessTimeDefined = defined;
172: if (defined)
173: file.LastAccessTime = fileTime;
174: break;
175: }
176: }
177: return SZ_OK;
178: }
179: */
180:
181: SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size)
182: {
183: #ifdef _LZMA_IN_CB
184: while (size > 0)
185: {
186: Byte *inBuffer;
187: size_t processedSize;
188: RINOK(inStream->Read(inStream, &inBuffer, size, &processedSize));
189: if (processedSize == 0 || processedSize > size)
190: return SZE_FAIL;
191: size -= processedSize;
192: do
193: {
194: *data++ = *inBuffer++;
195: }
196: while (--processedSize != 0);
197: }
198: #else
199: size_t processedSize;
200: RINOK(inStream->Read(inStream, data, size, &processedSize));
201: if (processedSize != size)
202: return SZE_FAIL;
203: #endif
204: return SZ_OK;
205: }
206:
207: SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data)
208: {
209: return SafeReadDirect(inStream, data, 1);
210: }
211:
212: SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value)
213: {
214: int i;
215: *value = 0;
216: for (i = 0; i < 4; i++)
217: {
218: Byte b;
219: RINOK(SafeReadDirectByte(inStream, &b));
220: *value |= ((UInt32)b << (8 * i));
221: }
222: return SZ_OK;
223: }
224:
225: SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value)
226: {
227: int i;
228: *value = 0;
229: for (i = 0; i < 8; i++)
230: {
231: Byte b;
232: RINOK(SafeReadDirectByte(inStream, &b));
233: *value |= ((UInt32)b << (8 * i));
234: }
235: return SZ_OK;
236: }
237:
238: int TestSignatureCandidate(Byte *testBytes)
239: {
240: size_t i;
241: for (i = 0; i < k7zSignatureSize; i++)
242: if (testBytes[i] != k7zSignature[i])
243: return 0;
244: return 1;
245: }
246:
247: typedef struct _CSzState
248: {
249: Byte *Data;
250: size_t Size;
251: }CSzData;
252:
253: SZ_RESULT SzReadByte(CSzData *sd, Byte *b)
254: {
255: if (sd->Size == 0)
256: return SZE_ARCHIVE_ERROR;
257: sd->Size--;
258: *b = *sd->Data++;
259: return SZ_OK;
260: }
261:
262: SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size)
263: {
264: size_t i;
265: for (i = 0; i < size; i++)
266: {
267: RINOK(SzReadByte(sd, data + i));
268: }
269: return SZ_OK;
270: }
271:
272: SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value)
273: {
274: int i;
275: *value = 0;
276: for (i = 0; i < 4; i++)
277: {
278: Byte b;
279: RINOK(SzReadByte(sd, &b));
280: *value |= ((UInt32)(b) << (8 * i));
281: }
282: return SZ_OK;
283: }
284:
285: SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value)
286: {
287: Byte firstByte;
288: Byte mask = 0x80;
289: int i;
290: RINOK(SzReadByte(sd, &firstByte));
291: *value = 0;
292: for (i = 0; i < 8; i++)
293: {
294: Byte b;
295: if ((firstByte & mask) == 0)
296: {
297: UInt64 highPart = firstByte & (mask - 1);
298: *value += (highPart << (8 * i));
299: return SZ_OK;
300: }
301: RINOK(SzReadByte(sd, &b));
302: *value |= ((UInt64)b << (8 * i));
303: mask >>= 1;
304: }
305: return SZ_OK;
306: }
307:
308: SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value)
309: {
310: UInt64 value64;
311: RINOK(SzReadNumber(sd, &value64));
312: *value = (CFileSize)value64;
313: return SZ_OK;
314: }
315:
316: SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value)
317: {
318: UInt64 value64;
319: RINOK(SzReadNumber(sd, &value64));
320: if (value64 >= 0x80000000)
321: return SZE_NOTIMPL;
322: if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2)))
323: return SZE_NOTIMPL;
324: *value = (UInt32)value64;
325: return SZ_OK;
326: }
327:
328: SZ_RESULT SzReadID(CSzData *sd, UInt64 *value)
329: {
330: return SzReadNumber(sd, value);
331: }
332:
333: SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size)
334: {
335: if (size > sd->Size)
336: return SZE_ARCHIVE_ERROR;
337: sd->Size -= (size_t)size;
338: sd->Data += (size_t)size;
339: return SZ_OK;
340: }
341:
342: SZ_RESULT SzSkeepData(CSzData *sd)
343: {
344: UInt64 size;
345: RINOK(SzReadNumber(sd, &size));
346: return SzSkeepDataSize(sd, size);
347: }
348:
349: SZ_RESULT SzReadArchiveProperties(CSzData *sd)
350: {
351: while(1)
352: {
353: UInt64 type;
354: RINOK(SzReadID(sd, &type));
355: if (type == k7zIdEnd)
356: break;
357: SzSkeepData(sd);
358: }
359: return SZ_OK;
360: }
361:
362: SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute)
363: {
364: while(1)
365: {
366: UInt64 type;
367: RINOK(SzReadID(sd, &type));
368: if (type == attribute)
369: return SZ_OK;
370: if (type == k7zIdEnd)
371: return SZE_ARCHIVE_ERROR;
372: RINOK(SzSkeepData(sd));
373: }
374: }
375:
376: SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, int **v, void * (*allocFunc)(size_t size))
377: {
378: Byte b = 0;
379: Byte mask = 0;
380: size_t i;
381: *v = (int *)allocFunc(numItems * sizeof(int));
382: RINOM(*v);
383: for(i = 0; i < numItems; i++)
384: {
385: if (mask == 0)
386: {
387: RINOK(SzReadByte(sd, &b));
388: mask = 0x80;
389: }
390: (*v)[i] = ((b & mask) != 0);
391: mask >>= 1;
392: }
393: return SZ_OK;
394: }
395:
396: SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, int **v, void * (*allocFunc)(size_t size))
397: {
398: Byte allAreDefined;
399: size_t i;
400: RINOK(SzReadByte(sd, &allAreDefined));
401: if (allAreDefined == 0)
402: return SzReadBoolVector(sd, numItems, v, allocFunc);
403: *v = (int *)allocFunc(numItems * sizeof(int));
404: RINOM(*v);
405: for(i = 0; i < numItems; i++)
406: (*v)[i] = 1;
407: return SZ_OK;
408: }
409:
410: SZ_RESULT SzReadHashDigests(
411: CSzData *sd,
412: size_t numItems,
413: int **digestsDefined,
414: UInt32 **digests,
415: void * (*allocFunc)(size_t size))
416: {
417: size_t i;
418: RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc));
419: *digests = (UInt32 *)allocFunc(numItems * sizeof(UInt32));
420: RINOM(*digests);
421: for(i = 0; i < numItems; i++)
422: if ((*digestsDefined)[i])
423: {
424: RINOK(SzReadUInt32(sd, (*digests) + i));
425: }
426: return SZ_OK;
427: }
428:
429: SZ_RESULT SzReadPackInfo(
430: CSzData *sd,
431: CFileSize *dataOffset,
432: UInt32 *numPackStreams,
433: CFileSize **packSizes,
434: int **packCRCsDefined,
435: UInt32 **packCRCs,
436: void * (*allocFunc)(size_t size))
437: {
438: UInt32 i;
439: RINOK(SzReadSize(sd, dataOffset));
440: RINOK(SzReadNumber32(sd, numPackStreams));
441:
442: RINOK(SzWaitAttribute(sd, k7zIdSize));
443: *packSizes = (CFileSize *)allocFunc((size_t)*numPackStreams * sizeof(CFileSize));
444: RINOM(*packSizes);
445:
446: for(i = 0; i < *numPackStreams; i++)
447: {
448: RINOK(SzReadSize(sd, (*packSizes) + i));
449: }
450:
451: while(1)
452: {
453: UInt64 type;
454: RINOK(SzReadID(sd, &type));
455: if (type == k7zIdEnd)
456: break;
457: if (type == k7zIdCRC)
458: {
459: RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc));
460: continue;
461: }
462: RINOK(SzSkeepData(sd));
463: }
464: if (*packCRCsDefined == 0)
465: {
466: *packCRCsDefined = (int *)allocFunc((size_t)*numPackStreams * sizeof(int));
467: RINOM(*packCRCsDefined);
468: *packCRCs = (UInt32 *)allocFunc((size_t)*numPackStreams * sizeof(UInt32));
469: RINOM(*packCRCs);
470: for(i = 0; i < *numPackStreams; i++)
471: {
472: (*packCRCsDefined)[i] = 0;
473: (*packCRCs)[i] = 0;
474: }
475: }
476: return SZ_OK;
477: }
478:
479: SZ_RESULT SzReadSwitch(CSzData *sd)
480: {
481: Byte external;
482: RINOK(SzReadByte(sd, &external));
483: return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR;
484: }
485:
486: SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size))
487: {
488: UInt32 numCoders;
489: UInt32 numBindPairs;
490: UInt32 numPackedStreams;
491: UInt32 i;
492: UInt32 numInStreams = 0;
493: UInt32 numOutStreams = 0;
494: RINOK(SzReadNumber32(sd, &numCoders));
495: folder->NumCoders = numCoders;
496:
497: folder->Coders = (CCoderInfo *)allocFunc((size_t)numCoders * sizeof(CCoderInfo));
498: RINOM(folder->Coders);
499: for (i = 0; i < numCoders; i++)
500: SzCoderInfoInit(folder->Coders + i);
501:
502: for (i = 0; i < numCoders; i++)
503: {
504: Byte mainByte;
505: CCoderInfo *coder = folder->Coders + i;
506: {
507: RINOK(SzReadByte(sd, &mainByte));
508: coder->MethodID.IDSize = (Byte)(mainByte & 0xF);
509: RINOK(SzReadBytes(sd, coder->MethodID.ID, coder->MethodID.IDSize));
510: if ((mainByte & 0x10) != 0)
511: {
512: RINOK(SzReadNumber32(sd, &coder->NumInStreams));
513: RINOK(SzReadNumber32(sd, &coder->NumOutStreams));
514: }
515: else
516: {
517: coder->NumInStreams = 1;
518: coder->NumOutStreams = 1;
519: }
520: if ((mainByte & 0x20) != 0)
521: {
522: UInt64 propertiesSize = 0;
523: RINOK(SzReadNumber(sd, &propertiesSize));
524: if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc))
525: return SZE_OUTOFMEMORY;
526: RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize));
527: }
528: }
529: while ((mainByte & 0x80) != 0)
530: {
531: RINOK(SzReadByte(sd, &mainByte));
532: RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));
533: if ((mainByte & 0x10) != 0)
534: {
535: UInt32 n;
536: RINOK(SzReadNumber32(sd, &n));
537: RINOK(SzReadNumber32(sd, &n));
538: }
539: if ((mainByte & 0x20) != 0)
540: {
541: UInt64 propertiesSize = 0;
542: RINOK(SzReadNumber(sd, &propertiesSize));
543: RINOK(SzSkeepDataSize(sd, propertiesSize));
544: }
545: }
546: numInStreams += (UInt32)coder->NumInStreams;
547: numOutStreams += (UInt32)coder->NumOutStreams;
548: }
549:
550: numBindPairs = numOutStreams - 1;
551: folder->NumBindPairs = numBindPairs;
552:
553: folder->BindPairs = (CBindPair *)allocFunc((size_t)numBindPairs * sizeof(CBindPair));
554: RINOM(folder->BindPairs);
555:
556: for (i = 0; i < numBindPairs; i++)
557: {
558: CBindPair *bindPair = folder->BindPairs + i;;
559: RINOK(SzReadNumber32(sd, &bindPair->InIndex));
560: RINOK(SzReadNumber32(sd, &bindPair->OutIndex));
561: }
562:
563: numPackedStreams = numInStreams - (UInt32)numBindPairs;
564:
565: folder->NumPackStreams = numPackedStreams;
566: folder->PackStreams = (UInt32 *)allocFunc((size_t)numPackedStreams * sizeof(UInt32));
567: RINOM(folder->PackStreams);
568:
569: if (numPackedStreams == 1)
570: {
571: UInt32 j;
572: UInt32 pi = 0;
573: for (j = 0; j < numInStreams; j++)
574: if (SzFolderFindBindPairForInStream(folder, j) < 0)
575: {
576: folder->PackStreams[pi++] = j;
577: break;
578: }
579: }
580: else
581: for(i = 0; i < numPackedStreams; i++)
582: {
583: RINOK(SzReadNumber32(sd, folder->PackStreams + i));
584: }
585: return SZ_OK;
586: }
587:
588: SZ_RESULT SzReadUnPackInfo(
589: CSzData *sd,
590: UInt32 *numFolders,
591: CFolder **folders,
592: void * (*allocFunc)(size_t size),
593: ISzAlloc *allocTemp)
594: {
595: UInt32 i;
596: RINOK(SzWaitAttribute(sd, k7zIdFolder));
597: RINOK(SzReadNumber32(sd, numFolders));
598: {
599: RINOK(SzReadSwitch(sd));
600:
601: *folders = (CFolder *)allocFunc((size_t)*numFolders * sizeof(CFolder));
602: RINOM(*folders);
603: for(i = 0; i < *numFolders; i++)
604: SzFolderInit((*folders) + i);
605:
606: for(i = 0; i < *numFolders; i++)
607: {
608: RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc));
609: }
610: }
611:
612: RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize));
613:
614: for(i = 0; i < *numFolders; i++)
615: {
616: UInt32 j;
617: CFolder *folder = (*folders) + i;
618: UInt32 numOutStreams = SzFolderGetNumOutStreams(folder);
619:
620: folder->UnPackSizes = (CFileSize *)allocFunc((size_t)numOutStreams * sizeof(CFileSize));
621: RINOM(folder->UnPackSizes);
622:
623: for(j = 0; j < numOutStreams; j++)
624: {
625: RINOK(SzReadSize(sd, folder->UnPackSizes + j));
626: }
627: }
628:
629: while(1)
630: {
631: UInt64 type;
632: RINOK(SzReadID(sd, &type));
633: if (type == k7zIdEnd)
634: return SZ_OK;
635: if (type == k7zIdCRC)
636: {
637: SZ_RESULT res;
638: int *crcsDefined = 0;
639: UInt32 *crcs = 0;
640: res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc);
641: if (res == SZ_OK)
642: {
643: for(i = 0; i < *numFolders; i++)
644: {
645: CFolder *folder = (*folders) + i;
646: folder->UnPackCRCDefined = crcsDefined[i];
647: folder->UnPackCRC = crcs[i];
648: }
649: }
650: allocTemp->Free(crcs);
651: allocTemp->Free(crcsDefined);
652: RINOK(res);
653: continue;
654: }
655: RINOK(SzSkeepData(sd));
656: }
657: }
658:
659: SZ_RESULT SzReadSubStreamsInfo(
660: CSzData *sd,
661: UInt32 numFolders,
662: CFolder *folders,
663: UInt32 *numUnPackStreams,
664: CFileSize **unPackSizes,
665: int **digestsDefined,
666: UInt32 **digests,
667: void * (*allocFunc)(size_t size),
668: ISzAlloc *allocTemp)
669: {
670: UInt64 type = 0;
671: UInt32 i;
672: UInt32 si = 0;
673: UInt32 numDigests = 0;
674:
675: for(i = 0; i < numFolders; i++)
676: folders[i].NumUnPackStreams = 1;
677: *numUnPackStreams = numFolders;
678:
679: while(1)
680: {
681: RINOK(SzReadID(sd, &type));
682: if (type == k7zIdNumUnPackStream)
683: {
684: *numUnPackStreams = 0;
685: for(i = 0; i < numFolders; i++)
686: {
687: UInt32 numStreams;
688: RINOK(SzReadNumber32(sd, &numStreams));
689: folders[i].NumUnPackStreams = numStreams;
690: *numUnPackStreams += numStreams;
691: }
692: continue;
693: }
694: if (type == k7zIdCRC || type == k7zIdSize)
695: break;
696: if (type == k7zIdEnd)
697: break;
698: RINOK(SzSkeepData(sd));
699: }
700:
701: *unPackSizes = (CFileSize *)allocFunc((size_t)*numUnPackStreams * sizeof(CFileSize));
702: RINOM(*unPackSizes);
703:
704: *digestsDefined = (int *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(int));
705: RINOM(*digestsDefined);
706:
707: *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32));
708: RINOM(*digests);
709:
710: for(i = 0; i < numFolders; i++)
711: {
712: /*
713: v3.13 incorrectly worked with empty folders
714: v4.07: we check that folder is empty
715: */
716: CFileSize sum = 0;
717: UInt32 j;
718: UInt32 numSubstreams = folders[i].NumUnPackStreams;
719: if (numSubstreams == 0)
720: continue;
721: if (type == k7zIdSize)
722: for (j = 1; j < numSubstreams; j++)
723: {
724: CFileSize size;
725: RINOK(SzReadSize(sd, &size));
726: (*unPackSizes)[si++] = size;
727: sum += size;
728: }
729: (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum;
730: }
731: if (type == k7zIdSize)
732: {
733: RINOK(SzReadID(sd, &type));
734: }
735:
736: for(i = 0; i < *numUnPackStreams; i++)
737: {
738: (*digestsDefined)[i] = 0;
739: (*digests)[i] = 0;
740: }
741:
742:
743: for(i = 0; i < numFolders; i++)
744: {
745: UInt32 numSubstreams = folders[i].NumUnPackStreams;
746: if (numSubstreams != 1 || !folders[i].UnPackCRCDefined)
747: numDigests += numSubstreams;
748: }
749:
750:
751: si = 0;
752: while(1)
753: {
754: if (type == k7zIdCRC)
755: {
756: int digestIndex = 0;
757: int *digestsDefined2 = 0;
758: UInt32 *digests2 = 0;
759: SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc);
760: if (res == SZ_OK)
761: {
762: for (i = 0; i < numFolders; i++)
763: {
764: CFolder *folder = folders + i;
765: UInt32 numSubstreams = folder->NumUnPackStreams;
766: if (numSubstreams == 1 && folder->UnPackCRCDefined)
767: {
768: (*digestsDefined)[si] = 1;
769: (*digests)[si] = folder->UnPackCRC;
770: si++;
771: }
772: else
773: {
774: UInt32 j;
775: for (j = 0; j < numSubstreams; j++, digestIndex++)
776: {
777: (*digestsDefined)[si] = digestsDefined2[digestIndex];
778: (*digests)[si] = digests2[digestIndex];
779: si++;
780: }
781: }
782: }
783: }
784: allocTemp->Free(digestsDefined2);
785: allocTemp->Free(digests2);
786: RINOK(res);
787: }
788: else if (type == k7zIdEnd)
789: return SZ_OK;
790: else
791: {
792: RINOK(SzSkeepData(sd));
793: }
794: RINOK(SzReadID(sd, &type));
795: }
796: }
797:
798:
799: SZ_RESULT SzReadStreamsInfo(
800: CSzData *sd,
801: CFileSize *dataOffset,
802: CArchiveDatabase *db,
803: UInt32 *numUnPackStreams,
804: CFileSize **unPackSizes,
805: int **digestsDefined,
806: UInt32 **digests,
807: void * (*allocFunc)(size_t size),
808: ISzAlloc *allocTemp)
809: {
810: while(1)
811: {
812: UInt64 type;
813: RINOK(SzReadID(sd, &type));
814: switch(type)
815: {
816: case k7zIdEnd:
817: return SZ_OK;
818: case k7zIdPackInfo:
819: {
820: RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams,
821: &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc));
822: break;
823: }
824: case k7zIdUnPackInfo:
825: {
826: RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp));
827: break;
828: }
829: case k7zIdSubStreamsInfo:
830: {
831: RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders,
832: numUnPackStreams, unPackSizes, digestsDefined, digests, allocFunc, allocTemp));
833: break;
834: }
835: default:
836: return SZE_FAIL;
837: }
838: }
839: }
840:
841: Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
842:
843: SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files,
844: void * (*allocFunc)(size_t size))
845: {
846: UInt32 i;
847: for(i = 0; i < numFiles; i++)
848: {
849: UInt32 len = 0;
850: UInt32 pos = 0;
851: CFileItem *file = files + i;
852: while(pos + 2 <= sd->Size)
853: {
854: int numAdds;
855: UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
856: pos += 2;
857: len++;
858: if (value == 0)
859: break;
860: if (value < 0x80)
861: continue;
862: if (value >= 0xD800 && value < 0xE000)
863: {
864: UInt32 c2;
865: if (value >= 0xDC00)
866: return SZE_ARCHIVE_ERROR;
867: if (pos + 2 > sd->Size)
868: return SZE_ARCHIVE_ERROR;
869: c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
870: pos += 2;
871: if (c2 < 0xDC00 || c2 >= 0xE000)
872: return SZE_ARCHIVE_ERROR;
873: value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
874: }
875: for (numAdds = 1; numAdds < 5; numAdds++)
876: if (value < (((UInt32)1) << (numAdds * 5 + 6)))
877: break;
878: len += numAdds;
879: }
880:
881: file->Name = (char *)allocFunc((size_t)len * sizeof(char));
882: RINOM(file->Name);
883:
884: len = 0;
885: while(2 <= sd->Size)
886: {
887: int numAdds;
888: UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
889: SzSkeepDataSize(sd, 2);
890: if (value < 0x80)
891: {
892: file->Name[len++] = (char)value;
893: if (value == 0)
894: break;
895: continue;
896: }
897: if (value >= 0xD800 && value < 0xE000)
898: {
899: UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
900: SzSkeepDataSize(sd, 2);
901: value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
902: }
903: for (numAdds = 1; numAdds < 5; numAdds++)
904: if (value < (((UInt32)1) << (numAdds * 5 + 6)))
905: break;
906: file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
907: do
908: {
909: numAdds--;
910: file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
911: }
912: while(numAdds > 0);
913:
914: len += numAdds;
915: }
916: }
917: return SZ_OK;
918: }
919:
920: SZ_RESULT SzReadHeader2(
921: CSzData *sd,
922: CArchiveDatabaseEx *db,
923: CFileSize **unPackSizes,
924: int **digestsDefined,
925: UInt32 **digests,
926: ISzAlloc *allocMain,
927: ISzAlloc *allocTemp)
928: {
929: UInt64 type;
930: UInt32 numUnPackStreams = 0;
931: UInt32 numFiles = 0;
932: CFileItem *files = 0;
933: UInt32 i;
934:
935: RINOK(SzReadID(sd, &type));
936:
937: if (type == k7zIdArchiveProperties)
938: {
939: RINOK(SzReadArchiveProperties(sd));
940: RINOK(SzReadID(sd, &type));
941: }
942:
943:
944: if (type == k7zIdMainStreamsInfo)
945: {
946: RINOK(SzReadStreamsInfo(sd,
947: &db->ArchiveInfo.DataStartPosition,
948: &db->Database,
949: &numUnPackStreams,
950: unPackSizes,
951: digestsDefined,
952: digests, allocMain->Alloc, allocTemp));
953: db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader;
954: RINOK(SzReadID(sd, &type));
955: }
956: else
957: {
958: return SZE_NOTIMPL;
959: }
960:
961: if (type == k7zIdEnd)
962: return SZ_OK;
963: if (type != k7zIdFilesInfo)
964: return SZE_ARCHIVE_ERROR;
965:
966: RINOK(SzReadNumber32(sd, &numFiles));
967: db->Database.NumFiles = numFiles;
968:
969: files = (CFileItem *)allocTemp->Alloc((size_t)numFiles * sizeof(CFileItem));
970: RINOM(files);
971: db->Database.Files = files;
972: for(i = 0; i < numFiles; i++)
973: SzFileInit(files + i);
974:
975: /*
976: CBoolVector emptyStreamVector;
977: emptyStreamVector.Reserve((size_t)numFiles);
978: for(i = 0; i < numFiles; i++)
979: emptyStreamVector.Add(false);
980: CBoolVector emptyFileVector;
981: UInt32 numEmptyStreams = 0;
982: */
983:
984: while(1)
985: {
986: UInt64 type;
987: UInt64 size;
988: RINOK(SzReadID(sd, &type));
989: if (type == k7zIdEnd)
990: break;
991: RINOK(SzReadNumber(sd, &size));
992:
993: switch(type)
994: {
995: case k7zIdName:
996: {
997: RINOK(SzReadSwitch(sd));
998: RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc))
999: break;
1000: }
1001: case k7zIdEmptyStream:
1002: {
1003: /*
1004: RINOK(ReadBoolVector((UInt32)numFiles, emptyStreamVector))
1005: UInt32 i;
1006: for (i = 0; i < (UInt32)emptyStreamVector.Size(); i++)
1007: if (emptyStreamVector[i])
1008: numEmptyStreams++;
1009: emptyFileVector.Reserve(numEmptyStreams);
1010: antiFileVector.Reserve(numEmptyStreams);
1011: for (i = 0; i < numEmptyStreams; i++)
1012: {
1013: emptyFileVector.Add(false);
1014: antiFileVector.Add(false);
1015: }
1016: break;
1017: */
1018: return SZE_NOTIMPL;
1019: }
1020: case k7zIdEmptyFile:
1021: {
1022: /*
1023: RINOK(ReadBoolVector(numEmptyStreams, emptyFileVector))
1024: break;
1025: */
1026: return SZE_NOTIMPL;
1027: }
1028: default:
1029: {
1030: RINOK(SzSkeepDataSize(sd, size));
1031: }
1032: }
1033: }
1034:
1035: /*
1036: UInt32 emptyFileIndex = 0;
1037: UInt32 sizeIndex = 0;
1038: for(i = 0; i < numFiles; i++)
1039: {
1040: CFileItem *file = files + i;
1041: file.HasStream = !emptyStreamVector[(UInt32)i];
1042: if(file.HasStream)
1043: {
1044: file.IsDirectory = false;
1045: file.IsAnti = false;
1046: file.UnPackSize = unPackSizes[sizeIndex];
1047: file.FileCRC = digests[sizeIndex];
1048: file.IsFileCRCDefined = digestsDefined[sizeIndex];
1049: sizeIndex++;
1050: }
1051: else
1052: {
1053: file.IsDirectory = !emptyFileVector[emptyFileIndex];
1054: file.IsAnti = antiFileVector[emptyFileIndex];
1055: emptyFileIndex++;
1056: file.UnPackSize = 0;
1057: file.IsFileCRCDefined = false;
1058: }
1059: }
1060: */
1061: for(i = 0; i < numFiles; i++)
1062: {
1063: CFileItem *file = files + i;
1064: file->Size = (*unPackSizes)[i];
1065: file->FileCRC = (*digests)[i];
1066: file->IsFileCRCDefined = (Byte)(*digestsDefined)[i];
1067: }
1068: return SzArDbExFill(db, allocMain->Alloc);
1069: }
1070:
1071: SZ_RESULT SzReadHeader(
1072: CSzData *sd,
1073: CArchiveDatabaseEx *db,
1074: ISzAlloc *allocMain,
1075: ISzAlloc *allocTemp)
1076: {
1077: CFileSize *unPackSizes = 0;
1078: int *digestsDefined = 0;
1079: UInt32 *digests = 0;
1080: SZ_RESULT res = SzReadHeader2(sd, db,
1081: &unPackSizes, &digestsDefined, &digests,
1082: allocMain, allocTemp);
1083: allocTemp->Free(unPackSizes);
1084: allocTemp->Free(digestsDefined);
1085: allocTemp->Free(digests);
1086: return res;
1087: }
1088:
1089: SZ_RESULT SzReadAndDecodePackedStreams2(
1090: ISzInStream *inStream,
1091: CSzData *sd,
1092: CSzByteBuffer *outBuffer,
1093: CFileSize baseOffset,
1094: CArchiveDatabase *db,
1095: CFileSize **unPackSizes,
1096: int **digestsDefined,
1097: UInt32 **digests,
1098: #ifndef _LZMA_IN_CB
1099: Byte **inBuffer,
1100: #endif
1101: ISzAlloc *allocTemp)
1102: {
1103:
1104: UInt32 numUnPackStreams = 0;
1105: CFileSize dataStartPos;
1106: CFolder *folder;
1107: #ifndef _LZMA_IN_CB
1108: CFileSize packSize = 0;
1109: UInt32 i = 0;
1110: #endif
1111: CFileSize unPackSize;
1112: size_t outRealSize;
1113: SZ_RESULT res;
1114:
1115: RINOK(SzReadStreamsInfo(sd, &dataStartPos, db,
1116: &numUnPackStreams, unPackSizes, digestsDefined, digests,
1117: allocTemp->Alloc, allocTemp));
1118:
1119: dataStartPos += baseOffset;
1120: if (db->NumFolders != 1)
1121: return SZE_ARCHIVE_ERROR;
1122:
1123: folder = db->Folders;
1124: unPackSize = SzFolderGetUnPackSize(folder);
1125:
1126: RINOK(inStream->Seek(inStream, dataStartPos));
1127:
1128: #ifndef _LZMA_IN_CB
1129: for (i = 0; i < db->NumPackStreams; i++)
1130: packSize += db->PackSizes[i];
1131:
1132: *inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize);
1133: RINOM(*inBuffer);
1134:
1135: RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize));
1136: #endif
1137:
1138: if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc))
1139: return SZE_OUTOFMEMORY;
1140:
1141: res = SzDecode(db->PackSizes, folder,
1142: #ifdef _LZMA_IN_CB
1143: inStream,
1144: #else
1145: *inBuffer,
1146: #endif
1147: outBuffer->Items, (size_t)unPackSize,
1148: &outRealSize, allocTemp);
1149: RINOK(res)
1150: if (outRealSize != (UInt32)unPackSize)
1151: return SZE_FAIL;
1152: if (folder->UnPackCRCDefined)
1153: if (!CrcVerifyDigest(folder->UnPackCRC, outBuffer->Items, (size_t)unPackSize))
1154: return SZE_FAIL;
1155: return SZ_OK;
1156: }
1157:
1158: SZ_RESULT SzReadAndDecodePackedStreams(
1159: ISzInStream *inStream,
1160: CSzData *sd,
1161: CSzByteBuffer *outBuffer,
1162: CFileSize baseOffset,
1163: ISzAlloc *allocTemp)
1164: {
1165: CArchiveDatabase db;
1166: CFileSize *unPackSizes = 0;
1167: int *digestsDefined = 0;
1168: UInt32 *digests = 0;
1169: #ifndef _LZMA_IN_CB
1170: Byte *inBuffer = 0;
1171: #endif
1172: SZ_RESULT res;
1173: SzArchiveDatabaseInit(&db);
1174: res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset,
1175: &db, &unPackSizes, &digestsDefined, &digests,
1176: #ifndef _LZMA_IN_CB
1177: &inBuffer,
1178: #endif
1179: allocTemp);
1180: SzArchiveDatabaseFree(&db, allocTemp->Free);
1181: allocTemp->Free(unPackSizes);
1182: allocTemp->Free(digestsDefined);
1183: allocTemp->Free(digests);
1184: #ifndef _LZMA_IN_CB
1185: allocTemp->Free(inBuffer);
1186: #endif
1187: return res;
1188: }
1189:
1190: SZ_RESULT SzArchiveOpen2(
1191: ISzInStream *inStream,
1192: CArchiveDatabaseEx *db,
1193: ISzAlloc *allocMain,
1194: ISzAlloc *allocTemp)
1195: {
1196: Byte signature[k7zSignatureSize];
1197: Byte version;
1198: UInt32 crcFromArchive;
1199: UInt64 nextHeaderOffset;
1200: UInt64 nextHeaderSize;
1201: UInt32 nextHeaderCRC;
1202: UInt32 crc;
1203: CFileSize pos = 0;
1204: CSzByteBuffer buffer;
1205: CSzData sd;
1206: SZ_RESULT res;
1207:
1208: RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize));
1209:
1210: if (!TestSignatureCandidate(signature))
1211: return SZE_ARCHIVE_ERROR;
1212:
1213: /*
1214: db.Clear();
1215: db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;
1216: */
1217: RINOK(SafeReadDirectByte(inStream, &version));
1218: if (version != k7zMajorVersion)
1219: return SZE_ARCHIVE_ERROR;
1220: RINOK(SafeReadDirectByte(inStream, &version));
1221:
1222: RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive));
1223:
1224: CrcInit(&crc);
1225: RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset));
1226: CrcUpdateUInt64(&crc, nextHeaderOffset);
1227: RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize));
1228: CrcUpdateUInt64(&crc, nextHeaderSize);
1229: RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC));
1230: CrcUpdateUInt32(&crc, nextHeaderCRC);
1231:
1232: pos = k7zStartHeaderSize;
1233: db->ArchiveInfo.StartPositionAfterHeader = pos;
1234:
1235: if (CrcGetDigest(&crc) != crcFromArchive)
1236: return SZE_ARCHIVE_ERROR;
1237:
1238: if (nextHeaderSize == 0)
1239: return SZ_OK;
1240:
1241: RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset)));
1242:
1243: if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc))
1244: return SZE_OUTOFMEMORY;
1245:
1246: res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize);
1247: if (res == SZ_OK)
1248: {
1249: if (CrcVerifyDigest(nextHeaderCRC, buffer.Items, (UInt32)nextHeaderSize))
1250: {
1251: while (1)
1252: {
1253: UInt64 type;
1254: sd.Data = buffer.Items;
1255: sd.Size = buffer.Capacity;
1256: res = SzReadID(&sd, &type);
1257: if (res != SZ_OK)
1258: break;
1259: if (type == k7zIdHeader)
1260: {
1261: res = SzReadHeader(&sd, db, allocMain, allocTemp);
1262: break;
1263: }
1264: if (type != k7zIdEncodedHeader)
1265: {
1266: res = SZE_ARCHIVE_ERROR;
1267: break;
1268: }
1269: {
1270: CSzByteBuffer outBuffer;
1271: res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer,
1272: db->ArchiveInfo.StartPositionAfterHeader,
1273: allocTemp);
1274: if (res != SZ_OK)
1275: {
1276: SzByteBufferFree(&outBuffer, allocTemp->Free);
1277: break;
1278: }
1279: SzByteBufferFree(&buffer, allocTemp->Free);
1280: buffer.Items = outBuffer.Items;
1281: buffer.Capacity = outBuffer.Capacity;
1282: }
1283: }
1284: }
1285: }
1286: SzByteBufferFree(&buffer, allocTemp->Free);
1287: return res;
1288: }
1289:
1290: SZ_RESULT SzArchiveOpen(
1291: ISzInStream *inStream,
1292: CArchiveDatabaseEx *db,
1293: ISzAlloc *allocMain,
1294: ISzAlloc *allocTemp)
1295: {
1296: SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp);
1297: if (res != SZ_OK)
1298: SzArDbExFree(db, allocMain->Free);
1299: return res;
1300: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>