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>