7zExtract.c 3.0 KB

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