misc/libphysfs/lzma/C/Archive/7z/7zExtract.c
changeset 13881 99b265e0d1d0
parent 13880 5f819b90d479
child 13882 b172a5d40eee
equal deleted inserted replaced
13880:5f819b90d479 13881:99b265e0d1d0
     1 /* 7zExtract.c */
       
     2 
       
     3 #include "7zExtract.h"
       
     4 #include "7zDecode.h"
       
     5 #include "../../7zCrc.h"
       
     6 
       
     7 SZ_RESULT SzExtract(
       
     8     ISzInStream *inStream, 
       
     9     CArchiveDatabaseEx *db,
       
    10     UInt32 fileIndex,
       
    11     UInt32 *blockIndex,
       
    12     Byte **outBuffer, 
       
    13     size_t *outBufferSize,
       
    14     size_t *offset, 
       
    15     size_t *outSizeProcessed, 
       
    16     ISzAlloc *allocMain,
       
    17     ISzAlloc *allocTemp)
       
    18 {
       
    19   UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex];
       
    20   SZ_RESULT res = SZ_OK;
       
    21   *offset = 0;
       
    22   *outSizeProcessed = 0;
       
    23   if (folderIndex == (UInt32)-1)
       
    24   {
       
    25     allocMain->Free(*outBuffer);
       
    26     *blockIndex = folderIndex;
       
    27     *outBuffer = 0;
       
    28     *outBufferSize = 0;
       
    29     return SZ_OK;
       
    30   }
       
    31 
       
    32   if (*outBuffer == 0 || *blockIndex != folderIndex)
       
    33   {
       
    34     CFolder *folder = db->Database.Folders + folderIndex;
       
    35     CFileSize unPackSizeSpec = SzFolderGetUnPackSize(folder);
       
    36     size_t unPackSize = (size_t)unPackSizeSpec;
       
    37     CFileSize startOffset = SzArDbGetFolderStreamPos(db, folderIndex, 0);
       
    38     #ifndef _LZMA_IN_CB
       
    39     Byte *inBuffer = 0;
       
    40     size_t processedSize;
       
    41     CFileSize packSizeSpec;
       
    42     size_t packSize;
       
    43     RINOK(SzArDbGetFolderFullPackSize(db, folderIndex, &packSizeSpec));
       
    44     packSize = (size_t)packSizeSpec;
       
    45     if (packSize != packSizeSpec)
       
    46       return SZE_OUTOFMEMORY;
       
    47     #endif
       
    48     if (unPackSize != unPackSizeSpec)
       
    49       return SZE_OUTOFMEMORY;
       
    50     *blockIndex = folderIndex;
       
    51     allocMain->Free(*outBuffer);
       
    52     *outBuffer = 0;
       
    53     
       
    54     RINOK(inStream->Seek(inStream, startOffset));
       
    55     
       
    56     #ifndef _LZMA_IN_CB
       
    57     if (packSize != 0)
       
    58     {
       
    59       inBuffer = (Byte *)allocTemp->Alloc(packSize);
       
    60       if (inBuffer == 0)
       
    61         return SZE_OUTOFMEMORY;
       
    62     }
       
    63     res = inStream->Read(inStream, inBuffer, packSize, &processedSize);
       
    64     if (res == SZ_OK && processedSize != packSize)
       
    65       res = SZE_FAIL;
       
    66     #endif
       
    67     if (res == SZ_OK)
       
    68     {
       
    69       *outBufferSize = unPackSize;
       
    70       if (unPackSize != 0)
       
    71       {
       
    72         *outBuffer = (Byte *)allocMain->Alloc(unPackSize);
       
    73         if (*outBuffer == 0)
       
    74           res = SZE_OUTOFMEMORY;
       
    75       }
       
    76       if (res == SZ_OK)
       
    77       {
       
    78         res = SzDecode(db->Database.PackSizes + 
       
    79           db->FolderStartPackStreamIndex[folderIndex], folder, 
       
    80           #ifdef _LZMA_IN_CB
       
    81           inStream, startOffset, 
       
    82           #else
       
    83           inBuffer, 
       
    84           #endif
       
    85           *outBuffer, unPackSize, allocTemp);
       
    86         if (res == SZ_OK)
       
    87         {
       
    88           if (folder->UnPackCRCDefined)
       
    89           {
       
    90             if (CrcCalc(*outBuffer, unPackSize) != folder->UnPackCRC)
       
    91               res = SZE_CRC_ERROR;
       
    92           }
       
    93         }
       
    94       }
       
    95     }
       
    96     #ifndef _LZMA_IN_CB
       
    97     allocTemp->Free(inBuffer);
       
    98     #endif
       
    99   }
       
   100   if (res == SZ_OK)
       
   101   {
       
   102     UInt32 i; 
       
   103     CFileItem *fileItem = db->Database.Files + fileIndex;
       
   104     *offset = 0;
       
   105     for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
       
   106       *offset += (UInt32)db->Database.Files[i].Size;
       
   107     *outSizeProcessed = (size_t)fileItem->Size;
       
   108     if (*offset + *outSizeProcessed > *outBufferSize)
       
   109       return SZE_FAIL;
       
   110     {
       
   111       if (fileItem->IsFileCRCDefined)
       
   112       {
       
   113         if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
       
   114           res = SZE_CRC_ERROR;
       
   115       }
       
   116     }
       
   117   }
       
   118   return res;
       
   119 }