mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 12:07:03 -06:00
18.05
This commit is contained in:
@@ -549,9 +549,9 @@ private:
|
||||
|
||||
Byte *TempBuf;
|
||||
UInt32 TempBufSize;
|
||||
UInt32 TempBufWritten;
|
||||
unsigned NumIdenticalFiles;
|
||||
bool TempBufMode;
|
||||
UInt32 m_BufStartFolderOffset;
|
||||
|
||||
unsigned m_StartIndex;
|
||||
unsigned m_CurrentIndex;
|
||||
@@ -575,7 +575,6 @@ private:
|
||||
HRESULT OpenFile();
|
||||
HRESULT CloseFileWithResOp(Int32 resOp);
|
||||
HRESULT CloseFile();
|
||||
HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK);
|
||||
public:
|
||||
HRESULT WriteEmptyFiles();
|
||||
|
||||
@@ -672,11 +671,11 @@ HRESULT CFolderOutStream::OpenFile()
|
||||
FreeTempBuf();
|
||||
TempBuf = (Byte *)MyAlloc(item.Size);
|
||||
TempBufSize = item.Size;
|
||||
if (TempBuf == NULL)
|
||||
if (!TempBuf)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
TempBufMode = true;
|
||||
m_BufStartFolderOffset = item.Offset;
|
||||
TempBufWritten = 0;
|
||||
}
|
||||
else if (numExtractItems == 1)
|
||||
{
|
||||
@@ -725,8 +724,9 @@ HRESULT CFolderOutStream::WriteEmptyFiles()
|
||||
}
|
||||
|
||||
|
||||
HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)
|
||||
HRESULT CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
// (data == NULL) means Error_Data for solid folder flushing
|
||||
COM_TRY_BEGIN
|
||||
|
||||
UInt32 realProcessed = 0;
|
||||
@@ -741,21 +741,34 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
HRESULT res = S_OK;
|
||||
if (numBytesToWrite != 0)
|
||||
{
|
||||
if (!isOK)
|
||||
if (!data)
|
||||
m_IsOk = false;
|
||||
|
||||
if (m_RealOutStream)
|
||||
{
|
||||
UInt32 processedSizeLocal = 0;
|
||||
res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);
|
||||
// 18.01 : we don't want ZEROs instead of missing data
|
||||
if (data)
|
||||
res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);
|
||||
else
|
||||
processedSizeLocal = numBytesToWrite;
|
||||
numBytesToWrite = processedSizeLocal;
|
||||
}
|
||||
|
||||
if (TempBufMode && TempBuf)
|
||||
memcpy(TempBuf + (m_PosInFolder - m_BufStartFolderOffset), data, numBytesToWrite);
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
memcpy(TempBuf + TempBufWritten, data, numBytesToWrite);
|
||||
TempBufWritten += numBytesToWrite;
|
||||
}
|
||||
}
|
||||
}
|
||||
realProcessed += numBytesToWrite;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
if (data)
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
size -= numBytesToWrite;
|
||||
m_RemainFileSize -= numBytesToWrite;
|
||||
m_PosInFolder += numBytesToWrite;
|
||||
@@ -773,7 +786,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
m_FileIsOpen = true;
|
||||
m_CurrentIndex++;
|
||||
if (result == S_OK && m_RealOutStream && TempBuf)
|
||||
result = WriteStream(m_RealOutStream, TempBuf, (size_t)(m_PosInFolder - m_BufStartFolderOffset));
|
||||
result = WriteStream(m_RealOutStream, TempBuf, TempBufWritten);
|
||||
|
||||
if (!TempBuf && TempBufMode && m_RealOutStream)
|
||||
{
|
||||
@@ -822,7 +835,8 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
realProcessed += numBytesToWrite;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
if (data)
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
size -= numBytesToWrite;
|
||||
m_PosInFolder += numBytesToWrite;
|
||||
}
|
||||
@@ -843,12 +857,6 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Write2(data, size, processedSize, true);
|
||||
}
|
||||
|
||||
|
||||
HRESULT CFolderOutStream::FlushCorrupted(unsigned folderIndex)
|
||||
{
|
||||
if (!NeedMoreWrite())
|
||||
@@ -862,19 +870,16 @@ HRESULT CFolderOutStream::FlushCorrupted(unsigned folderIndex)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
const unsigned kBufSize = (1 << 12);
|
||||
Byte buf[kBufSize];
|
||||
for (unsigned i = 0; i < kBufSize; i++)
|
||||
buf[i] = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!NeedMoreWrite())
|
||||
return S_OK;
|
||||
UInt64 remain = GetRemain();
|
||||
UInt32 size = (remain < kBufSize ? (UInt32)remain : (UInt32)kBufSize);
|
||||
UInt32 size = (UInt32)1 << 20;
|
||||
if (size > remain)
|
||||
size = (UInt32)remain;
|
||||
UInt32 processedSizeLocal = 0;
|
||||
RINOK(Write2(buf, size, &processedSizeLocal, false));
|
||||
RINOK(Write(NULL, size, &processedSizeLocal));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -219,6 +219,7 @@ class CHandler:
|
||||
bool _masterCrcError;
|
||||
bool _headersError;
|
||||
|
||||
UInt32 _dataStartOffset;
|
||||
UInt64 _startPos;
|
||||
UInt64 _phySize;
|
||||
|
||||
@@ -333,6 +334,7 @@ static const Byte kProps[] =
|
||||
kpidCRC,
|
||||
kpidComment,
|
||||
kpidMethod
|
||||
// kpidOffset
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
@@ -631,17 +633,40 @@ bool CHandler::ParseBlob(const CByteBuffer &data)
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream)
|
||||
{
|
||||
/*
|
||||
- usual dmg contains Koly Header at the end:
|
||||
- rare case dmg contains Koly Header at the start.
|
||||
*/
|
||||
|
||||
_dataStartOffset = 0;
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPos));
|
||||
|
||||
UInt64 fileSize = 0;
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));
|
||||
RINOK(stream->Seek(_startPos, STREAM_SEEK_SET, NULL));
|
||||
|
||||
Byte buf[HEADER_SIZE];
|
||||
RINOK(ReadStream_FALSE(stream, buf, HEADER_SIZE));
|
||||
|
||||
UInt64 headerPos;
|
||||
bool startKolyMode = false;
|
||||
|
||||
if (IsKoly(buf))
|
||||
{
|
||||
// it can be normal koly-at-the-end or koly-at-the-start
|
||||
headerPos = _startPos;
|
||||
if (_startPos <= (1 << 8))
|
||||
{
|
||||
// we want to support startKolyMode, even if there is
|
||||
// some data before dmg file, like 128 bytes MacBin header
|
||||
_dataStartOffset = HEADER_SIZE;
|
||||
startKolyMode = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &headerPos));
|
||||
// we check only koly-at-the-end
|
||||
headerPos = fileSize;
|
||||
if (headerPos < HEADER_SIZE)
|
||||
return S_FALSE;
|
||||
headerPos -= HEADER_SIZE;
|
||||
@@ -667,24 +692,35 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
// CChecksum dataForkChecksum;
|
||||
// dataForkChecksum.Parse(buf + 0x50);
|
||||
|
||||
_startPos = 0;
|
||||
|
||||
UInt64 top = 0;
|
||||
if (!dataForkPair.UpdateTop(headerPos, top)) return S_FALSE;
|
||||
if (!xmlPair.UpdateTop(headerPos, top)) return S_FALSE;
|
||||
if (!rsrcPair.UpdateTop(headerPos, top)) return S_FALSE;
|
||||
UInt64 limit = startKolyMode ? fileSize : headerPos;
|
||||
|
||||
if (!dataForkPair.UpdateTop(limit, top)) return S_FALSE;
|
||||
if (!xmlPair.UpdateTop(limit, top)) return S_FALSE;
|
||||
if (!rsrcPair.UpdateTop(limit, top)) return S_FALSE;
|
||||
|
||||
/* Some old dmg files contain garbage data in blobPair field.
|
||||
So we need to ignore such garbage case;
|
||||
And we still need to detect offset of start of archive for "parser" mode. */
|
||||
|
||||
bool useBlob = blobPair.UpdateTop(headerPos, top);
|
||||
bool useBlob = blobPair.UpdateTop(limit, top);
|
||||
|
||||
_startPos = 0;
|
||||
_phySize = headerPos + HEADER_SIZE;
|
||||
|
||||
if (top != headerPos)
|
||||
if (startKolyMode)
|
||||
_phySize = top;
|
||||
else
|
||||
{
|
||||
_phySize = headerPos + HEADER_SIZE;
|
||||
_startPos = 0;
|
||||
if (top != headerPos)
|
||||
{
|
||||
/*
|
||||
if expected absolute offset is not equal to real header offset,
|
||||
2 cases are possible:
|
||||
- additional (unknown) headers
|
||||
- archive with offset.
|
||||
So we try to read XML with absolute offset to select from these two ways.
|
||||
*/
|
||||
CForkPair xmlPair2 = xmlPair;
|
||||
const char *sz = "<?xml version";
|
||||
const unsigned len = (unsigned)strlen(sz);
|
||||
@@ -694,9 +730,11 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
if (ReadData(stream, xmlPair2, buf2) != S_OK
|
||||
|| memcmp(buf2, sz, len) != 0)
|
||||
{
|
||||
// if absolute offset is not OK, probably it's archive with offset
|
||||
_startPos = headerPos - top;
|
||||
_phySize = top + HEADER_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Byte reserved[0x78]
|
||||
@@ -1041,6 +1079,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
case kpidOffset:
|
||||
{
|
||||
prop = item.StartPos;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
case kpidMethod:
|
||||
{
|
||||
CMethods m;
|
||||
@@ -1384,7 +1430,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
break;
|
||||
}
|
||||
|
||||
RINOK(_inStream->Seek(_startPos + item.StartPos + block.PackPos, STREAM_SEEK_SET, NULL));
|
||||
RINOK(_inStream->Seek(_startPos + _dataStartOffset + item.StartPos + block.PackPos, STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(block.PackSize);
|
||||
bool realMethod = true;
|
||||
outStreamSpec->Init(block.UnpSize);
|
||||
@@ -1781,7 +1827,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
|
||||
spec->Stream = _inStream;
|
||||
spec->Size = spec->File->Size;
|
||||
RINOK(spec->InitAndSeek(_startPos));
|
||||
RINOK(spec->InitAndSeek(_startPos + _dataStartOffset));
|
||||
*stream = specStream.Detach();
|
||||
return S_OK;
|
||||
|
||||
|
||||
@@ -567,6 +567,7 @@ static const char * const g_Machines[] =
|
||||
|
||||
static const CUInt32PCharPair g_MachinePairs[] =
|
||||
{
|
||||
{ 243, "RISC-V" },
|
||||
{ 47787, "Xilinx MicroBlaze" }
|
||||
// { 0x9026, "Alpha" }
|
||||
};
|
||||
|
||||
@@ -317,11 +317,15 @@ public:
|
||||
// bool CaseSensetive;
|
||||
UString ResFileName;
|
||||
|
||||
UInt64 SpecOffset;
|
||||
UInt64 PhySize;
|
||||
UInt64 PhySize2;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
SpecOffset = 0;
|
||||
PhySize = 0;
|
||||
PhySize2 = 0;
|
||||
HeadersError = false;
|
||||
ThereAreAltStreams = false;
|
||||
// CaseSensetive = false;
|
||||
@@ -444,7 +448,7 @@ HRESULT CDatabase::ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inSt
|
||||
e.NumBlocks > fork.NumBlocks - curBlock ||
|
||||
e.NumBlocks > Header.NumBlocks - e.Pos)
|
||||
return S_FALSE;
|
||||
RINOK(inStream->Seek((UInt64)e.Pos << Header.BlockSizeLog, STREAM_SEEK_SET, NULL));
|
||||
RINOK(inStream->Seek(SpecOffset + ((UInt64)e.Pos << Header.BlockSizeLog), STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadStream_FALSE(inStream,
|
||||
(Byte *)buf + ((size_t)curBlock << Header.BlockSizeLog),
|
||||
(size_t)e.NumBlocks << Header.BlockSizeLog));
|
||||
@@ -1154,13 +1158,36 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
|
||||
}
|
||||
|
||||
static const unsigned kHeaderPadSize = (1 << 10);
|
||||
static const unsigned kMainHeaderSize = 512;
|
||||
static const unsigned kHfsHeaderSize = kHeaderPadSize + kMainHeaderSize;
|
||||
|
||||
API_FUNC_static_IsArc IsArc_HFS(const Byte *p, size_t size)
|
||||
{
|
||||
if (size < kHfsHeaderSize)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
p += kHeaderPadSize;
|
||||
if (p[0] == 'B' && p[1] == 'D')
|
||||
{
|
||||
if (p[0x7C] != 'H' || p[0x7C + 1] != '+')
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p[0] != 'H' || (p[1] != '+' && p[1] != 'X'))
|
||||
return k_IsArc_Res_NO;
|
||||
UInt32 version = Get16(p + 2);
|
||||
if (version < 4 || version > 5)
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
return k_IsArc_Res_YES;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
|
||||
{
|
||||
Clear();
|
||||
static const unsigned kHeaderSize = kHeaderPadSize + 512;
|
||||
Byte buf[kHeaderSize];
|
||||
RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize));
|
||||
Byte buf[kHfsHeaderSize];
|
||||
RINOK(ReadStream_FALSE(inStream, buf, kHfsHeaderSize));
|
||||
{
|
||||
for (unsigned i = 0; i < kHeaderPadSize; i++)
|
||||
if (buf[i] != 0)
|
||||
@@ -1171,6 +1198,67 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
|
||||
|
||||
h.Header[0] = p[0];
|
||||
h.Header[1] = p[1];
|
||||
|
||||
if (p[0] == 'B' && p[1] == 'D')
|
||||
{
|
||||
/*
|
||||
It's header for old HFS format.
|
||||
We don't support old HFS format, but we support
|
||||
special HFS volume that contains embedded HFS+ volume
|
||||
*/
|
||||
|
||||
if (p[0x7C] != 'H' || p[0x7C + 1] != '+')
|
||||
return S_FALSE;
|
||||
|
||||
/*
|
||||
h.CTime = Get32(p + 0x2);
|
||||
h.MTime = Get32(p + 0x6);
|
||||
|
||||
h.NumFiles = Get32(p + 0x54);
|
||||
h.NumFolders = Get32(p + 0x58);
|
||||
|
||||
if (h.NumFolders > ((UInt32)1 << 29) ||
|
||||
h.NumFiles > ((UInt32)1 << 30))
|
||||
return S_FALSE;
|
||||
if (progress)
|
||||
{
|
||||
UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1;
|
||||
RINOK(progress->SetTotal(&numFiles, NULL));
|
||||
}
|
||||
h.NumFreeBlocks = Get16(p + 0x22);
|
||||
*/
|
||||
|
||||
UInt32 blockSize = Get32(p + 0x14);
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 9; ((UInt32)1 << i) != blockSize; i++)
|
||||
if (i == 31)
|
||||
return S_FALSE;
|
||||
h.BlockSizeLog = i;
|
||||
}
|
||||
|
||||
h.NumBlocks = Get16(p + 0x12);
|
||||
/*
|
||||
we suppose that it has the follwing layout
|
||||
{
|
||||
start block with header
|
||||
[h.NumBlocks]
|
||||
end block with header
|
||||
}
|
||||
*/
|
||||
PhySize2 = ((UInt64)h.NumBlocks + 2) << h.BlockSizeLog;
|
||||
|
||||
UInt32 startBlock = Get16(p + 0x7C + 2);
|
||||
UInt32 blockCount = Get16(p + 0x7C + 4);
|
||||
SpecOffset = (UInt64)(1 + startBlock) << h.BlockSizeLog;
|
||||
UInt64 phy = SpecOffset + ((UInt64)blockCount << h.BlockSizeLog);
|
||||
if (PhySize2 < phy)
|
||||
PhySize2 = phy;
|
||||
RINOK(inStream->Seek(SpecOffset, STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadStream_FALSE(inStream, buf, kHfsHeaderSize));
|
||||
}
|
||||
|
||||
if (p[0] != 'H' || (p[1] != '+' && p[1] != 'X'))
|
||||
return S_FALSE;
|
||||
h.Version = Get16(p + 2);
|
||||
@@ -1330,7 +1418,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
case kpidExtension: prop = Header.IsHfsX() ? "hfsx" : "hfs"; break;
|
||||
case kpidMethod: prop = Header.IsHfsX() ? "HFSX" : "HFS+"; break;
|
||||
case kpidPhySize: prop = PhySize; break;
|
||||
case kpidPhySize:
|
||||
{
|
||||
UInt64 v = SpecOffset + PhySize;
|
||||
if (v < PhySize2)
|
||||
v = PhySize2;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
case kpidClusterSize: prop = (UInt32)1 << Header.BlockSizeLog; break;
|
||||
case kpidFreeSpace: prop = (UInt64)Header.GetFreeSize(); break;
|
||||
case kpidMTime: HfsTimeToProp(Header.MTime, prop); break;
|
||||
@@ -1754,7 +1849,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if (fork.Size == pos)
|
||||
break;
|
||||
const CExtent &e = fork.Extents[extentIndex];
|
||||
RINOK(_stream->Seek((UInt64)e.Pos << Header.BlockSizeLog, STREAM_SEEK_SET, NULL));
|
||||
RINOK(_stream->Seek(SpecOffset + ((UInt64)e.Pos << Header.BlockSizeLog), STREAM_SEEK_SET, NULL));
|
||||
UInt64 extentRem = (UInt64)e.NumBlocks << Header.BlockSizeLog;
|
||||
while (extentRem != 0)
|
||||
{
|
||||
@@ -1865,6 +1960,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
}
|
||||
|
||||
static const Byte k_Signature[] = {
|
||||
2, 'B', 'D',
|
||||
4, 'H', '+', 0, 4,
|
||||
4, 'H', 'X', 0, 5 };
|
||||
|
||||
@@ -1873,6 +1969,6 @@ REGISTER_ARC_I(
|
||||
k_Signature,
|
||||
kHeaderPadSize,
|
||||
NArcInfoFlags::kMultiSignature,
|
||||
NULL)
|
||||
IsArc_HFS)
|
||||
|
||||
}}
|
||||
|
||||
@@ -2201,6 +2201,11 @@ bool CHeader::ParseCoff(const Byte *p)
|
||||
return false;
|
||||
if (OptHeaderSize != 0 && OptHeaderSize < k_OptHeader32_Size_MIN)
|
||||
return false;
|
||||
|
||||
// 18.04: we reduce false detections
|
||||
if (NumSections == 0 && OptHeaderSize == 0)
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(g_MachinePairs); i++)
|
||||
if (Machine == g_MachinePairs[i].Value)
|
||||
return true;
|
||||
|
||||
@@ -139,11 +139,10 @@ static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val)
|
||||
{
|
||||
*val = 0;
|
||||
|
||||
for (unsigned i = 0; i < maxSize;)
|
||||
for (unsigned i = 0; i < maxSize && i < 10;)
|
||||
{
|
||||
Byte b = p[i];
|
||||
if (i < 10)
|
||||
*val |= (UInt64)(b & 0x7F) << (7 * i);
|
||||
*val |= (UInt64)(b & 0x7F) << (7 * i);
|
||||
i++;
|
||||
if ((b & 0x80) == 0)
|
||||
return i;
|
||||
@@ -1363,7 +1362,9 @@ static const Byte kProps[] =
|
||||
kpidCharacts,
|
||||
kpidSymLink,
|
||||
kpidHardLink,
|
||||
kpidCopyLink
|
||||
kpidCopyLink,
|
||||
|
||||
kpidVolumeIndex
|
||||
};
|
||||
|
||||
|
||||
@@ -1794,6 +1795,18 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
|
||||
case kpidSplitBefore: prop = item.IsSplitBefore(); break;
|
||||
case kpidSplitAfter: prop = lastItem.IsSplitAfter(); break;
|
||||
|
||||
case kpidVolumeIndex:
|
||||
{
|
||||
if (item.VolIndex < _arcs.Size())
|
||||
{
|
||||
const CInArcInfo &arcInfo = _arcs[item.VolIndex].Info;
|
||||
if (arcInfo.IsVolume())
|
||||
prop = (UInt64)arcInfo.GetVolIndex();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidCRC:
|
||||
{
|
||||
const CItem *item2 = (lastItem.IsSplitAfter() ? &item : &lastItem);
|
||||
|
||||
@@ -180,7 +180,7 @@ struct CItem
|
||||
|
||||
AString Name;
|
||||
|
||||
int VolIndex;
|
||||
unsigned VolIndex;
|
||||
int NextItem;
|
||||
|
||||
UInt32 UnixMTime;
|
||||
|
||||
@@ -777,7 +777,9 @@ static const Byte kProps[] =
|
||||
kpidCRC,
|
||||
kpidHostOS,
|
||||
kpidMethod,
|
||||
kpidUnpackVer
|
||||
kpidUnpackVer,
|
||||
|
||||
kpidVolumeIndex
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
@@ -995,6 +997,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidCommented: prop = item.IsCommented(); break;
|
||||
case kpidSplitBefore: prop = item.IsSplitBefore(); break;
|
||||
case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter(); break;
|
||||
|
||||
case kpidVolumeIndex:
|
||||
if (_arcInfo.Is_VolNumber_Defined())
|
||||
prop = (UInt32)(_arcInfo.VolNumber + refItem.VolumeIndex);
|
||||
break;
|
||||
|
||||
case kpidCRC:
|
||||
{
|
||||
prop = ((lastItem.IsSplitAfter()) ? item.FileCRC : lastItem.FileCRC);
|
||||
|
||||
@@ -26,7 +26,7 @@ struct CInArcInfo
|
||||
UInt32 DataCRC;
|
||||
bool EndOfArchive_was_Read;
|
||||
|
||||
CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false) {}
|
||||
CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false), VolNumber(0) {}
|
||||
|
||||
UInt64 GetPhySize() const { return EndPos - StartPos; }
|
||||
|
||||
|
||||
@@ -94,7 +94,9 @@ static bool ParseInt64(const char *p, Int64 &val)
|
||||
|
||||
static bool ParseInt64_MTime(const char *p, Int64 &val)
|
||||
{
|
||||
// rare case tar contains spaces instead of MTime
|
||||
// rare case tar : ZEROs in Docker-Windows TARs
|
||||
// rare case tar : spaces
|
||||
if (GetUi32(p) != 0)
|
||||
for (unsigned i = 0; i < 12; i++)
|
||||
if (p[i] != ' ')
|
||||
return ParseInt64(p, val);
|
||||
|
||||
@@ -1993,6 +1993,13 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
|
||||
}
|
||||
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
|
||||
{
|
||||
/* possible cases:
|
||||
- exe with zip inside
|
||||
- sfx: a.exe, a.z02, a.z03,... , a.zip
|
||||
a.exe is start volume.
|
||||
- zip renamed to exe
|
||||
*/
|
||||
|
||||
StartIsExe = true;
|
||||
BaseName = name;
|
||||
StartVolIndex = 0;
|
||||
@@ -2000,7 +2007,22 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
|
||||
We can open arc.zip, if it was requesed to open arc.exe.
|
||||
But it's possible that arc.exe and arc.zip are not parts of same archive.
|
||||
So we can disable such operation */
|
||||
return S_FALSE; // don't open arc.zip instead of arc.exe
|
||||
|
||||
// 18.04: we still want to open zip renamed to exe.
|
||||
/*
|
||||
{
|
||||
UString volName = name;
|
||||
volName += IsUpperCase ? "Z01" : "z01";
|
||||
{
|
||||
CMyComPtr<IInStream> stream;
|
||||
HRESULT res2 = volCallback->GetStream(volName, &stream);
|
||||
if (res2 == S_OK)
|
||||
DisableVolsSearch = true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
DisableVolsSearch = true;
|
||||
return S_OK;
|
||||
}
|
||||
else if (ext[0] == 'z' || ext[0] == 'Z')
|
||||
{
|
||||
@@ -2040,6 +2062,9 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
|
||||
HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback,
|
||||
unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols)
|
||||
{
|
||||
if (Vols.DisableVolsSearch)
|
||||
return S_OK;
|
||||
|
||||
numMissingVols = 0;
|
||||
|
||||
for (unsigned i = start;; i++)
|
||||
@@ -2090,6 +2115,8 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback,
|
||||
}
|
||||
if (res == S_FALSE || !stream)
|
||||
{
|
||||
if (i == 1 && Vols.StartIsExe)
|
||||
return S_OK;
|
||||
if (Vols.MissingName.IsEmpty())
|
||||
Vols.MissingName = volName;
|
||||
numMissingVols++;
|
||||
|
||||
@@ -162,6 +162,7 @@ struct CVols
|
||||
|
||||
bool NeedSeek;
|
||||
|
||||
bool DisableVolsSearch;
|
||||
bool StartIsExe; // is .exe
|
||||
bool StartIsZ; // is .zip or .zNN
|
||||
bool StartIsZip; // is .zip
|
||||
@@ -201,6 +202,7 @@ struct CVols
|
||||
StreamIndex = -1;
|
||||
NeedSeek = false;
|
||||
|
||||
DisableVolsSearch = false;
|
||||
StartIsExe = false;
|
||||
StartIsZ = false;
|
||||
StartIsZip = false;
|
||||
|
||||
Reference in New Issue
Block a user