HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, const CObjectVector<NArchive::NTar::CItemEx> &inputItems, const CObjectVector<CUpdateItem> &updateItems, IArchiveUpdateCallback *updateCallback) { COutArchive outArchive; outArchive.Create(outStream); UInt64 complexity = 0; int i; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) complexity += ui.Size; else complexity += inputItems[ui.IndexInArchive].GetFullSize(); } RINOK(updateCallback->SetTotal(complexity)); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); streamSpec->SetStream(inStream); complexity = 0; for (i = 0; i < updateItems.Size(); i++) { lps->InSize = lps->OutSize = complexity; RINOK(lps->SetCur()); const CUpdateItem &ui = updateItems[i]; CItem item; if (ui.NewProps) { item.Mode = ui.Mode; item.Name = ui.Name; item.User = ui.User; item.Group = ui.Group; if (ui.IsDir) { item.LinkFlag = NFileHeader::NLinkFlag::kDirectory; item.PackSize = 0; } else { item.LinkFlag = NFileHeader::NLinkFlag::kNormal; item.PackSize = ui.Size; } item.MTime = ui.MTime; item.DeviceMajorDefined = false; item.DeviceMinorDefined = false; item.UID = 0; item.GID = 0; memmove(item.Magic, NFileHeader::NMagic::kEmpty, 8); } else item = inputItems[ui.IndexInArchive]; if (ui.NewData) { item.PackSize = ui.Size; if (ui.Size == (UInt64)(Int64)-1) return E_INVALIDARG; } else item.PackSize = inputItems[ui.IndexInArchive].PackSize; if (ui.NewData) { CMyComPtr<ISequentialInStream> fileInStream; HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); if (res != S_FALSE) { RINOK(res); RINOK(outArchive.WriteHeader(item)); if (!ui.IsDir) { RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress)); if (copyCoderSpec->TotalSize != item.PackSize) return E_FAIL; RINOK(outArchive.FillDataResidual(item.PackSize)); } } complexity += ui.Size; RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); } else { const CItemEx &existItem = inputItems[ui.IndexInArchive]; UInt64 size; if (ui.NewProps) { RINOK(outArchive.WriteHeader(item)); RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL)); size = existItem.PackSize; } else { RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL)); size = existItem.GetFullSize(); } streamSpec->Init(size); RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); if (copyCoderSpec->TotalSize != size) return E_FAIL; RINOK(outArchive.FillDataResidual(existItem.PackSize)); complexity += size; } } lps->InSize = lps->OutSize = complexity; RINOK(lps->SetCur()); return outArchive.WriteFinishHeader(); }
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) { size_t processed = 1; RINOK(stream->Read(stream, buf, &processed)); return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; }
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) { Byte props[LZMA_PROPS_SIZE]; RINOK(Lzma2Dec_GetOldProps(prop, props)); return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); }
HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) { filled = false; UInt32 processedSize; Byte startHeader[2]; RINOK(ReadBytes(startHeader, 2, processedSize)) if (processedSize == 0) return S_OK; if (processedSize == 1) return (startHeader[0] == 0) ? S_OK: S_FALSE; if (startHeader[0] == 0 && startHeader[1] == 0) return S_OK; Byte header[256]; const UInt32 kBasicPartSize = 22; RINOK(ReadBytes(header, kBasicPartSize, processedSize)); if (processedSize != kBasicPartSize) return (startHeader[0] == 0) ? S_OK: S_FALSE; const Byte *p = header; memmove(item.Method, p, kMethodIdSize); if (!item.IsValidMethod()) return S_OK; p += kMethodIdSize; p = ReadUInt32(p, item.PackSize); p = ReadUInt32(p, item.Size); p = ReadUInt32(p, item.ModifiedTime); item.Attributes = *p++; item.Level = *p++; if (item.Level > 2) return S_FALSE; UInt32 headerSize; if (item.Level < 2) { headerSize = startHeader[0]; if (headerSize < kBasicPartSize) return S_FALSE; UInt32 remain = headerSize - kBasicPartSize; RINOK(CheckReadBytes(header + kBasicPartSize, remain)); if (startHeader[1] != CalcSum(header, headerSize)) return S_FALSE; size_t nameLength = *p++; if ((p - header) + nameLength + 2 > headerSize) return S_FALSE; p = ReadString(p, nameLength, item.Name); } else headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8); p = ReadUInt16(p, item.CRC); if (item.Level != 0) { if (item.Level == 2) { RINOK(CheckReadBytes(header + kBasicPartSize, 2)); } if ((size_t)(p - header) + 3 > headerSize) return S_FALSE; item.OsId = *p++; UInt16 nextSize; p = ReadUInt16(p, nextSize); while (nextSize != 0) { if (nextSize < 3) return S_FALSE; if (item.Level == 1) { if (item.PackSize < nextSize) return S_FALSE; item.PackSize -= nextSize; } CExtension ext; RINOK(CheckReadBytes(&ext.Type, 1)) nextSize -= 3; ext.Data.SetCapacity(nextSize); RINOK(CheckReadBytes((Byte *)ext.Data, nextSize)) item.Extensions.Add(ext); Byte hdr2[2]; RINOK(CheckReadBytes(hdr2, 2)); ReadUInt16(hdr2, nextSize); } } item.DataPosition = m_Position; filled = true; return S_OK; }
HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK) { passwOK = false; if (_remSize < 16) return E_NOTIMPL; Byte *p = _bufAligned; UInt16 format = GetUi16(p); if (format != 3) return E_NOTIMPL; UInt16 algId = GetUi16(p + 2); if (algId < kAES128) return E_NOTIMPL; algId -= kAES128; if (algId > 2) return E_NOTIMPL; UInt16 bitLen = GetUi16(p + 4); UInt16 flags = GetUi16(p + 6); if (algId * 64 + 128 != bitLen) return E_NOTIMPL; _key.KeySize = 16 + algId * 8; bool cert = ((flags & 2) != 0); if ((flags & 0x4000) != 0) { // Use 3DES return E_NOTIMPL; } if (cert) { return E_NOTIMPL; } else { if ((flags & 1) == 0) return E_NOTIMPL; } UInt32 rdSize = GetUi16(p + 8); if (rdSize + 16 > _remSize) return E_NOTIMPL; /* if (cert) { // how to filter rd, if ((rdSize & 0xF) != 0) ? /* if ((rdSize & 0x7) != 0) return E_NOTIMPL; } else */ { if ((rdSize & 0xF) != 0) return E_NOTIMPL; } memmove(p, p + 10, rdSize); const Byte *p2 = p + rdSize + 10; UInt32 reserved = GetUi32(p2); p2 += 4; /* if (cert) { UInt32 numRecipients = reserved; if (numRecipients == 0) return E_NOTIMPL; { UInt32 hashAlg = GetUi16(p2); hashAlg = hashAlg; UInt32 hashSize = GetUi16(p2 + 2); hashSize = hashSize; p2 += 4; reserved = reserved; // return E_NOTIMPL; for (unsigned r = 0; r < numRecipients; r++) { UInt32 specSize = GetUi16(p2); p2 += 2; p2 += specSize; } } } else */ { if (reserved != 0) return E_NOTIMPL; } UInt32 validSize = GetUi16(p2); p2 += 2; const size_t validOffset = p2 - p; if ((validSize & 0xF) != 0 || validOffset + validSize != _remSize) return E_NOTIMPL; { RINOK(SetKey(_key.MasterKey, _key.KeySize)); RINOK(SetInitVector(_iv, 16)); RINOK(Init()); Filter(p, rdSize); } Byte fileKey[32]; NSha1::CContext sha; sha.Init(); sha.Update(_iv, _ivSize); sha.Update(p, rdSize - 16); // we don't use last 16 bytes (PAD bytes) DeriveKey(sha, fileKey); RINOK(SetKey(fileKey, _key.KeySize)); RINOK(SetInitVector(_iv, 16)); Init(); memmove(p, p + validOffset, validSize); Filter(p, validSize); if (validSize < 4) return E_NOTIMPL; validSize -= 4; if (GetUi32(p + validSize) != CrcCalc(p, validSize)) return S_OK; passwOK = true; return S_OK; }
static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAlloc *alloc) { UInt64 indexSize; Byte buf[XZ_STREAM_FOOTER_SIZE]; if ((*startOffset & 3) != 0 || *startOffset < XZ_STREAM_FOOTER_SIZE) return SZ_ERROR_NO_ARCHIVE; *startOffset = -XZ_STREAM_FOOTER_SIZE; RINOK(SeekFromCur(stream, startOffset)); RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) { UInt32 total = 0; *startOffset += XZ_STREAM_FOOTER_SIZE; for (;;) { size_t i; #define TEMP_BUF_SIZE (1 << 10) Byte tempBuf[TEMP_BUF_SIZE]; if (*startOffset < XZ_STREAM_FOOTER_SIZE || total > (1 << 16)) return SZ_ERROR_NO_ARCHIVE; i = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset; total += (UInt32)i; *startOffset = -(Int64)i; RINOK(SeekFromCur(stream, startOffset)); RINOK(LookInStream_Read2(stream, tempBuf, i, SZ_ERROR_NO_ARCHIVE)); for (; i != 0; i--) if (tempBuf[i - 1] != 0) break; if (i != 0) { if ((i & 3) != 0) return SZ_ERROR_NO_ARCHIVE; *startOffset += i; break; } } if (*startOffset < XZ_STREAM_FOOTER_SIZE) return SZ_ERROR_NO_ARCHIVE; *startOffset -= XZ_STREAM_FOOTER_SIZE; RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET)); RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) return SZ_ERROR_NO_ARCHIVE; } p->flags = (CXzStreamFlags)GetBe16(buf + 8); if (!XzFlags_IsSupported(p->flags)) return SZ_ERROR_UNSUPPORTED; if (GetUi32(buf) != CrcCalc(buf + 4, 6)) return SZ_ERROR_ARCHIVE; indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2; *startOffset = -(Int64)(indexSize + XZ_STREAM_FOOTER_SIZE); RINOK(SeekFromCur(stream, startOffset)); RINOK(Xz_ReadIndex(p, stream, indexSize, alloc)); { UInt64 totalSize = Xz_GetPackSize(p); UInt64 sum = XZ_STREAM_HEADER_SIZE + totalSize + indexSize; if (totalSize == XZ_SIZE_OVERFLOW || sum >= ((UInt64)1 << 63) || totalSize >= ((UInt64)1 << 63)) return SZ_ERROR_ARCHIVE; *startOffset = -(Int64)sum; RINOK(SeekFromCur(stream, startOffset)); } { CXzStreamFlags headerFlags; CSecToRead secToRead; SecToRead_CreateVTable(&secToRead); secToRead.realStream = stream; RINOK(Xz_ReadHeader(&headerFlags, &secToRead.s)); return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE; } }
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { NStream::NLSBF::CBaseDecoder<CInBuffer> inBuffer; COutBuffer outBuffer; if (!inBuffer.Create(kBufferSize)) return E_OUTOFMEMORY; inBuffer.SetStream(inStream); inBuffer.Init(); if (!outBuffer.Create(kBufferSize)) return E_OUTOFMEMORY; outBuffer.SetStream(outStream); outBuffer.Init(); int maxbits = _properties & kNumBitsMask; if (maxbits < kNumMinBits || maxbits > kNumMaxBits) return S_FALSE; UInt32 numItems = 1 << maxbits; bool blockMode = ((_properties & kBlockModeMask) != 0); if (!blockMode) return E_NOTIMPL; if (maxbits != _numMaxBits || _parents == 0 || _suffixes == 0 || _stack == 0) { if (!Alloc(numItems)) return E_OUTOFMEMORY; _numMaxBits = maxbits; } UInt64 prevPos = 0; int numBits = kNumMinBits; UInt32 head = blockMode ? 257 : 256; bool needPrev = false; int keepBits = 0; _parents[256] = 0; // virus protection _suffixes[256] = 0; while (true) { if (keepBits < numBits) keepBits = numBits * 8; UInt32 symbol = inBuffer.ReadBits(numBits); if (inBuffer.ExtraBitsWereRead()) break; keepBits -= numBits; if (symbol >= head) return S_FALSE; if (blockMode && symbol == 256) { for (;keepBits > 0; keepBits--) inBuffer.ReadBits(1); numBits = kNumMinBits; head = 257; needPrev = false; continue; } UInt32 cur = symbol; int i = 0; while (cur >= 256) { _stack[i++] = _suffixes[cur]; cur = _parents[cur]; } _stack[i++] = (Byte)cur; if (needPrev) { _suffixes[head - 1] = (Byte)cur; if (symbol == head - 1) _stack[0] = (Byte)cur; } while (i > 0) outBuffer.WriteByte((_stack[--i])); if (head < numItems) { needPrev = true; _parents[head++] = (UInt16)symbol; if (head > ((UInt32)1 << numBits)) { if (numBits < maxbits) { numBits++; keepBits = numBits * 8; } } } else needPrev = false; UInt64 nowPos = outBuffer.GetProcessedSize(); if (progress != NULL && nowPos - prevPos > (1 << 18)) { prevPos = nowPos; UInt64 packSize = inBuffer.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &nowPos)); } } return outBuffer.Flush(); }
static SRes SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); }
static SRes SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; }
static SRes SzArEx_Open2( CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte header[k7zStartHeaderSize]; Int64 startArcPos; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; #ifdef _7ZIP_CRC_SUPPORT UInt32 nextHeaderCRC; #endif CBuf buffer; SRes res; startArcPos = 0; RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR)); RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); if (!TestSignatureCandidate(header)) return SZ_ERROR_NO_ARCHIVE; if (header[6] != k7zMajorVersion) return SZ_ERROR_UNSUPPORTED; nextHeaderOffset = GetUi64(header + 12); nextHeaderSize = GetUi64(header + 20); #ifdef _7ZIP_CRC_SUPPORT nextHeaderCRC = GetUi32(header + 28); #endif p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; #ifdef _7ZIP_CRC_SUPPORT if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; #endif nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; if (nextHeaderSizeT == 0) return SZ_OK; if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) return SZ_ERROR_NO_ARCHIVE; { Int64 pos = 0; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); if ((UInt64)pos < startArcPos + nextHeaderOffset || (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); if (res == SZ_OK) { #ifdef _7ZIP_CRC_SUPPORT res = SZ_ERROR_ARCHIVE; if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) #else if (1) #endif { CSzData sd; UInt64 type; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); if (res == SZ_OK) { if (type == k7zIdEncodedHeader) { CBuf outBuffer; Buf_Init(&outBuffer); res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); if (res != SZ_OK) Buf_Free(&outBuffer, allocTemp); else { Buf_Free(&buffer, allocTemp); buffer.data = outBuffer.data; buffer.size = outBuffer.size; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); } } } if (res == SZ_OK) { if (type == k7zIdHeader) res = SzReadHeader(p, &sd, allocMain, allocTemp); else res = SZ_ERROR_UNSUPPORTED; } } } Buf_Free(&buffer, allocTemp); 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; }
static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { const CRefItem &a1 = *p1; const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; /* if (u1.IsAltStream != u2.IsAltStream) return u1.IsAltStream ? 1 : -1; */ // Actually there are no dirs that time. They were stored in other steps // So that code is unused? if (u1.IsDir != u2.IsDir) return u1.IsDir ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); int n = CompareFileNames(u1.Name, u2.Name); return -n; } // bool sortByType = *(bool *)param; const CSortParam *sortParam = (const CSortParam *)param; bool sortByType = sortParam->SortByType; if (sortByType) { RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex); RINOZ(CompareFileNames(u1.Name.Ptr(a1.ExtensionPos), u2.Name.Ptr(a2.ExtensionPos))); RINOZ(CompareFileNames(u1.Name.Ptr(a1.NamePos), u2.Name.Ptr(a2.NamePos))); if (!u1.MTimeDefined && u2.MTimeDefined) return 1; if (u1.MTimeDefined && !u2.MTimeDefined) return -1; if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime); RINOZ_COMP(u1.Size, u2.Size); } /* int par1 = a1.UpdateItem->ParentFolderIndex; int par2 = a2.UpdateItem->ParentFolderIndex; const CTreeFolder &tf1 = (*sortParam->TreeFolders)[par1]; const CTreeFolder &tf2 = (*sortParam->TreeFolders)[par2]; int b1 = tf1.SortIndex, e1 = tf1.SortIndexEnd; int b2 = tf2.SortIndex, e2 = tf2.SortIndexEnd; if (b1 < b2) { if (e1 <= b2) return -1; // p2 in p1 int par = par2; for (;;) { const CTreeFolder &tf = (*sortParam->TreeFolders)[par]; par = tf.Parent; if (par == par1) { RINOZ(CompareFileNames(u1.Name, tf.Name)); break; } } } else if (b2 < b1) { if (e2 <= b1) return 1; // p1 in p2 int par = par1; for (;;) { const CTreeFolder &tf = (*sortParam->TreeFolders)[par]; par = tf.Parent; if (par == par2) { RINOZ(CompareFileNames(tf.Name, u2.Name)); break; } } } */ // RINOZ_COMP(a1.UpdateItem->ParentSortIndex, a2.UpdateItem->ParentSortIndex); RINOK(CompareFileNames(u1.Name, u2.Name)); RINOZ_COMP(a1.UpdateItem->IndexInClient, a2.UpdateItem->IndexInClient); RINOZ_COMP(a1.UpdateItem->IndexInArchive, a2.UpdateItem->IndexInArchive); return 0; }
STDMETHODIMP CNsisDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { try { *processedSize = 0; if (_nsisState == NSIS_STATE_FINISHED) return S_OK; if (_nsisState == NSIS_STATE_ERROR) return S_FALSE; if (size == 0) return S_OK; CState &state = m_State; if (_nsisState == NSIS_STATE_INIT) { if (!Base.BitDecoder.Create(kBufferSize)) return E_OUTOFMEMORY; if (!state.Alloc()) return E_OUTOFMEMORY; Base.BitDecoder.Init(); _nsisState = NSIS_STATE_NEW_BLOCK; } if (_nsisState == NSIS_STATE_NEW_BLOCK) { Byte b = (Byte)Base.ReadBits(8); if (b == kFinSig0) { _nsisState = NSIS_STATE_FINISHED; return S_OK; } if (b != kBlockSig0) { _nsisState = NSIS_STATE_ERROR; return S_FALSE; } CBlockProps props; props.randMode = false; RINOK(Base.ReadBlock(state.Counters, 9 * kBlockSizeStep, &props)); _blockSize = props.blockSize; DecodeBlock1(state.Counters, props.blockSize); const UInt32 *tt = state.Counters + 256; _tPos = tt[tt[props.origPtr] >> 8]; _prevByte = (unsigned)(_tPos & 0xFF); _numReps = 0; _repRem = 0; _nsisState = NSIS_STATE_DATA; } UInt32 tPos = _tPos; unsigned prevByte = _prevByte; unsigned numReps = _numReps; UInt32 blockSize = _blockSize; const UInt32 *tt = state.Counters + 256; while (_repRem) { _repRem--; *(Byte *)data = (Byte)prevByte; data = (Byte *)data + 1; (*processedSize)++; if (--size == 0) return S_OK; } if (blockSize == 0) { _nsisState = NSIS_STATE_NEW_BLOCK; return S_OK; } do { unsigned b = (unsigned)(tPos & 0xFF); tPos = tt[tPos >> 8]; blockSize--; if (numReps == kRleModeRepSize) { numReps = 0; while (b) { b--; *(Byte *)data = (Byte)prevByte; data = (Byte *)data + 1; (*processedSize)++; if (--size == 0) break; } _repRem = b; continue; } if (b != prevByte) numReps = 0; numReps++; prevByte = b; *(Byte *)data = (Byte)b; data = (Byte *)data + 1; (*processedSize)++; size--; } while (size && blockSize); _tPos = tPos; _prevByte = prevByte; _numReps = numReps; _blockSize = blockSize; return S_OK; }
HRESULT CDecoder::DecodeFile(ICompressProgressInfo *progress) { Progress = progress; #ifndef _7ZIP_ST RINOK(Create()); for (UInt32 t = 0; t < NumThreads; t++) { CState &s = m_States[t]; if (!s.Alloc()) return E_OUTOFMEMORY; if (MtMode) { RINOK(s.StreamWasFinishedEvent.Reset()); RINOK(s.WaitingWasStartedEvent.Reset()); RINOK(s.CanWriteEvent.Reset()); } } #else if (!m_States[0].Alloc()) return E_OUTOFMEMORY; #endif IsBz = false; /* if (Base.BitDecoder.ExtraBitsWereRead()) return E_FAIL; */ Byte s[4]; unsigned i; for (i = 0; i < 4; i++) s[i] = ReadByte(); if (Base.BitDecoder.ExtraBitsWereRead()) return S_FALSE; if (s[0] != kArSig0 || s[1] != kArSig1 || s[2] != kArSig2 || s[3] <= kArSig3 || s[3] > kArSig3 + kBlockSizeMultMax) return S_FALSE; UInt32 dicSize = (UInt32)(s[3] - kArSig3) * kBlockSizeStep; CombinedCrc.Init(); #ifndef _7ZIP_ST if (MtMode) { NextBlockIndex = 0; StreamWasFinished1 = StreamWasFinished2 = false; CloseThreads = false; CanStartWaitingEvent.Reset(); m_States[0].CanWriteEvent.Set(); BlockSizeMax = dicSize; Result1 = Result2 = S_OK; CanProcessEvent.Set(); UInt32 t; for (t = 0; t < NumThreads; t++) m_States[t].StreamWasFinishedEvent.Lock(); CanProcessEvent.Reset(); CanStartWaitingEvent.Set(); for (t = 0; t < NumThreads; t++) m_States[t].WaitingWasStartedEvent.Lock(); CanStartWaitingEvent.Reset(); RINOK(Result2); RINOK(Result1); } else #endif { CState &state = m_States[0]; for (;;) { RINOK(SetRatioProgress(Base.BitDecoder.GetProcessedSize())); UInt32 crc; RINOK(ReadSignature(crc)); if (BzWasFinished) return S_OK; CBlockProps props; props.randMode = true; RINOK(Base.ReadBlock(state.Counters, dicSize, &props)); DecodeBlock1(state.Counters, props.blockSize); if (DecodeBlock(props, state.Counters + 256, m_OutStream) != crc) { CrcError = true; return S_FALSE; } } } return SetRatioProgress(Base.BitDecoder.GetProcessedSize()); }
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, const CObjectVector<NArchive::NTar::CItemEx> &inputItems, const CObjectVector<CUpdateItemInfo> &updateItems, IArchiveUpdateCallback *updateCallback) { COutArchive outArchive; outArchive.Create(outStream); UInt64 complexity = 0; int i; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItemInfo &updateItem = updateItems[i]; if (updateItem.NewData) complexity += updateItem.Size; else complexity += inputItems[updateItem.IndexInArchive].GetFullSize(); complexity += kOneItemComplexity; } RINOK(updateCallback->SetTotal(complexity)); complexity = 0; for(i = 0; i < updateItems.Size(); i++) { RINOK(updateCallback->SetCompleted(&complexity)); CLocalProgress *localProgressSpec = new CLocalProgress; CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec; localProgressSpec->Init(updateCallback, true); CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo; CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec; localCompressProgressSpec->Init(localProgress, &complexity, NULL); const CUpdateItemInfo &updateItem = updateItems[i]; CItem item; if (updateItem.NewProperties) { item.Mode = 0777; item.Name = (updateItem.Name); if (updateItem.IsDirectory) { item.LinkFlag = NFileHeader::NLinkFlag::kDirectory; item.Size = 0; } else { item.LinkFlag = NFileHeader::NLinkFlag::kNormal; item.Size = updateItem.Size; } item.ModificationTime = updateItem.Time; item.DeviceMajorDefined = false; item.DeviceMinorDefined = false; item.UID = 0; item.GID = 0; memmove(item.Magic, NFileHeader::NMagic::kEmpty, 8); } else { const CItemEx &existItemInfo = inputItems[updateItem.IndexInArchive]; item = existItemInfo; } if (updateItem.NewData) { item.Size = updateItem.Size; if (item.Size == UInt64(Int64(-1))) return E_INVALIDARG; } else { const CItemEx &existItemInfo = inputItems[updateItem.IndexInArchive]; item.Size = existItemInfo.Size; } if (updateItem.NewData) { CMyComPtr<ISequentialInStream> fileInStream; HRESULT res = updateCallback->GetStream(updateItem.IndexInClient, &fileInStream); if (res != S_FALSE) { RINOK(res); RINOK(outArchive.WriteHeader(item)); if (!updateItem.IsDirectory) { UInt64 totalSize; RINOK(CopyBlock(fileInStream, outStream, compressProgress, &totalSize)); if (totalSize != item.Size) return E_FAIL; RINOK(outArchive.FillDataResidual(item.Size)); } } complexity += updateItem.Size; RINOK(updateCallback->SetOperationResult( NArchive::NUpdate::NOperationResult::kOK)); } else { CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); const CItemEx &existItemInfo = inputItems[updateItem.IndexInArchive]; if (updateItem.NewProperties) { RINOK(outArchive.WriteHeader(item)); RINOK(inStream->Seek(existItemInfo.GetDataPosition(), STREAM_SEEK_SET, NULL)); streamSpec->Init(inStream, existItemInfo.Size); } else { RINOK(inStream->Seek(existItemInfo.HeaderPosition, STREAM_SEEK_SET, NULL)); streamSpec->Init(inStream, existItemInfo.GetFullSize()); } RINOK(CopyBlock(inStreamLimited, outStream, compressProgress)); RINOK(outArchive.FillDataResidual(existItemInfo.Size)); complexity += existItemInfo.GetFullSize(); } complexity += kOneItemComplexity; } return outArchive.WriteFinishHeader(); }
static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) { UInt32 numCoders, numBindPairs, numPackStreams, i; UInt32 numInStreams = 0, numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); if (numCoders > NUM_FOLDER_CODERS_MAX) return SZ_ERROR_UNSUPPORTED; folder->NumCoders = numCoders; MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc); for (i = 0; i < numCoders; i++) SzCoderInfo_Init(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CSzCoderInfo *coder = folder->Coders + i; { unsigned idSize, j; Byte longID[15]; RINOK(SzReadByte(sd, &mainByte)); idSize = (unsigned)(mainByte & 0xF); RINOK(SzReadBytes(sd, longID, idSize)); if (idSize > sizeof(coder->MethodID)) return SZ_ERROR_UNSUPPORTED; coder->MethodID = 0; for (j = 0; j < idSize; j++) coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); if (coder->NumInStreams > NUM_CODER_STREAMS_MAX || coder->NumOutStreams > NUM_CODER_STREAMS_MAX) return SZ_ERROR_UNSUPPORTED; } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc)) return SZ_ERROR_MEM; RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += coder->NumInStreams; numOutStreams += coder->NumOutStreams; } if (numOutStreams == 0) return SZ_ERROR_UNSUPPORTED; folder->NumBindPairs = numBindPairs = numOutStreams - 1; MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); for (i = 0; i < numBindPairs; i++) { CSzBindPair *bp = folder->BindPairs + i; RINOK(SzReadNumber32(sd, &bp->InIndex)); RINOK(SzReadNumber32(sd, &bp->OutIndex)); } if (numInStreams < numBindPairs) return SZ_ERROR_UNSUPPORTED; folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs; MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc); if (numPackStreams == 1) { for (i = 0; i < numInStreams ; i++) if (SzFolder_FindBindPairForInStream(folder, i) < 0) break; if (i == numInStreams) return SZ_ERROR_UNSUPPORTED; folder->PackStreams[0] = i; } else for (i = 0; i < numPackStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; }
HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { #ifdef COMPRESS_BZIP2_MT Progress = progress; if (!Create()) return E_FAIL; for (UInt32 t = 0; t < NumThreads; t++) #endif { #ifdef COMPRESS_BZIP2_MT CThreadInfo &ti = ThreadsInfo[t]; ti.StreamWasFinishedEvent.Reset(); ti.WaitingWasStartedEvent.Reset(); ti.CanWriteEvent.Reset(); #else CThreadInfo &ti = ThreadsInfo; ti.Encoder = this; #endif ti.m_OptimizeNumTables = m_OptimizeNumTables; if (!ti.Create()) return E_OUTOFMEMORY; } if (!m_InStream.Create(kBufferSize)) return E_OUTOFMEMORY; if (!m_OutStream.Create(kBufferSize)) return E_OUTOFMEMORY; m_InStream.SetStream(inStream); m_InStream.Init(); m_OutStream.SetStream(outStream); m_OutStream.Init(); CFlusher flusher(this); CombinedCRC.Init(); #ifdef COMPRESS_BZIP2_MT NextBlockIndex = 0; StreamWasFinished = false; CloseThreads = false; CanStartWaitingEvent.Reset(); #endif WriteByte(kArSig0); WriteByte(kArSig1); WriteByte(kArSig2); WriteByte((Byte)(kArSig3 + m_BlockSizeMult)); #ifdef COMPRESS_BZIP2_MT if (MtMode) { ThreadsInfo[0].CanWriteEvent.Set(); Result = S_OK; CS.Leave(); UInt32 t; for (t = 0; t < NumThreads; t++) ThreadsInfo[t].StreamWasFinishedEvent.Lock(); CS.Enter(); CanStartWaitingEvent.Set(); for (t = 0; t < NumThreads; t++) ThreadsInfo[t].WaitingWasStartedEvent.Lock(); CanStartWaitingEvent.Reset(); RINOK(Result); } else #endif { for (;;) { CThreadInfo &ti = #ifdef COMPRESS_BZIP2_MT ThreadsInfo[0]; #else ThreadsInfo; #endif UInt32 blockSize = ReadRleBlock(ti.m_Block); if (blockSize == 0) break; RINOK(ti.EncodeBlock3(blockSize)); if (progress) { UInt64 packSize = m_InStream.GetProcessedSize(); UInt64 unpackSize = m_OutStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &unpackSize)); } } } WriteByte(kFinSig0); WriteByte(kFinSig1); WriteByte(kFinSig2); WriteByte(kFinSig3); WriteByte(kFinSig4); WriteByte(kFinSig5); WriteCRC(CombinedCRC.GetDigest()); return S_OK; }
static SRes SzReadUnpackInfo( CSzData *sd, UInt32 *numFolders, CSzFolder **folders, /* for alloc */ ISzAlloc *alloc, ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc); for (i = 0; i < *numFolders; i++) SzFolder_Init((*folders) + i); for (i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize)); for (i = 0; i < *numFolders; i++) { UInt32 j; CSzFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder); MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc); for (j = 0; j < numOutStreams; j++) { RINOK(SzReadNumber(sd, folder->UnpackSizes + j)); } } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SRes res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp); if (res == SZ_OK) { for (i = 0; i < *numFolders; i++) { CSzFolder *folder = (*folders) + i; folder->UnpackCRCDefined = crcsDefined[i]; folder->UnpackCRC = crcs[i]; } } IAlloc_Free(allocTemp, crcs); IAlloc_Free(allocTemp, crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } }
HRESULT CInArchive::Open2() { Clear(); RINOK(_stream->Seek(kStartPos, STREAM_SEEK_CUR, &_position)); m_BufferPos = 0; BlockSize = kBlockSize; for (;;) { Byte sig[7]; ReadBytes(sig, 7); Byte ver = sig[6]; if (!CheckSignature(kSig_CD001, sig + 1)) { return S_FALSE; /* if (sig[0] != 0 || ver != 1) break; if (CheckSignature(kSig_BEA01, sig + 1)) { } else if (CheckSignature(kSig_TEA01, sig + 1)) { break; } else if (CheckSignature(kSig_NSR02, sig + 1)) { } else break; SkipZeros(0x800 - 7); continue; */ } // version = 2 for ISO 9660:1999? if (ver > 2) throw S_FALSE; if (sig[0] == NVolDescType::kTerminator) { break; // Skip(0x800 - 7); // continue; } switch(sig[0]) { case NVolDescType::kBootRecord: { _bootIsDefined = true; ReadBootRecordDescriptor(_bootDesc); break; } case NVolDescType::kPrimaryVol: case NVolDescType::kSupplementaryVol: { // some ISOs have two PrimaryVols. CVolumeDescriptor vd; ReadVolumeDescriptor(vd); if (sig[0] == NVolDescType::kPrimaryVol) { // some burners write "Joliet" Escape Sequence to primary volume memset(vd.EscapeSequence, 0, sizeof(vd.EscapeSequence)); } VolDescs.Add(vd); break; } default: break; } } if (VolDescs.IsEmpty()) return S_FALSE; for (MainVolDescIndex = VolDescs.Size() - 1; MainVolDescIndex > 0; MainVolDescIndex--) if (VolDescs[MainVolDescIndex].IsJoliet()) break; // MainVolDescIndex = 0; // to read primary volume const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex]; if (vd.LogicalBlockSize != kBlockSize) return S_FALSE; (CDirRecord &)_rootDir = vd.RootDirRecord; ReadDir(_rootDir, 0); CreateRefs(_rootDir); ReadBootInfo(); return S_OK; }
static SRes SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CSzFolder *folders, UInt32 *numUnpackStreams, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for (i = 0; i < numFolders; i++) folders[i].NumUnpackStreams = 1; *numUnpackStreams = numFolders; for (;;) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnpackStream) { *numUnpackStreams = 0; for (i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnpackStreams = numStreams; *numUnpackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnpackStreams == 0) { *unpackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64)); RINOM(*unpackSizes); *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32)); RINOM(*digests); } for (i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ UInt64 sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { UInt64 size; RINOK(SzReadNumber(sd, &size)); (*unpackSizes)[si++] = size; sum += size; } (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for (i = 0; i < *numUnpackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for (i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; } si = 0; for (;;) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CSzFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnpackStreams; if (numSubstreams == 1 && folder->UnpackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnpackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } IAlloc_Free(allocTemp, digestsDefined2); IAlloc_Free(allocTemp, digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } }
HRESULT CInArchive::Open(IInStream *inStream) { RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); m_Stream = inStream; return S_OK; }
static SRes SzReadHeader2( CSzArEx *p, /* allocMain */ CSzData *sd, UInt64 **unpackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ Byte **lwtVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnpackStreams = 0; UInt32 numFiles = 0; CSzFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &p->dataPos, &p->db, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocMain, allocTemp)); p->dataPos += p->startPosAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZ_ERROR_ARCHIVE; RINOK(SzReadNumber32(sd, &numFiles)); p->db.NumFiles = numFiles; MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain); p->db.Files = files; for (i = 0; i < numFiles; i++) SzFile_Init(files + i); for (;;) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if (size > sd->Size) return SZ_ERROR_ARCHIVE; if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { size_t namesSize; RINOK(SzReadSwitch(sd)); namesSize = (size_t)size - 1; if ((namesSize & 1) != 0) return SZ_ERROR_ARCHIVE; if (!Buf_Create(&p->FileNames, namesSize, allocMain)) return SZ_ERROR_MEM; MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); memcpy(p->FileNames.data, sd->Data, namesSize); RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets)) RINOK(SzSkeepDataSize(sd, namesSize)); break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); break; } case k7zIdWinAttributes: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); RINOK(SzReadSwitch(sd)); for (i = 0; i < numFiles; i++) { CSzFileItem *f = &files[i]; Byte defined = (*lwtVector)[i]; f->AttribDefined = defined; f->Attrib = 0; if (defined) { RINOK(SzReadUInt32(sd, &f->Attrib)); } } IAlloc_Free(allocTemp, *lwtVector); *lwtVector = NULL; break; } case k7zIdMTime: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); RINOK(SzReadSwitch(sd)); for (i = 0; i < numFiles; i++) { CSzFileItem *f = &files[i]; Byte defined = (*lwtVector)[i]; f->MTimeDefined = defined; f->MTime.Low = f->MTime.High = 0; if (defined) { RINOK(SzReadUInt32(sd, &f->MTime.Low)); RINOK(SzReadUInt32(sd, &f->MTime.High)); } } IAlloc_Free(allocTemp, *lwtVector); *lwtVector = NULL; break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for (i = 0; i < numFiles; i++) { CSzFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if (file->HasStream) { file->IsDir = 0; file->Size = (*unpackSizes)[sizeIndex]; file->Crc = (*digests)[sizeIndex]; file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDir = 1; else file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->Crc = 0; file->CrcDefined = 0; } } } return SzArEx_Fill(p, allocMain); }
HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { NBitl::CBaseDecoder<CInBuffer> inBuffer; COutBuffer outBuffer; if (!inBuffer.Create(kBufferSize)) return E_OUTOFMEMORY; inBuffer.SetStream(inStream); inBuffer.Init(); if (!outBuffer.Create(kBufferSize)) return E_OUTOFMEMORY; outBuffer.SetStream(outStream); outBuffer.Init(); { unsigned i; for (i = 0; i < 257; i++) _parents[i] = (UInt16)i; for (; i < kNumItems; i++) _parents[i] = kNumItems; for (i = 0; i < kNumItems; i++) _suffixes[i] = 0; } UInt64 prevPos = 0; unsigned numBits = kNumMinBits; unsigned head = 257; int lastSym = -1; Byte lastChar2 = 0; for (;;) { UInt32 sym = inBuffer.ReadBits(numBits); if (inBuffer.ExtraBitsWereRead()) break; if (sym == 256) { sym = inBuffer.ReadBits(numBits); if (sym == 1) { if (numBits >= kNumMaxBits) return S_FALSE; numBits++; continue; } if (sym != 2) return S_FALSE; { unsigned i; for (i = 257; i < kNumItems; i++) _stack[i] = 0; for (i = 257; i < kNumItems; i++) { unsigned par = _parents[i]; if (par != kNumItems) _stack[par] = 1; } for (i = 257; i < kNumItems; i++) if (_stack[i] == 0) _parents[i] = kNumItems; head = 257; continue; } } bool needPrev = false; if (head < kNumItems && lastSym >= 0) { while (head < kNumItems && _parents[head] != kNumItems) head++; if (head < kNumItems) { if (head == (unsigned)lastSym) { // we need to fix the code for that case // _parents[head] is not allowed to link to itself return E_NOTIMPL; } needPrev = true; _parents[head] = (UInt16)lastSym; _suffixes[head] = (Byte)lastChar2; head++; } } if (_parents[sym] == kNumItems) return S_FALSE; lastSym = sym; unsigned cur = sym; unsigned i = 0; while (cur >= 256) { _stack[i++] = _suffixes[cur]; cur = _parents[cur]; } _stack[i++] = (Byte)cur; lastChar2 = (Byte)cur; if (needPrev) _suffixes[head - 1] = (Byte)cur; do outBuffer.WriteByte(_stack[--i]); while (i); if (progress) { const UInt64 nowPos = outBuffer.GetProcessedSize(); if (nowPos - prevPos >= (1 << 18)) { prevPos = nowPos; const UInt64 packSize = inBuffer.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &nowPos)); } } } return outBuffer.Flush(); }
HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { NBitl::CBaseDecoder<CInBuffer> inBuffer; COutBuffer outBuffer; if (!inBuffer.Create(kBufferSize)) return E_OUTOFMEMORY; inBuffer.SetStream(inStream); inBuffer.Init(); if (!outBuffer.Create(kBufferSize)) return E_OUTOFMEMORY; outBuffer.SetStream(outStream); outBuffer.Init(); UInt64 prevPos = 0; int numBits = kNumMinBits; UInt32 head = 257; bool needPrev = false; UInt32 lastSymbol = 0; int i; for (i = 0; i < kNumItems; i++) _parents[i] = 0; for (i = 0; i < kNumItems; i++) _suffixes[i] = 0; for (i = 0; i < 257; i++) _isFree[i] = false; for (; i < kNumItems; i++) _isFree[i] = true; for (;;) { UInt32 symbol = inBuffer.ReadBits(numBits); if (inBuffer.ExtraBitsWereRead()) break; if (_isFree[symbol]) return S_FALSE; if (symbol == 256) { UInt32 symbol = inBuffer.ReadBits(numBits); if (symbol == 1) { if (numBits < kNumMaxBits) numBits++; } else if (symbol == 2) { if (needPrev) _isFree[head - 1] = true; for (i = 257; i < kNumItems; i++) _isParent[i] = false; for (i = 257; i < kNumItems; i++) if (!_isFree[i]) _isParent[_parents[i]] = true; for (i = 257; i < kNumItems; i++) if (!_isParent[i]) _isFree[i] = true; head = 257; while (head < kNumItems && !_isFree[head]) head++; if (head < kNumItems) { needPrev = true; _isFree[head] = false; _parents[head] = (UInt16)lastSymbol; head++; } } else return S_FALSE; continue; } UInt32 cur = symbol; i = 0; int corectionIndex = -1; while (cur >= 256) { if (cur == head - 1) corectionIndex = i; _stack[i++] = _suffixes[cur]; cur = _parents[cur]; } _stack[i++] = (Byte)cur; if (needPrev) { _suffixes[head - 1] = (Byte)cur; if (corectionIndex >= 0) _stack[corectionIndex] = (Byte)cur; } while (i > 0) outBuffer.WriteByte((_stack[--i])); while (head < kNumItems && !_isFree[head]) head++; if (head < kNumItems) { needPrev = true; _isFree[head] = false; _parents[head] = (UInt16)symbol; head++; } else needPrev = false; lastSymbol = symbol; UInt64 nowPos = outBuffer.GetProcessedSize(); if (progress != NULL && nowPos - prevPos > (1 << 18)) { prevPos = nowPos; UInt64 packSize = inBuffer.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &nowPos)); } } return outBuffer.Flush(); }
SRes SzAr_Extract( const CSzArEx *p, ILookInStream *inStream, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; SRes res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-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 unpackSizeSpec = SzFolder_GetUnpackSize(folder); size_t unpackSize = (size_t)unpackSizeSpec; UInt64 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 = (Byte *)IAlloc_Alloc(allocMain, unpackSize); if (*outBuffer == 0) res = SZ_ERROR_MEM; } if (res == SZ_OK) { res = SzDecode(p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], folder, 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 i; CSzFileItem *fileItem = p->db.Files + fileIndex; *offset = 0; for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)p->db.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZ_ERROR_FAIL; { if (fileItem->FileCRCDefined) { if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) res = SZ_ERROR_CRC; } } } return res; }
static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf, ISeqOutStream *outStream, ISeqInStream *inStream, const CXzProps *props, ICompressProgress *progress) { xz->flags = (Byte)props->checkId; RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, props->lzma2Props)); RINOK(Xz_WriteHeader(xz->flags, outStream)); { CSeqCheckInStream checkInStream; CSeqSizeOutStream seqSizeOutStream; CXzBlock block; unsigned filterIndex = 0; CXzFilter *filter = NULL; const CXzFilterProps *fp = props->filterProps; XzBlock_ClearFlags(&block); XzBlock_SetNumFilters(&block, 1 + (fp ? 1 : 0)); if (fp) { filter = &block.filters[filterIndex++]; filter->id = fp->id; filter->propsSize = 0; if (fp->id == XZ_ID_Delta) { filter->props[0] = (Byte)(fp->delta - 1); filter->propsSize = 1; } else if (fp->ipDefined) { SetUi32(filter->props, fp->ip); filter->propsSize = 4; } } { CXzFilter *f = &block.filters[filterIndex++]; f->id = XZ_ID_LZMA2; f->propsSize = 1; f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2); } seqSizeOutStream.p.Write = MyWrite; seqSizeOutStream.realStream = outStream; seqSizeOutStream.processed = 0; RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.p)); checkInStream.p.Read = SeqCheckInStream_Read; checkInStream.realStream = inStream; SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags)); if (fp) { #ifdef USE_SUBBLOCK if (fp->id == XZ_ID_Subblock) { lzmaf->sb.inStream = &checkInStream.p; RINOK(SbEncInStream_Init(&lzmaf->sb)); } else #endif { lzmaf->filter.realStream = &checkInStream.p; RINOK(SeqInFilter_Init(&lzmaf->filter, filter)); } } { UInt64 packPos = seqSizeOutStream.processed; SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p, fp ? #ifdef USE_SUBBLOCK (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p: #endif &lzmaf->filter.p: &checkInStream.p, progress); RINOK(res); block.unpackSize = checkInStream.processed; block.packSize = seqSizeOutStream.processed - packPos; } { unsigned padSize = 0; Byte buf[128]; while((((unsigned)block.packSize + padSize) & 3) != 0) buf[padSize++] = 0; SeqCheckInStream_GetDigest(&checkInStream, buf + padSize); RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags))); RINOK(Xz_AddIndexRecord(xz, block.unpackSize, seqSizeOutStream.processed - padSize, &g_Alloc)); } } return Xz_WriteFooter(xz, outStream); }
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; *srcLen = 0; *status = LZMA_STATUS_NOT_SPECIFIED; while (p->state != LZMA2_STATE_FINISHED) { SizeT dicPos = p->decoder.dicPos; if (p->state == LZMA2_STATE_ERROR) return SZ_ERROR_DATA; if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_OK; } if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) { if (*srcLen == inSize) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } (*srcLen)++; p->state = Lzma2Dec_UpdateState(p, *src++); continue; } { SizeT destSizeCur = dicLimit - dicPos; SizeT srcSizeCur = inSize - *srcLen; ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; if (p->unpackSize <= destSizeCur) { destSizeCur = (SizeT)p->unpackSize; curFinishMode = LZMA_FINISH_END; } if (LZMA2_IS_UNCOMPRESSED_STATE(p)) { if (*srcLen == inSize) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (p->state == LZMA2_STATE_DATA) { Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); if (initDic) p->needInitProp = p->needInitState = True; else if (p->needInitDic) return SZ_ERROR_DATA; p->needInitDic = False; LzmaDec_InitDicAndState(&p->decoder, initDic, False); } if (srcSizeCur > destSizeCur) srcSizeCur = destSizeCur; if (srcSizeCur == 0) return SZ_ERROR_DATA; LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur); src += srcSizeCur; *srcLen += srcSizeCur; p->unpackSize -= (UInt32)srcSizeCur; p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; } else { SizeT outSizeProcessed; SRes res; if (p->state == LZMA2_STATE_DATA) { int mode = LZMA2_GET_LZMA_MODE(p); Bool initDic = (mode == 3); Bool initState = (mode > 0); if ((!initDic && p->needInitDic) || (!initState && p->needInitState)) return SZ_ERROR_DATA; LzmaDec_InitDicAndState(&p->decoder, initDic, initState); p->needInitDic = False; p->needInitState = False; p->state = LZMA2_STATE_DATA_CONT; } if (srcSizeCur > p->packSize) srcSizeCur = (SizeT)p->packSize; res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status); src += srcSizeCur; *srcLen += srcSizeCur; p->packSize -= (UInt32)srcSizeCur; outSizeProcessed = p->decoder.dicPos - dicPos; p->unpackSize -= (UInt32)outSizeProcessed; RINOK(res); if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) return res; if (srcSizeCur == 0 && outSizeProcessed == 0) { if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK || p->unpackSize != 0 || p->packSize != 0) return SZ_ERROR_DATA; p->state = LZMA2_STATE_CONTROL; } if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) *status = LZMA_STATUS_NOT_FINISHED; } } } *status = LZMA_STATUS_FINISHED_WITH_MARK; return SZ_OK; }
HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder) { bool created = false; UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (codec.Id == methodId) { if (encode) { if (codec.CreateEncoder) { void *p = codec.CreateEncoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } else if (codec.CreateDecoder) { void *p = codec.CreateDecoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } } #ifdef EXTERNAL_CODECS if (!created && externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Id == methodId) { if (encode) { if (codec.EncoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } else if (codec.DecoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } } #endif if (onlyCoder && filter) { CFilterCoder *coderSpec = new CFilterCoder; coder = coderSpec; coderSpec->Filter = filter; } return S_OK; }
HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (!m_InBitStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!m_OutWindowStream.Create(kHistorySize)) return E_OUTOFMEMORY; if (outSize == NULL) return E_INVALIDARG; UInt64 pos = 0, unPackSize = *outSize; m_OutWindowStream.SetStream(outStream); m_OutWindowStream.Init(false); m_InBitStream.SetStream(inStream); m_InBitStream.Init(); // CCoderReleaser coderReleaser(this); if (!ReadTables()) return S_FALSE; while (pos < unPackSize) { if (progress != NULL && pos % (1 << 16) == 0) { UInt64 packSize = m_InBitStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &pos)); } if (m_InBitStream.ReadBits(1) == kMatchId) // match { UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits); UInt32 distance = m_DistanceDecoder.DecodeSymbol(&m_InBitStream); if (distance >= kDistanceTableSize) return S_FALSE; distance = (distance << m_NumDistanceLowDirectBits) + lowDistBits; UInt32 lengthSymbol = m_LengthDecoder.DecodeSymbol(&m_InBitStream); if (lengthSymbol >= kLengthTableSize) return S_FALSE; UInt32 length = lengthSymbol + m_MinMatchLength; if (lengthSymbol == kLengthTableSize - 1) // special symbol = 63 length += m_InBitStream.ReadBits(kNumAdditionalLengthBits); while (distance >= pos && length > 0) { m_OutWindowStream.PutByte(0); pos++; length--; } if (length > 0) m_OutWindowStream.CopyBlock(distance, length); pos += length; } else { Byte b; if (m_LiteralsOn) { UInt32 temp = m_LiteralDecoder.DecodeSymbol(&m_InBitStream); if (temp >= kLiteralTableSize) return S_FALSE; b = (Byte)temp; } else b = (Byte)m_InBitStream.ReadBits(kNumBitsInByte); m_OutWindowStream.PutByte(b); pos++; } } if (pos > unPackSize) return S_FALSE; return m_OutWindowStream.Flush(); }
HRESULT CEncoder::Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()); if (_mixerCoderSpec == NULL) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } _mixerCoderSpec->ReInit(); // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); CObjectVector<CInOutTempBuffer> inOutTempBuffers; CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; int numMethods = _bindInfo.Coders.Size(); int i; for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { inOutTempBuffers.Add(CInOutTempBuffer()); inOutTempBuffers.Back().Create(); inOutTempBuffers.Back().InitWriting(); } for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec; tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBuffers.Add(tempBuffer); tempBufferSpecs.Add(tempBufferSpec); } for (i = 0; i < numMethods; i++) _mixerCoderSpec->SetCoderInfo(i, NULL, NULL); if (_bindInfo.InStreams.IsEmpty()) return E_FAIL; UInt32 mainCoderIndex, mainStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); if (inStreamSize != NULL) { CRecordVector<const UInt64 *> sizePointers; for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) if (i == mainStreamIndex) sizePointers.Add(inStreamSize); else sizePointers.Add(NULL); _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); } // UInt64 outStreamStartPos; // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec; inStreamSizeCountSpec->Init(inStream); outStreamSizeCountSpec->SetStream(outStream); outStreamSizeCountSpec->Init(); CRecordVector<ISequentialInStream *> inStreamPointers; CRecordVector<ISequentialOutStream *> outStreamPointers; inStreamPointers.Add(inStreamSizeCount); outStreamPointers.Add(outStreamSizeCount); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); for (i = 0; i < _codersInfo.Size(); i++) { CCoderInfo &encodingInfo = _codersInfo[i]; CMyComPtr<ICryptoResetInitVector> resetInitVector; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); if (resetInitVector != NULL) { resetInitVector->ResetInitVector(); } CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); writeCoderProperties->WriteCoderProperties(outStream); size_t size = outStreamSpec->GetSize(); encodingInfo.Props.SetCapacity(size); memmove(encodingInfo.Props, outStreamSpec->GetBuffer(), size); } } UInt32 progressIndex = mainCoderIndex; for (i = 0; i < _codersInfo.Size(); i++) { const CCoderInfo &e = _codersInfo[i]; if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size()) progressIndex = i + 1; } _mixerCoderSpec->SetProgressCoderIndex(progressIndex); RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); packSizes.Add(outStreamSizeCountSpec->GetSize()); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; inOutTempBuffer.FlushWrite(); inOutTempBuffer.InitReading(); inOutTempBuffer.WriteToStream(outStream); packSizes.Add(inOutTempBuffer.GetDataSize()); } for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) { int binder = _bindInfo.FindBinderForInStream( _bindReverseConverter->DestOutToSrcInMap[i]); UInt64 streamSize; if (binder < 0) streamSize = inStreamSizeCountSpec->GetSize(); else streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); folderItem.UnpackSizes.Add(streamSize); } for (i = numMethods - 1; i >= 0; i--) folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props; return S_OK; }