SRes SzArEx_Extract( const CSzArEx *p, ISeekInStream *inStream, const UInt16 *outputDir, ICompressProgress *progress, ISzAlloc *allocTemp) { UInt32 blockIndex = 0xffffffff; UInt64 totalUnpackSize = 0; UInt32 i; SRes res = SZ_OK; for (i = 0; i < p->db.NumFolders; i++) { CSzFolder *folder = p->db.Folders + i; UInt64 unpackSize = SzFolder_GetUnpackSize(folder); totalUnpackSize += unpackSize; } if(progress != NULL) CompressCallback_Init((CCompressCallback*)progress,totalUnpackSize); for (i = 0; i < p->db.NumFiles; i++) { UInt32 folderIndex = p->FileIndexToFolderIndexMap[i]; if (folderIndex == (UInt32)-1) { blockIndex = folderIndex; continue; } if(folderIndex != blockIndex) { CSzFolder *folder = p->db.Folders + folderIndex; UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); size_t unpackSize = (size_t)unpackSizeSpec; UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); CFolderOutStream outStream; FolderOutStream_Init(&outStream,p,folderIndex,outputDir); if (unpackSize != unpackSizeSpec) return SZ_ERROR_MEM; blockIndex = folderIndex; res = SzFolder_Decode(folder, p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], inStream, startOffset, &outStream.s, unpackSize, progress, allocTemp); File_Close(&outStream.file); if(res != SZ_OK) break; } } return res; }
static SRes SzReadAndDecodePackedStreams2( ISeekInStream *inStream, CSzData *sd, ISeqOutStream *outStream, UInt64 baseOffset, CSzAr *p, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { CMemOutStream* memStream; UInt32 numUnpackStreams = 0; UInt64 dataStartPos; CSzFolder *folder; UInt64 unpackSize; SRes res; Int64 offset; RINOK(SzReadStreamsInfo(sd, &dataStartPos, p, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp, allocTemp)); dataStartPos += baseOffset; if (p->NumFolders != 1) return SZ_ERROR_ARCHIVE; folder = p->Folders; unpackSize = SzFolder_GetUnpackSize(folder); offset = (Int64)dataStartPos; RINOK(inStream->Seek(inStream, &offset, SZ_SEEK_SET)); memStream = (CMemOutStream*)outStream; if (!Buf_Create((CBuf*)&memStream->data, (size_t)unpackSize, allocTemp)) return SZ_ERROR_MEM; res = SzFolder_Decode(folder, p->PackSizes, inStream, dataStartPos, outStream, (size_t)unpackSize, NULL, allocTemp); RINOK(res); if (folder->UnpackCRCDefined) if (CrcCalc(memStream->data, (size_t)unpackSize) != folder->UnpackCRC) return SZ_ERROR_CRC; return SZ_OK; }
static SRes SzReadAndDecodePackedStreams2( ILookInStream *inStream, CSzData *sd, CBuf *outBuffer, UInt64 baseOffset, CSzAr *p, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt32 numUnpackStreams = 0; UInt64 dataStartPos; CSzFolder *folder; UInt64 unpackSize; SRes res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, p, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp, allocTemp)); dataStartPos += baseOffset; if (p->NumFolders != 1) return SZ_ERROR_ARCHIVE; folder = p->Folders; unpackSize = SzFolder_GetUnpackSize(folder); RINOK(LookInStream_SeekTo(inStream, dataStartPos)); if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) return SZ_ERROR_MEM; res = SzFolder_Decode(folder, p->PackSizes, inStream, dataStartPos, outBuffer->data, (size_t)unpackSize, allocTemp); RINOK(res); #ifdef _7ZIP_CRC_SUPPORT if (folder->UnpackCRCDefined) if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC) return SZ_ERROR_CRC; #endif return SZ_OK; }
SRes SzArEx_Extract( const CSzArEx *p, ILookInStream *inStream, uint32_t fileIndex, uint32_t *blockIndex, uint8_t **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { uint32_t folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; SRes res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (uint32_t)-1) { IAlloc_Free(allocMain, *outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CSzFolder *folder = p->db.Folders + folderIndex; uint64_t unpackSizeSpec = SzFolder_GetUnpackSize(folder); size_t unpackSize = (size_t)unpackSizeSpec; uint64_t startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); if (unpackSize != unpackSizeSpec) return SZ_ERROR_MEM; *blockIndex = folderIndex; IAlloc_Free(allocMain, *outBuffer); *outBuffer = 0; RINOK(LookInStream_SeekTo(inStream, startOffset)); if (res == SZ_OK) { *outBufferSize = unpackSize; if (unpackSize != 0) { *outBuffer = (uint8_t *)IAlloc_Alloc(allocMain, unpackSize); if (*outBuffer == 0) res = SZ_ERROR_MEM; } if (res == SZ_OK) { res = SzFolder_Decode(folder, p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], inStream, startOffset, *outBuffer, unpackSize, allocTemp); if (res == SZ_OK) { if (folder->UnpackCRCDefined) { if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) res = SZ_ERROR_CRC; } } } } } if (res == SZ_OK) { uint32_t i; CSzFileItem *fileItem = p->db.Files + fileIndex; *offset = 0; for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (uint32_t)p->db.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZ_ERROR_FAIL; if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc) res = SZ_ERROR_CRC; } return res; }
SRes SzArEx_Extract( const CSzArEx *p, ILookInStream *inStream, UInt32 fileIndex, SzArEx_DictCache *dictCache, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; SRes res = SZ_OK; dictCache->entryOffset = 0; dictCache->outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { SzArEx_DictCache_free(dictCache); dictCache->blockIndex = folderIndex; return SZ_OK; } if (dictCache->outBuffer == 0 || dictCache->blockIndex != folderIndex) { CSzFolder *folder = p->db.Folders + folderIndex; UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); size_t unpackSize = (size_t)unpackSizeSpec; UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); if (unpackSize != unpackSizeSpec) return SZ_ERROR_MEM; SzArEx_DictCache_free(dictCache); dictCache->blockIndex = folderIndex; RINOK(LookInStream_SeekTo(inStream, startOffset)); if (res == SZ_OK) { dictCache->outBufferSize = unpackSize; if (unpackSize != 0) { if (dictCache->mapFilename && (unpackSize >= k7zUnpackMapDictionaryInMemoryMaxNumBytes)) { // map to disk is enabled and file is larger than 1 megabyte. // note that an error condition is checked by seeing if // dictCache->outBuffer after a map attempt SzArEx_DictCache_mmap(dictCache); } else { dictCache->outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); } if (dictCache->outBuffer == 0) res = SZ_ERROR_MEM; } if (res == SZ_OK) { res = SzFolder_Decode(folder, p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], inStream, startOffset, dictCache->outBuffer, unpackSize, allocTemp); if (res == SZ_OK) { if (folder->UnpackCRCDefined) { #ifdef _7ZIP_CRC_SUPPORT if (CrcCalc(dictCache->outBuffer, unpackSize) != folder->UnpackCRC) res = SZ_ERROR_CRC; #endif } } } } } if (res == SZ_OK) { UInt32 i; CSzFileItem *fileItem = p->db.Files + fileIndex; dictCache->entryOffset = 0; for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) dictCache->entryOffset += (UInt32)p->db.Files[i].Size; dictCache->outSizeProcessed = (size_t)fileItem->Size; if (dictCache->entryOffset + dictCache->outSizeProcessed > dictCache->outBufferSize) return SZ_ERROR_FAIL; #ifdef _7ZIP_CRC_SUPPORT if (fileItem->CrcDefined && CrcCalc(dictCache->outBuffer + dictCache->entryOffset, dictCache->outSizeProcessed) != fileItem->Crc) res = SZ_ERROR_CRC; #endif } return res; }