Annotation of elwix/tools/oldlzma/SRC/7zip/Archive/7z_C/7zIn.c, revision 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>