Beispiel #1
0
SZ_RESULT SzExtract(
    ISzInStream *inStream, 
    CArchiveDatabaseEx *db,
    UInt32 fileIndex,
    UInt32 *blockIndex,
    Byte **outBuffer, 
    size_t *outBufferSize,
    size_t *offset, 
    size_t *outSizeProcessed, 
    ISzAlloc *allocMain,
    ISzAlloc *allocTemp)
{
  UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex];
  SZ_RESULT res = SZ_OK;
  *offset = 0;
  *outSizeProcessed = 0;
  if (folderIndex == (UInt32)-1)
  {
    allocMain->Free(*outBuffer);
    *blockIndex = folderIndex;
    *outBuffer = 0;
    *outBufferSize = 0;
    return SZ_OK;
  }

  if (*outBuffer == 0 || *blockIndex != folderIndex)
  {
    CFolder *folder = db->Database.Folders + folderIndex;
    CFileSize unPackSize = SzFolderGetUnPackSize(folder);
    #ifndef _LZMA_IN_CB
    CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex);
    Byte *inBuffer = 0;
    size_t processedSize;
    #endif
    *blockIndex = folderIndex;
    allocMain->Free(*outBuffer);
    *outBuffer = 0;
    
    RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0)));
    
    #ifndef _LZMA_IN_CB
    inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize);
    if (inBuffer == 0)
      return SZE_OUTOFMEMORY;
    res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize);
    if (res == SZ_OK && processedSize != (size_t)packSize)
      res = SZE_FAIL;
    #endif
    if (res == SZ_OK)
    {
      *outBuffer = (Byte *)allocMain->Alloc((size_t)unPackSize);
      *outBufferSize = (size_t)unPackSize;
      if (*outBuffer != 0)
      {
        size_t outRealSize;
        res = SzDecode(db->Database.PackSizes + 
          db->FolderStartPackStreamIndex[folderIndex], folder, 
          #ifdef _LZMA_IN_CB
          inStream,
          #else
          inBuffer, 
          #endif
          *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp);
        if (res == SZ_OK)
        {
          if (outRealSize == (size_t)unPackSize)
          {
            if (folder->UnPackCRCDefined)
            {
              if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize))
                res = SZE_FAIL;
            }
          }
          else
            res = SZE_FAIL;
        }
      }
      else
        res = SZE_OUTOFMEMORY;
    }
    #ifndef _LZMA_IN_CB
    allocTemp->Free(inBuffer);
    #endif
  }
  if (res == SZ_OK)
  {
    UInt32 i; 
    CFileItem *fileItem = db->Database.Files + fileIndex;
    *offset = 0;
    for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
      *offset += (UInt32)db->Database.Files[i].Size;
    *outSizeProcessed = (size_t)fileItem->Size;
    if (*offset + *outSizeProcessed > *outBufferSize)
      return SZE_FAIL;
    {
      if (fileItem->IsFileCRCDefined)
      {
        if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer + *offset, *outSizeProcessed))
          res = SZE_FAIL;
      }
    }
  }
  return res;
}
Beispiel #2
0
// similar to SzExtract but needs less memory
SZ_RESULT SzExtract2(
    ISzInStream *inStream,
    CArchiveDatabaseEx *db,
    UInt32 fileIndex,
    UInt32 *blockIndex,
    Byte **outBuffer,
    size_t *outBufferSize,
    size_t *offset,
    size_t *outSizeProcessed,
    ISzAlloc *allocMain,
    ISzAlloc *allocTemp)
{
  UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex];
  SZ_RESULT res = SZ_OK;
  *offset = 0;
  *outSizeProcessed = 0;
  if (folderIndex == (UInt32)-1)
  {
    *blockIndex = folderIndex;
    #ifndef NGC
    allocMain->Free(*outBuffer);
    *outBuffer = 0;
    #endif
    *outBufferSize = 0;
    return SZ_OK;
  }

//  if (*outBuffer == 0 || *blockIndex != folderIndex)
//  {
    CFolder *folder = db->Database.Folders + folderIndex;
    CFileSize unPackSize = SzFolderGetUnPackSize(folder);
    #ifndef _LZMA_IN_CB
    CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex);
    Byte *inBuffer = 0;
    size_t processedSize;
    #endif
    *blockIndex = folderIndex;
    #ifndef NGC
    allocMain->Free(*outBuffer);
    *outBuffer = 0;
    #endif

    RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0)));

    #ifndef _LZMA_IN_CB
    if (packSize != 0)
    {
      inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize);
      if (inBuffer == 0)
        return SZE_OUTOFMEMORY;
    }
    res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize);
    if (res == SZ_OK && processedSize != (size_t)packSize)
      res = SZE_FAIL;
    #endif
    if (res == SZ_OK)
    {
	  // calculate file offset and filesize
      CFileItem *fileItem = db->Database.Files + fileIndex;
	  UInt32 i;
	  *offset = 0;
	  for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
		*offset += (UInt32)db->Database.Files[i].Size;
	  *outSizeProcessed = (size_t)fileItem->Size;
      *outBufferSize = (size_t)fileItem->Size;
      if (unPackSize != 0)
      {
		#ifndef NGC
        *outBuffer = (Byte *)allocMain->Alloc((size_t)fileItem->Size);
        if (*outBuffer == 0)
          res = SZE_OUTOFMEMORY;
        #endif
      }
      if (res == SZ_OK)
      {

        size_t outRealSize;
        res = SzDecode2(db->Database.PackSizes +
          db->FolderStartPackStreamIndex[folderIndex], folder,
          #ifdef _LZMA_IN_CB
          inStream,
          #else
          inBuffer,
          #endif
          *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp,
		  offset, outSizeProcessed
		  );
		  *outSizeProcessed = outRealSize;
/*        if (res == SZ_OK) // we can't validate the CRC of the whole data stream because we only extracted the wanted file
        {
          if (outRealSize == (size_t)unPackSize)
          {
            if (folder->UnPackCRCDefined)
            {
              if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize))
                res = SZE_FAIL;
            }
          }
          else
            res = SZE_FAIL;
        }*/
      }
//    }
    #ifndef _LZMA_IN_CB
    allocTemp->Free(inBuffer);
    #endif
  }
  if (res == SZ_OK)
  {
/*    UInt32 i;
    CFileItem *fileItem = db->Database.Files + fileIndex;
    *offset = 0;
    for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
      *offset += (UInt32)db->Database.Files[i].Size;
    *outSizeProcessed = (size_t)fileItem->Size;*/
    //CFileItem *fileItem = db->Database.Files + fileIndex;
    if (/**offset +*/ *outSizeProcessed > *outBufferSize)
      return SZE_FAIL;
    {
      //if (fileItem->IsFileCRCDefined)
      //{
       // if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer/* + *offset*/, *outSizeProcessed))
        //  res = SZE_CRC_ERROR; // why does SzExtract return SZE_FAIL when we can return SZE_CRC_ERROR?
      //}
    }
  }

  // change *offset to 0 because SzExtract normally decompresses the whole solid block
  // and sets *offset to the offset of the wanted file.
  // SzDecode2 does only copy the needed file to the output buffer and has to set *offset
  // to 0 to ensure compatibility with SzExtract
  *offset = 0;
  return res;
}