Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2015-10-18 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:56 +0300
commita663a6deb7a150f935fac7efdbf4d53d27369594 (patch)
treed1be306b33dd96050206da5774fff7bd9083ddfa
parent6543c280208393fa32cb0094f770d14c1cfb13b2 (diff)
15.0915.09
-rw-r--r--C/7zVersion.h8
-rw-r--r--C/LzFind.c22
-rw-r--r--C/LzFind.h10
-rw-r--r--C/LzFindMt.c19
-rw-r--r--C/Lzma2Enc.c18
-rw-r--r--C/LzmaEnc.c55
-rw-r--r--C/MtCoder.c4
-rw-r--r--CPP/7zip/Archive/ApmHandler.cpp10
-rw-r--r--CPP/7zip/Archive/Chm/ChmHandler.cpp42
-rw-r--r--CPP/7zip/Archive/Chm/ChmIn.cpp15
-rw-r--r--CPP/7zip/Archive/Chm/ChmIn.h14
-rw-r--r--CPP/7zip/Archive/ComHandler.cpp4
-rw-r--r--CPP/7zip/Archive/ExtHandler.cpp476
-rw-r--r--CPP/7zip/Archive/FatHandler.cpp24
-rw-r--r--CPP/7zip/Archive/GptHandler.cpp11
-rw-r--r--CPP/7zip/Archive/HandlerCont.cpp56
-rw-r--r--CPP/7zip/Archive/HandlerCont.h27
-rw-r--r--CPP/7zip/Archive/Iso/IsoHandler.cpp8
-rw-r--r--CPP/7zip/Archive/Iso/IsoIn.cpp8
-rw-r--r--CPP/7zip/Archive/Iso/IsoIn.h8
-rw-r--r--CPP/7zip/Archive/MbrHandler.cpp11
-rw-r--r--CPP/7zip/Archive/MubHandler.cpp11
-rw-r--r--CPP/7zip/Archive/NtfsHandler.cpp10
-rw-r--r--CPP/7zip/Archive/RpmHandler.cpp9
-rw-r--r--CPP/7zip/Archive/Udf/UdfIn.cpp2
-rw-r--r--CPP/7zip/Archive/Udf/UdfIn.h6
-rw-r--r--CPP/7zip/Archive/VmdkHandler.cpp1034
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.cpp4
-rw-r--r--CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp17
-rw-r--r--CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp8
-rw-r--r--CPP/7zip/Common/LimitedStreams.cpp22
-rw-r--r--CPP/7zip/Common/LimitedStreams.h6
-rw-r--r--CPP/7zip/Common/MethodProps.cpp50
-rw-r--r--CPP/7zip/Compress/Lzma2Encoder.cpp15
-rw-r--r--CPP/7zip/UI/Client7z/Client7z.cpp15
-rw-r--r--CPP/7zip/UI/Console/Main.cpp30
-rw-r--r--CPP/7zip/UI/FileManager/PanelItemOpen.cpp52
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.cpp34
-rw-r--r--CPP/Windows/PropVariant.cpp3
-rw-r--r--DOC/7zip.inf4
-rw-r--r--DOC/7zip.nsi2
-rw-r--r--DOC/7zip.wxs2
-rw-r--r--DOC/readme.txt2
-rw-r--r--DOC/src-history.txt14
44 files changed, 1648 insertions, 554 deletions
diff --git a/C/7zVersion.h b/C/7zVersion.h
index 87f6cff8..7e98b1c0 100644
--- a/C/7zVersion.h
+++ b/C/7zVersion.h
@@ -1,9 +1,9 @@
#define MY_VER_MAJOR 15
-#define MY_VER_MINOR 8
+#define MY_VER_MINOR 9
#define MY_VER_BUILD 0
-#define MY_VERSION_NUMBERS "15.08"
-#define MY_VERSION "15.08 beta"
-#define MY_DATE "2015-10-01"
+#define MY_VERSION_NUMBERS "15.09"
+#define MY_VERSION "15.09 beta"
+#define MY_DATE "2015-10-16"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"
diff --git a/C/LzFind.c b/C/LzFind.c
index fbb6cdb2..2d05fa39 100644
--- a/C/LzFind.c
+++ b/C/LzFind.c
@@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms
-2015-05-15 : Igor Pavlov : Public domain */
+2015-10-15 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -11,7 +11,7 @@
#define kEmptyHashValue 0
#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
-#define kNormalizeMask (~(kNormalizeStepMin - 1))
+#define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))
#define kMaxHistorySize ((UInt32)7 << 29)
#define kStartMaxLen 3
@@ -60,9 +60,11 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
if (p->streamEndWasReached || p->result != SZ_OK)
return;
+ /* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */
+
if (p->directInput)
{
- UInt32 curSize = 0xFFFFFFFF - p->streamPos;
+ UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos);
if (curSize > p->directInputRem)
curSize = (UInt32)p->directInputRem;
p->directInputRem -= curSize;
@@ -97,7 +99,7 @@ void MatchFinder_MoveBlock(CMatchFinder *p)
{
memmove(p->bufferBase,
p->buffer - p->keepSizeBefore,
- (size_t)(p->streamPos - p->pos + p->keepSizeBefore));
+ (size_t)(p->streamPos - p->pos) + p->keepSizeBefore);
p->buffer = p->bufferBase + p->keepSizeBefore;
}
@@ -290,7 +292,7 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
p->posLimit = p->pos + limit;
}
-void MatchFinder_Init(CMatchFinder *p)
+void MatchFinder_Init_2(CMatchFinder *p, int readData)
{
UInt32 i;
UInt32 *hash = p->hash;
@@ -303,10 +305,18 @@ void MatchFinder_Init(CMatchFinder *p)
p->pos = p->streamPos = p->cyclicBufferSize;
p->result = SZ_OK;
p->streamEndWasReached = 0;
- MatchFinder_ReadBlock(p);
+
+ if (readData)
+ MatchFinder_ReadBlock(p);
+
MatchFinder_SetLimits(p);
}
+void MatchFinder_Init(CMatchFinder *p)
+{
+ MatchFinder_Init_2(p, True);
+}
+
static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
{
return (p->pos - p->historySize - 1) & kNormalizeMask;
diff --git a/C/LzFind.h b/C/LzFind.h
index 2c094877..d119944f 100644
--- a/C/LzFind.h
+++ b/C/LzFind.h
@@ -1,5 +1,5 @@
/* LzFind.h -- Match finder for LZ algorithms
-2015-05-01 : Igor Pavlov : Public domain */
+2015-10-15 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_H
#define __LZ_FIND_H
@@ -53,6 +53,11 @@ typedef struct _CMatchFinder
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
+#define Inline_MatchFinder_IsFinishedOK(p) \
+ ((p)->streamEndWasReached \
+ && (p)->streamPos == (p)->pos \
+ && (!(p)->directInput || (p)->directInputRem == 0))
+
int MatchFinder_NeedMove(CMatchFinder *p);
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
void MatchFinder_MoveBlock(CMatchFinder *p);
@@ -98,9 +103,12 @@ typedef struct _IMatchFinder
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
+void MatchFinder_Init_2(CMatchFinder *p, int readData);
void MatchFinder_Init(CMatchFinder *p);
+
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
diff --git a/C/LzFindMt.c b/C/LzFindMt.c
index 2b7c1576..a4ffa5ef 100644
--- a/C/LzFindMt.c
+++ b/C/LzFindMt.c
@@ -1,5 +1,5 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
-2015-05-03 : Igor Pavlov : Public domain */
+2015-10-15 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -173,12 +173,12 @@ static void HashThreadFunc(CMatchFinderMt *mt)
CriticalSection_Enter(&mt->btSync.cs);
CriticalSection_Enter(&mt->hashSync.cs);
{
- const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);
- const Byte *afterPtr;
+ const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf);
+ ptrdiff_t offset;
MatchFinder_MoveBlock(mf);
- afterPtr = MatchFinder_GetPointerToCurrentPos(mf);
- mt->pointerToCurPos -= beforePtr - afterPtr;
- mt->buffer -= beforePtr - afterPtr;
+ offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf);
+ mt->pointerToCurPos -= offset;
+ mt->buffer -= offset;
}
CriticalSection_Leave(&mt->btSync.cs);
CriticalSection_Leave(&mt->hashSync.cs);
@@ -501,8 +501,11 @@ void MatchFinderMt_Init(CMatchFinderMt *p)
CMatchFinder *mf = p->MatchFinder;
p->btBufPos = p->btBufPosLimit = 0;
p->hashBufPos = p->hashBufPosLimit = 0;
- MatchFinder_Init(mf);
- p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
+
+ /* Init without data reading. We don't want to read data in this thread */
+ MatchFinder_Init_2(mf, False);
+
+ p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf);
p->btNumAvailBytes = 0;
p->lzPos = p->historySize + 1;
diff --git a/C/Lzma2Enc.c b/C/Lzma2Enc.c
index 7a0fd7d3..1b77a2bb 100644
--- a/C/Lzma2Enc.c
+++ b/C/Lzma2Enc.c
@@ -1,5 +1,5 @@
/* Lzma2Enc.c -- LZMA2 Encoder
-2015-09-16 : Igor Pavlov : Public domain */
+2015-10-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -479,7 +479,7 @@ SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
for (i = 0; i < p->props.numBlockThreads; i++)
{
- CLzma2EncInt *t = &p->coders[i];
+ CLzma2EncInt *t = &p->coders[(unsigned)i];
if (!t->enc)
{
t->enc = LzmaEnc_Create(p->alloc);
@@ -489,11 +489,7 @@ SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
}
#ifndef _7ZIP_ST
- if (p->props.numBlockThreads <= 1)
- #endif
- return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
-
- #ifndef _7ZIP_ST
+ if (p->props.numBlockThreads > 1)
{
CMtCallbackImp mtCallback;
@@ -508,9 +504,17 @@ SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
p->mtCoder.blockSize = p->props.blockSize;
p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;
+ if (p->mtCoder.destBlockSize < p->props.blockSize)
+ {
+ p->mtCoder.destBlockSize = (size_t)0 - 1;
+ if (p->mtCoder.destBlockSize < p->props.blockSize)
+ return SZ_ERROR_FAIL;
+ }
p->mtCoder.numThreads = p->props.numBlockThreads;
return MtCoder_Code(&p->mtCoder);
}
#endif
+
+ return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
}
diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c
index ea214850..8e8f255b 100644
--- a/C/LzmaEnc.c
+++ b/C/LzmaEnc.c
@@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder
-2015-05-15 Igor Pavlov : Public domain */
+2015-10-15 Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -505,8 +505,8 @@ static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11,
static void RangeEnc_Construct(CRangeEnc *p)
{
- p->outStream = 0;
- p->bufBase = 0;
+ p->outStream = NULL;
+ p->bufBase = NULL;
}
#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
@@ -514,10 +514,10 @@ static void RangeEnc_Construct(CRangeEnc *p)
#define RC_BUF_SIZE (1 << 16)
static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
{
- if (p->bufBase == 0)
+ if (!p->bufBase)
{
p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
- if (p->bufBase == 0)
+ if (!p->bufBase)
return 0;
p->bufLim = p->bufBase + RC_BUF_SIZE;
}
@@ -1749,15 +1749,15 @@ void LzmaEnc_Construct(CLzmaEnc *p)
#endif
LzmaEnc_InitPriceTables(p->ProbPrices);
- p->litProbs = 0;
- p->saveState.litProbs = 0;
+ p->litProbs = NULL;
+ p->saveState.litProbs = NULL;
}
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
{
void *p;
p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
- if (p != 0)
+ if (p)
LzmaEnc_Construct((CLzmaEnc *)p);
return p;
}
@@ -1766,8 +1766,8 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->litProbs);
alloc->Free(alloc, p->saveState.litProbs);
- p->litProbs = 0;
- p->saveState.litProbs = 0;
+ p->litProbs = NULL;
+ p->saveState.litProbs = NULL;
}
void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
@@ -1963,12 +1963,12 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
{
unsigned lclp = p->lc + p->lp;
- if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
+ if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
{
LzmaEnc_FreeLits(p, alloc);
p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
- if (p->litProbs == 0 || p->saveState.litProbs == 0)
+ if (!p->litProbs || !p->saveState.litProbs)
{
LzmaEnc_FreeLits(p, alloc);
return SZ_ERROR_MEM;
@@ -2140,6 +2140,7 @@ void LzmaEnc_Finish(CLzmaEncHandle pp)
#endif
}
+
typedef struct
{
ISeqOutStream funcTable;
@@ -2169,12 +2170,14 @@ UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
}
+
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
{
const CLzmaEnc *p = (CLzmaEnc *)pp;
return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
}
+
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
{
@@ -2209,6 +2212,7 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
return res;
}
+
static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
{
SRes res = SZ_OK;
@@ -2222,9 +2226,9 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
for (;;)
{
res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
- if (res != SZ_OK || p->finished != 0)
+ if (res != SZ_OK || p->finished)
break;
- if (progress != 0)
+ if (progress)
{
res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
if (res != SZ_OK)
@@ -2234,10 +2238,19 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
}
}
}
+
LzmaEnc_Finish(p);
+
+ /*
+ if (res == S_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))
+ res = SZ_ERROR_FAIL;
+ }
+ */
+
return res;
}
+
SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
ISzAlloc *alloc, ISzAlloc *allocBig)
{
@@ -2245,6 +2258,7 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i
return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
}
+
SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
{
CLzmaEnc *p = (CLzmaEnc *)pp;
@@ -2272,6 +2286,7 @@ SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
return SZ_OK;
}
+
SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
{
@@ -2280,19 +2295,22 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
CSeqOutStreamBuf outStream;
- LzmaEnc_SetInputBuf(p, src, srcLen);
-
outStream.funcTable.Write = MyWrite;
outStream.data = dest;
outStream.rem = *destLen;
outStream.overflow = False;
p->writeEndMark = writeEndMark;
-
p->rc.outStream = &outStream.funcTable;
+
res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
+
if (res == SZ_OK)
+ {
res = LzmaEnc_Encode2(p, progress);
+ if (res == SZ_OK && p->nowPos64 != srcLen)
+ res = SZ_ERROR_FAIL;
+ }
*destLen -= outStream.rem;
if (outStream.overflow)
@@ -2300,13 +2318,14 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
return res;
}
+
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
{
CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
SRes res;
- if (p == 0)
+ if (!p)
return SZ_ERROR_MEM;
res = LzmaEnc_SetProps(p, props);
diff --git a/C/MtCoder.c b/C/MtCoder.c
index dc5116c0..8d9731d0 100644
--- a/C/MtCoder.c
+++ b/C/MtCoder.c
@@ -1,10 +1,8 @@
/* MtCoder.c -- Multi-thread Coder
-2015-09-28 : Igor Pavlov : Public domain */
+2015-10-13 : Igor Pavlov : Public domain */
#include "Precomp.h"
-#include <stdio.h>
-
#include "MtCoder.h"
void LoopThread_Construct(CLoopThread *p)
diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp
index fcd686aa..51719d53 100644
--- a/CPP/7zip/Archive/ApmHandler.cpp
+++ b/CPP/7zip/Archive/ApmHandler.cpp
@@ -83,8 +83,14 @@ class CHandler: public CHandlerCont
HRESULT ReadTables(IInStream *stream);
UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; }
- virtual UInt64 GetItemPos(UInt32 index) const { return BlocksToBytes(_items[index].StartBlock); }
- virtual UInt64 GetItemSize(UInt32 index) const { return BlocksToBytes(_items[index].NumBlocks); }
+ virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const
+ {
+ const CItem &item = _items[index];
+ pos = BlocksToBytes(item.StartBlock);
+ size = BlocksToBytes(item.NumBlocks);
+ return NExtract::NOperationResult::kOK;
+ }
+
public:
INTERFACE_IInArchive_Cont(;)
};
diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp
index 3e29fd00..2a72e8e9 100644
--- a/CPP/7zip/Archive/Chm/ChmHandler.cpp
+++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp
@@ -101,6 +101,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
+
if (m_Database.NewFormat)
{
switch (propID)
@@ -112,12 +113,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop.Detach(value);
return S_OK;
}
- int entryIndex;
+
+ unsigned entryIndex;
if (m_Database.LowLevel)
entryIndex = index;
else
entryIndex = m_Database.Indices[index];
+
const CItem &item = m_Database.Items[entryIndex];
+
switch (propID)
{
case kpidPath:
@@ -161,6 +165,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
#endif
}
+
prop.Detach(value);
return S_OK;
COM_TRY_END
@@ -244,9 +249,9 @@ public:
UInt64 m_PosInFolder;
UInt64 m_PosInSection;
const CRecordVector<bool> *m_ExtractStatuses;
- int m_StartIndex;
- int m_CurrentIndex;
- int m_NumFiles;
+ unsigned m_StartIndex;
+ unsigned m_CurrentIndex;
+ unsigned m_NumFiles;
private:
const CFilesDatabase *m_Database;
@@ -298,7 +303,7 @@ HRESULT CChmFolderOutStream::WriteEmptyFiles()
{
if (m_FileIsOpen)
return S_OK;
- for (;m_CurrentIndex < m_NumFiles; m_CurrentIndex++)
+ for (; m_CurrentIndex < m_NumFiles; m_CurrentIndex++)
{
UInt64 fileSize = m_Database->GetFileSize(m_StartIndex + m_CurrentIndex);
if (fileSize != 0)
@@ -368,7 +373,7 @@ HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *proce
// return E_FAIL;
}
- int fullIndex = m_StartIndex + m_CurrentIndex;
+ unsigned fullIndex = m_StartIndex + m_CurrentIndex;
m_RemainFileSize = m_Database->GetFileSize(fullIndex);
UInt64 fileOffset = m_Database->GetFileOffset(fullIndex);
if (fileOffset < m_PosInSection)
@@ -408,7 +413,7 @@ HRESULT CChmFolderOutStream::FlushCorrupted(UInt64 maxSize)
{
const UInt32 kBufferSize = (1 << 10);
Byte buffer[kBufferSize];
- for (int i = 0; i < kBufferSize; i++)
+ for (unsigned i = 0; i < kBufferSize; i++)
buffer[i] = 0;
if (maxSize > m_FolderSize)
maxSize = m_FolderSize;
@@ -531,9 +536,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
for (i = 0; i < numItems; i++)
{
UInt32 index = allFilesMode ? i : indices[i];
- int entryIndex = m_Database.Indices[index];
- const CItem &item = m_Database.Items[entryIndex];
- UInt64 sectionIndex = item.Section;
+ const CItem &item = m_Database.Items[m_Database.Indices[index]];
+ const UInt64 sectionIndex = item.Section;
if (item.IsDir() || item.Size == 0)
continue;
if (sectionIndex == 0)
@@ -567,14 +571,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CByteBuffer packBuf;
- for (i = 0; i < numItems;)
+ for (i = 0;;)
{
RINOK(extractCallback->SetCompleted(&currentTotalSize));
+
+ if (i >= numItems)
+ break;
+
UInt32 index = allFilesMode ? i : indices[i];
i++;
- int entryIndex = m_Database.Indices[index];
- const CItem &item = m_Database.Items[entryIndex];
- UInt64 sectionIndex = item.Section;
+ const CItem &item = m_Database.Items[m_Database.Indices[index]];
+ const UInt64 sectionIndex = item.Section;
Int32 askMode= testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
@@ -645,7 +652,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 folderIndex = m_Database.GetFolder(index);
- UInt64 compressedPos = m_Database.ContentOffset + section.Offset;
+ const UInt64 compressedPos = m_Database.ContentOffset + section.Offset;
RINOK(lzxDecoderSpec->SetParams_and_Alloc(lzxInfo.GetNumDictBits()));
const CItem *lastItem = &item;
@@ -673,9 +680,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
for (; i < numItems; i++)
{
- UInt32 nextIndex = allFilesMode ? i : indices[i];
- int entryIndex = m_Database.Indices[nextIndex];
- const CItem &nextItem = m_Database.Items[entryIndex];
+ const UInt32 nextIndex = allFilesMode ? i : indices[i];
+ const CItem &nextItem = m_Database.Items[m_Database.Indices[nextIndex]];
if (nextItem.Section != sectionIndex)
break;
UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex);
diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp
index d7556b89..6bdf2af4 100644
--- a/CPP/7zip/Archive/Chm/ChmIn.cpp
+++ b/CPP/7zip/Archive/Chm/ChmIn.cpp
@@ -656,7 +656,7 @@ static AString GetSectionPrefix(const AString &name)
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
-static int CompareFiles(const int *p1, const int *p2, void *param)
+static int CompareFiles(const unsigned *p1, const unsigned *p2, void *param)
{
const CObjectVector<CItem> &items = *(const CObjectVector<CItem> *)param;
const CItem &item1 = items[*p1];
@@ -731,7 +731,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
RINOK(DecompressStream(inStream, database, kNameList));
/* UInt16 length = */ ReadUInt16();
UInt16 numSections = ReadUInt16();
- for (int i = 0; i < numSections; i++)
+ for (unsigned i = 0; i < numSections; i++)
{
CSectionInfo section;
UInt16 nameLen = ReadUInt16();
@@ -766,10 +766,10 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
RINOK(DecompressStream(inStream, database, transformPrefix + kTransformList));
if ((_chunkSize & 0xF) != 0)
return S_FALSE;
- int numGuids = (int)(_chunkSize / 0x10);
+ unsigned numGuids = (unsigned)(_chunkSize / 0x10);
if (numGuids < 1)
return S_FALSE;
- for (int i = 0; i < numGuids; i++)
+ for (unsigned i = 0; i < numGuids; i++)
{
CMethodInfo method;
ReadGUID(method.Guid);
@@ -803,14 +803,17 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
return S_FALSE;
{
- int n = GetLog(ReadUInt32());
+ // There is bug in VC6, if we use function call as parameter for inline function
+ UInt32 val32 = ReadUInt32();
+ int n = GetLog(val32);
if (n < 0 || n > 16)
return S_FALSE;
li.ResetIntervalBits = n;
}
{
- int n = GetLog(ReadUInt32());
+ UInt32 val32 = ReadUInt32();
+ int n = GetLog(val32);
if (n < 0 || n > 16)
return S_FALSE;
li.WindowSizeBits = n;
diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h
index dc5e8263..60852852 100644
--- a/CPP/7zip/Archive/Chm/ChmIn.h
+++ b/CPP/7zip/Archive/Chm/ChmIn.h
@@ -177,25 +177,25 @@ class CFilesDatabase: public CDatabase
{
public:
bool LowLevel;
- CRecordVector<int> Indices;
+ CUIntVector Indices;
CObjectVector<CSectionInfo> Sections;
- UInt64 GetFileSize(int fileIndex) const { return Items[Indices[fileIndex]].Size; }
- UInt64 GetFileOffset(int fileIndex) const { return Items[Indices[fileIndex]].Offset; }
+ UInt64 GetFileSize(unsigned fileIndex) const { return Items[Indices[fileIndex]].Size; }
+ UInt64 GetFileOffset(unsigned fileIndex) const { return Items[Indices[fileIndex]].Offset; }
- UInt64 GetFolder(int fileIndex) const
+ UInt64 GetFolder(unsigned fileIndex) const
{
const CItem &item = Items[Indices[fileIndex]];
- const CSectionInfo &section = Sections[(int)item.Section];
+ const CSectionInfo &section = Sections[(unsigned)item.Section];
if (section.IsLzx())
return section.Methods[0].LzxInfo.GetFolder(item.Offset);
return 0;
}
- UInt64 GetLastFolder(int fileIndex) const
+ UInt64 GetLastFolder(unsigned fileIndex) const
{
const CItem &item = Items[Indices[fileIndex]];
- const CSectionInfo &section = Sections[(int)item.Section];
+ const CSectionInfo &section = Sections[(unsigned)item.Section];
if (section.IsLzx())
return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1);
return 0;
diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp
index e24074a5..3a4834cd 100644
--- a/CPP/7zip/Archive/ComHandler.cpp
+++ b/CPP/7zip/Archive/ComHandler.cpp
@@ -433,9 +433,9 @@ HRESULT CDatabase::Open(IInStream *inStream)
SectorSizeBits = sectorSizeBits;
MiniSectorSizeBits = miniSectorSizeBits;
- if (sectorSizeBits > 28 ||
+ if (sectorSizeBits > 24 ||
sectorSizeBits < 7 ||
- miniSectorSizeBits > 28 ||
+ miniSectorSizeBits > 24 ||
miniSectorSizeBits < 2 ||
miniSectorSizeBits > sectorSizeBits)
return S_FALSE;
diff --git a/CPP/7zip/Archive/ExtHandler.cpp b/CPP/7zip/Archive/ExtHandler.cpp
index 6d8101f5..a9d0facb 100644
--- a/CPP/7zip/Archive/ExtHandler.cpp
+++ b/CPP/7zip/Archive/ExtHandler.cpp
@@ -4,6 +4,11 @@
// #define SHOW_DEBUG_INFO
+// #include <stdio.h>
+// #define PRF2(x) x
+
+#define PRF2(x)
+
#ifdef SHOW_DEBUG_INFO
#include <stdio.h>
#define PRF(x) x
@@ -23,7 +28,6 @@
#include "../../Windows/PropVariantUtils.h"
#include "../../Windows/TimeUtils.h"
-#include "../Common/LimitedStreams.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamObjects.h"
@@ -300,7 +304,7 @@ struct CHeader
// UInt64 NumBlocksSuper;
UInt64 NumFreeBlocks;
UInt32 NumFreeInodes;
- UInt32 FirstDataBlock;
+ // UInt32 FirstDataBlock;
UInt32 BlocksPerGroup;
UInt32 ClustersPerGroup;
@@ -349,6 +353,7 @@ struct CHeader
bool IsOldRev() const { return RevLevel == EXT4_GOOD_OLD_REV; }
UInt64 GetNumGroups() const { return (NumBlocks + BlocksPerGroup - 1) / BlocksPerGroup; }
+ UInt64 GetNumGroups2() const { return ((UInt64)NumInodes + InodesPerGroup - 1) / InodesPerGroup; }
bool IsThereFileType() const { return (FeatureIncompat & EXT4_FEATURE_INCOMPAT_FILETYPE) != 0; }
bool Is64Bit() const { return (FeatureIncompat & EXT4_FEATURE_INCOMPAT_64BIT) != 0; }
@@ -367,6 +372,15 @@ static int inline GetLog(UInt32 num)
return -1;
}
+static bool inline IsEmptyData(const Byte *data, unsigned size)
+{
+ for (unsigned i = 0; i < size; i++)
+ if (data[i] != 0)
+ return false;
+ return true;
+}
+
+
bool CHeader::Parse(const Byte *p)
{
if (GetUi16(p + 0x38) != 0xEF53)
@@ -375,21 +389,25 @@ bool CHeader::Parse(const Byte *p)
LE_32 (0x18, BlockBits);
LE_32 (0x1C, ClusterBits);
- if (ClusterBits != 0 && BlockBits != ClusterBits)
+ if (ClusterBits != 0 && BlockBits != ClusterBits)
return false;
- if (BlockBits > 16 - 10) return false;
+ if (BlockBits > 16 - 10)
+ return false;
BlockBits += 10;
- if (ClusterBits > 16) return false;
LE_32 (0x00, NumInodes);
LE_32 (0x04, NumBlocks);
// LE_32 (0x08, NumBlocksSuper);
LE_32 (0x0C, NumFreeBlocks);
LE_32 (0x10, NumFreeInodes);
- LE_32 (0x14, FirstDataBlock);
- if (FirstDataBlock != 0)
+ if (NumInodes < 2 || NumInodes <= NumFreeInodes)
+ return false;
+
+ UInt32 FirstDataBlock;
+ LE_32 (0x14, FirstDataBlock);
+ if (FirstDataBlock != (unsigned)(BlockBits == 10 ? 1 : 0))
return false;
LE_32 (0x20, BlocksPerGroup);
@@ -397,10 +415,18 @@ bool CHeader::Parse(const Byte *p)
if (BlocksPerGroup != ClustersPerGroup)
return false;
- if (BlocksPerGroup != ((UInt32)1 << (BlockBits + 3)))
+ if (BlocksPerGroup == 0)
return false;
+ if (BlocksPerGroup != ((UInt32)1 << (BlockBits + 3)))
+ {
+ // it's allowed in ext2
+ // return false;
+ }
LE_32 (0x28, InodesPerGroup);
+
+ if (InodesPerGroup < 1 || InodesPerGroup > NumInodes)
+ return false;
LE_32 (0x2C, MountTime);
LE_32 (0x30, WriteTime);
@@ -485,6 +511,9 @@ bool CHeader::Parse(const Byte *p)
if (NumFreeBlocks > NumBlocks)
return false;
+ if (GetNumGroups() != GetNumGroups2())
+ return false;
+
return true;
}
@@ -612,7 +641,7 @@ struct CExtTime
struct CNode
{
- Int32 ParentNode; // in _nodes[], -1 if not dir
+ Int32 ParentNode; // in _refs[], -1 if not dir
int ItemIndex; // in _items[]
int SymLinkIndex; // in _symLinks[]
int DirIndex; // in _dirs[]
@@ -621,7 +650,6 @@ struct CNode
UInt16 Uid;
UInt16 Gid;
// UInt16 Checksum;
- bool IsEmpty;
UInt64 FileSize;
CExtTime MTime;
@@ -662,6 +690,7 @@ bool CNode::Parse(const Byte *p, const CHeader &_h)
MTime.Extra = 0;
ATime.Extra = 0;
CTime.Extra = 0;
+ CTime.Val = 0;
// InodeChangeTime.Extra = 0;
// DTime.Extra = 0;
@@ -692,14 +721,21 @@ bool CNode::Parse(const Byte *p, const CHeader &_h)
FileSize |= ((UInt64)highSize << 32);
}
+ // UInt32 fragmentAddress;
// LE_32 (0x70, fragmentAddress);
// osd2
{
// Linux;
+ // ext2:
+ // Byte FragmentNumber = p[0x74];
+ // Byte FragmentSize = p[0x74 + 1];
+
+ // ext4:
UInt32 numBlocksHigh;
LE_16 (0x74, numBlocksHigh);
NumBlocks |= (UInt64)numBlocksHigh << 32;
+
HI_16 (0x74 + 4, Uid);
HI_16 (0x74 + 6, Gid);
/*
@@ -738,8 +774,8 @@ bool CNode::Parse(const Byte *p, const CHeader &_h)
struct CItem
{
- unsigned Node; // in _nodes[]
- int ParentNode; // in _nodes[]
+ unsigned Node; // in _refs[]
+ int ParentNode; // in _refs[]
int SymLinkItemIndex; // in _items[], if the Node contains SymLink to existing dir
Byte Type;
@@ -778,6 +814,7 @@ class CHandler:
public CMyUnknownImp
{
CObjectVector<CItem> _items;
+ CIntVector _refs;
CRecordVector<CNode> _nodes;
CObjectVector<CUIntVector> _dirs; // each CUIntVector contains indexes in _items[] only for dir items;
AStringVector _symLinks;
@@ -789,6 +826,7 @@ class CHandler:
UInt64 _phySize;
bool _isArc;
bool _headersError;
+ bool _headersWarning;
bool _linksError;
bool _isUTF;
@@ -831,14 +869,14 @@ class CHandler:
}
HRESULT SeekAndRead(IInStream *inStream, UInt64 block, Byte *data, size_t size);
- HRESULT ParseDir(const Byte *data, size_t size, unsigned nodeIndex);
+ HRESULT ParseDir(const Byte *data, size_t size, unsigned iNodeDir);
int FindTargetItem_for_SymLink(unsigned dirNode, const AString &path) const;
HRESULT FillFileBlocks2(UInt32 block, unsigned level, unsigned numBlocks, CRecordVector<UInt32> &blocks);
HRESULT FillFileBlocks(const Byte *p, unsigned numBlocks, CRecordVector<UInt32> &blocks);
HRESULT FillExtents(const Byte *p, size_t size, CRecordVector<CExtent> &extents, int parentDepth);
- HRESULT GetStream_Node(UInt32 nodeIndex, ISequentialInStream **stream);
+ HRESULT GetStream_Node(unsigned nodeIndex, ISequentialInStream **stream);
HRESULT ExtractNode(unsigned nodeIndex, CByteBuffer &data);
void ClearRefs();
@@ -860,13 +898,13 @@ public:
-HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
+HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned iNodeDir)
{
bool isThereSelfLink = false;
- PRF(printf("\n\n========= node = %5d size = %5d", nodeIndex, size));
+ PRF(printf("\n\n========= node = %5d size = %5d", (unsigned)iNodeDir, (unsigned)size));
- CNode &nodeDir = _nodes[nodeIndex];
+ CNode &nodeDir = _nodes[_refs[iNodeDir]];
nodeDir.DirIndex = _dirs.Size();
CUIntVector &dir = _dirs.AddNew();
int parentNode = -1;
@@ -891,7 +929,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
if (nameLen + 8 > recLen)
return S_FALSE;
- if (iNode >= _nodes.Size())
+ if (iNode >= _refs.Size())
return S_FALSE;
item.Clear();
@@ -901,7 +939,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
else if (type != 0)
return S_FALSE;
- item.ParentNode = nodeIndex;
+ item.ParentNode = iNodeDir;
item.Node = iNode;
item.Name.SetFrom_CalcLen((const char *)(p + 8), nameLen);
@@ -922,7 +960,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
return S_FALSE;
*/
- PRF(printf("\n EMPTY %6d %d %s", recLen, type, (const char *)item.Name));
+ PRF(printf("\n EMPTY %6d %d %s", (unsigned)recLen, (unsigned)type, (const char *)item.Name));
if (type == 0xDE)
{
// checksum
@@ -930,9 +968,10 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
continue;
}
- CNode &node = _nodes[iNode];
- if (node.IsEmpty)
+ int nodeIndex = _refs[iNode];
+ if (nodeIndex < 0)
return S_FALSE;
+ CNode &node = _nodes[nodeIndex];
if (_h.IsThereFileType() && type != 0)
{
@@ -944,7 +983,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
node.NumLinksCalced++;
- PRF(printf("\n%s %6d %s", item.IsDir() ? "DIR " : " ", item.Node, (const char *)item.Name));
+ PRF(printf("\n%s %6d %s", item.IsDir() ? "DIR " : " ", (unsigned)item.Node, (const char *)item.Name));
if (item.Name[0] == '.')
{
@@ -953,7 +992,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
if (isThereSelfLink)
return S_FALSE;
isThereSelfLink = true;
- if (nodeIndex != nodeIndex)
+ if (iNode != iNodeDir)
return S_FALSE;
continue;
}
@@ -964,7 +1003,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
return S_FALSE;
if (!node.IsDir())
return S_FALSE;
- if (iNode == nodeIndex && iNode != k_INODE_ROOT)
+ if (iNode == iNodeDir && iNode != k_INODE_ROOT)
return S_FALSE;
parentNode = iNode;
@@ -978,7 +1017,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
}
}
- if (iNode == nodeIndex)
+ if (iNode == iNodeDir)
return S_FALSE;
if (parentNode < 0)
@@ -987,8 +1026,8 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
if (node.IsDir())
{
if (node.ParentNode < 0)
- node.ParentNode = nodeIndex;
- else if ((unsigned)node.ParentNode != nodeIndex)
+ node.ParentNode = iNodeDir;
+ else if ((unsigned)node.ParentNode != iNodeDir)
return S_FALSE;
const unsigned itemIndex = _items.Size();
dir.Add(itemIndex);
@@ -1005,7 +1044,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
}
-int CHandler::FindTargetItem_for_SymLink(unsigned nodeIndex, const AString &path) const
+int CHandler::FindTargetItem_for_SymLink(unsigned iNode, const AString &path) const
{
unsigned pos = 0;
@@ -1014,8 +1053,8 @@ int CHandler::FindTargetItem_for_SymLink(unsigned nodeIndex, const AString &path
if (path[0] == '/')
{
- nodeIndex = k_INODE_ROOT;
- if (nodeIndex >= _nodes.Size())
+ iNode = k_INODE_ROOT;
+ if (iNode >= _refs.Size())
return -1;
pos = 1;
}
@@ -1024,7 +1063,7 @@ int CHandler::FindTargetItem_for_SymLink(unsigned nodeIndex, const AString &path
while (pos != path.Len())
{
- const CNode &node = _nodes[nodeIndex];
+ const CNode &node = _nodes[_refs[iNode]];
int slash = path.Find('/', pos);
if (slash < 0)
@@ -1046,9 +1085,9 @@ int CHandler::FindTargetItem_for_SymLink(unsigned nodeIndex, const AString &path
{
if (node.ParentNode < 0)
return -1;
- if (nodeIndex == k_INODE_ROOT)
+ if (iNode == k_INODE_ROOT)
return -1;
- nodeIndex = node.ParentNode;
+ iNode = node.ParentNode;
continue;
}
}
@@ -1065,13 +1104,13 @@ int CHandler::FindTargetItem_for_SymLink(unsigned nodeIndex, const AString &path
const CItem &item = _items[dir[i]];
if (item.Name == s)
{
- nodeIndex = item.Node;
+ iNode = item.Node;
break;
}
}
}
- return _nodes[nodeIndex].ItemIndex;
+ return _nodes[_refs[iNode]].ItemIndex;
}
@@ -1178,7 +1217,10 @@ HRESULT CHandler::Open2(IInStream *inStream)
UInt32 numReserveInodes = _h.NumInodes - _h.NumFreeInodes + 1;
// numReserveInodes = _h.NumInodes + 1;
if (numReserveInodes != 0)
+ {
_nodes.Reserve(numReserveInodes);
+ _refs.Reserve(numReserveInodes);
+ }
UInt32 numNodes = _h.InodesPerGroup;
if (numNodes > _h.NumInodes)
@@ -1195,6 +1237,8 @@ HRESULT CHandler::Open2(IInStream *inStream)
nodesMap.Alloc(blockSize);
unsigned globalNodeIndex = 0;
+ // unsigned numEmpty = 0;
+ unsigned numEmpty_in_Maps = 0;
FOR_VECTOR (gi, groups)
{
@@ -1203,40 +1247,40 @@ HRESULT CHandler::Open2(IInStream *inStream)
const CGroupDescriptor &gd = groups[gi];
- PRF(printf("\n\ng%6d block = %6x\n", gi, gd.InodeTable));
+ PRF(printf("\n\ng%6d block = %6x\n", gi, (unsigned)gd.InodeTable));
RINOK(SeekAndRead(inStream, gd.InodeBitmap, nodesMap, blockSize));
RINOK(SeekAndRead(inStream, gd.InodeTable, nodesData, nodesDataSize));
+
+ unsigned numEmpty_in_Map = 0;
for (size_t n = 0; n < numNodes && globalNodeIndex < _h.NumInodes; n++, globalNodeIndex++)
{
if ((nodesMap[n >> 3] & ((unsigned)1 << (n & 7))) == 0)
+ {
+ numEmpty_in_Map++;
continue;
+ }
const Byte *p = nodesData + (size_t)n * _h.InodeSize;
- unsigned j = 0;
- for (j = 0; j < _h.InodeSize; j++)
- if (p[j] != 0)
- break;
-
- if (j == _h.InodeSize)
+ if (IsEmptyData(p, _h.InodeSize))
{
- if (_nodes.Size() >= _h.FirstInode)
+ if (globalNodeIndex + 1 >= _h.FirstInode)
{
+ _headersError = true;
// return S_FALSE;
}
continue;
}
CNode node;
- node.IsEmpty = false;
PRF(printf("\nnode = %5d ", (unsigned)n));
if (!node.Parse(p, _h))
return S_FALSE;
- // PRF(printf("\n %6d", n));
+ // PRF(printf("\n %6d", (unsigned)n));
/*
SetUi32(p + 0x7C, 0)
SetUi32(p + 0x82, 0)
@@ -1249,19 +1293,36 @@ HRESULT CHandler::Open2(IInStream *inStream)
if (crc != node.Checksum) return S_FALSE;
*/
- while (_nodes.Size() < globalNodeIndex + 1)
+ while (_refs.Size() < globalNodeIndex + 1)
{
- CNode node2;
- node2.IsEmpty = true;
- _nodes.Add(node2);
+ // numEmpty++;
+ _refs.Add(-1);
}
- _nodes.Add(node);
+ _refs.Add(_nodes.Add(node));
+ }
+
+
+ numEmpty_in_Maps += numEmpty_in_Map;
+
+ if (numEmpty_in_Map != gd.NumFreeInodes)
+ {
+ _headersWarning = true;
+ // return S_FALSE;
}
}
- if (_nodes.Size() <= k_INODE_ROOT)
+ if (numEmpty_in_Maps != _h.NumFreeInodes)
+ {
+ // some ext2 examples has incorrect value in _h.NumFreeInodes.
+ // so we disable check;
+ _headersWarning = true;
+ }
+
+ if (_refs.Size() <= k_INODE_ROOT)
return S_FALSE;
+
+ // printf("\n numReserveInodes = %6d, _refs.Size() = %d, numEmpty = %7d\n", numReserveInodes, _refs.Size(), (unsigned)numEmpty);
}
}
@@ -1272,14 +1333,17 @@ HRESULT CHandler::Open2(IInStream *inStream)
CByteBuffer dataBuf;
- FOR_VECTOR (i, _nodes)
+ FOR_VECTOR (i, _refs)
{
+ int nodeIndex = _refs[i];
{
- const CNode &node = _nodes[i];
- if (node.IsEmpty || !node.IsDir())
+ if (nodeIndex < 0)
+ continue;
+ const CNode &node = _nodes[nodeIndex];
+ if (!node.IsDir())
continue;
}
- RINOK(ExtractNode(i, dataBuf));
+ RINOK(ExtractNode(nodeIndex, dataBuf));
if (dataBuf.Size() == 0)
{
// _headersError = true;
@@ -1292,18 +1356,19 @@ HRESULT CHandler::Open2(IInStream *inStream)
RINOK(CheckProgress());
}
- if (_nodes[k_INODE_ROOT].ParentNode != k_INODE_ROOT)
+ if (_nodes[_refs[k_INODE_ROOT]].ParentNode != k_INODE_ROOT)
return S_FALSE;
}
{
// ---------- Check NumLinks and unreferenced dir nodes ----------
- FOR_VECTOR (i, _nodes)
+ FOR_VECTOR (i, _refs)
{
- const CNode &node = _nodes[i];
- if (node.IsEmpty)
+ int nodeIndex = _refs[i];
+ if (nodeIndex < 0)
continue;
+ const CNode &node = _nodes[nodeIndex];
if (node.NumLinks != node.NumLinksCalced)
{
@@ -1331,19 +1396,23 @@ HRESULT CHandler::Open2(IInStream *inStream)
{
// ---------- Check that there is no loops in parents list ----------
- unsigned numNodes = _nodes.Size();
+ unsigned numNodes = _refs.Size();
CIntArr UsedByNode(numNodes);
{
- for (unsigned i = 0; i < numNodes; i++)
- UsedByNode[i] = -1;
+ {
+ for (unsigned i = 0; i < numNodes; i++)
+ UsedByNode[i] = -1;
+ }
}
- FOR_VECTOR (i, _nodes)
+ FOR_VECTOR (i, _refs)
{
{
- CNode &node = _nodes[i];
- if (node.IsEmpty
- || node.ParentNode < 0 // not dir
+ int nodeIndex = _refs[i];
+ if (nodeIndex < 0)
+ continue;
+ const CNode &node = _nodes[nodeIndex];
+ if (node.ParentNode < 0 // not dir
|| i == k_INODE_ROOT)
continue;
}
@@ -1352,9 +1421,10 @@ HRESULT CHandler::Open2(IInStream *inStream)
for (;;)
{
- CNode &node = _nodes[c];
- if (node.IsEmpty)
+ int nodeIndex = _refs[c];
+ if (nodeIndex < 0)
return S_FALSE;
+ CNode &node = _nodes[nodeIndex];
if (UsedByNode[c] != -1)
{
@@ -1380,14 +1450,17 @@ HRESULT CHandler::Open2(IInStream *inStream)
CByteBuffer data;
unsigned i;
- for (i = 0; i < _nodes.Size(); i++)
+ for (i = 0; i < _refs.Size(); i++)
{
- CNode &node = _nodes[i];
- if (node.IsEmpty || !node.IsLink())
+ int nodeIndex = _refs[i];
+ if (nodeIndex < 0)
+ continue;
+ CNode &node = _nodes[nodeIndex];
+ if (!node.IsLink())
continue;
if (node.FileSize > ((UInt32)1 << 14))
continue;
- if (ExtractNode(i, data) == S_OK && data.Size() != 0)
+ if (ExtractNode(nodeIndex, data) == S_OK && data.Size() != 0)
{
s.SetFrom_CalcLen((const char *)(const Byte *)data, (unsigned)data.Size());
if (s.Len() == data.Size())
@@ -1402,7 +1475,7 @@ HRESULT CHandler::Open2(IInStream *inStream)
for (i = 0; i < _items.Size(); i++)
{
CItem &item = _items[i];
- int sym = _nodes[item.Node].SymLinkIndex;
+ int sym = _nodes[_refs[item.Node]].SymLinkIndex;
if (sym >= 0 && item.ParentNode >= 0)
{
item.SymLinkItemIndex = FindTargetItem_for_SymLink(item.ParentNode, _symLinks[sym]);
@@ -1425,11 +1498,12 @@ HRESULT CHandler::Open2(IInStream *inStream)
bool useSys = false;
bool useUnknown = false;
- for (unsigned i = 0; i < _nodes.Size(); i++)
+ FOR_VECTOR (i, _refs)
{
- const CNode &node = _nodes[i];
- if (node.IsEmpty)
+ int nodeIndex = _refs[i];
+ if (nodeIndex < 0)
continue;
+ const CNode &node = _nodes[nodeIndex];
if (node.NumLinksCalced == 0 /* || i > 100 && i < 150 */) // for debug
{
@@ -1509,6 +1583,7 @@ void CHandler::ClearRefs()
_stream.Release();
_items.Clear();
_nodes.Clear();
+ _refs.Clear();
_auxItems.Clear();
_symLinks.Clear();
_dirs.Clear();
@@ -1524,6 +1599,7 @@ STDMETHODIMP CHandler::Close()
_phySize = 0;
_isArc = false;
_headersError = false;
+ _headersWarning = false;
_linksError = false;
_isUTF = true;
@@ -1562,7 +1638,7 @@ void CHandler::GetPath(unsigned index, AString &s) const
return;
}
- const CNode &node = _nodes[item.ParentNode];
+ const CNode &node = _nodes[_refs[item.ParentNode]];
if (node.ItemIndex < 0)
return;
index = node.ItemIndex;
@@ -1585,7 +1661,7 @@ bool CHandler::GetPackSize(unsigned index, UInt64 &totalPack) const
}
const CItem &item = _items[index];
- const CNode &node = _nodes[item.Node];
+ const CNode &node = _nodes[_refs[item.Node]];
// if (!node.IsFlags_EXTENTS())
{
@@ -1766,22 +1842,29 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidId:
{
- char s[16 * 2 + 2];
- for (unsigned i = 0; i < 16; i++)
- PrintHex(_h.Uuid[i], s + i * 2);
- s[16 * 2] = 0;
- prop = s;
+ if (!IsEmptyData(_h.Uuid, 16))
+ {
+ char s[16 * 2 + 2];
+ for (unsigned i = 0; i < 16; i++)
+ PrintHex(_h.Uuid[i], s + i * 2);
+ s[16 * 2] = 0;
+ prop = s;
+ }
break;
}
case kpidCodePage: if (_isUTF) prop = "UTF-8"; break;
- case kpidVolumeName: StringToProp(_isUTF, _h.VolName, sizeof(_h.VolName), prop); break;
+
+ case kpidShortComment:
+ case kpidVolumeName:
+ StringToProp(_isUTF, _h.VolName, sizeof(_h.VolName), prop); break;
+
case kpidLastMount: StringToProp(_isUTF, _h.LastMount, sizeof(_h.LastMount), prop); break;
case kpidCharacts: FLAGS_TO_PROP(g_FeatureCompat_Flags, _h.FeatureCompat, prop); break;
case kpidFeatureIncompat: FLAGS_TO_PROP(g_FeatureIncompat_Flags, _h.FeatureIncompat, prop); break;
case kpidFeatureRoCompat: FLAGS_TO_PROP(g_FeatureRoCompat_Flags, _h.FeatureRoCompat, prop); break;
- case kpidWrittenKB: prop = _h.WrittenKB; break;
+ case kpidWrittenKB: if (_h.WrittenKB != 0) prop = _h.WrittenKB; break;
case kpidPhySize: prop = _phySize; break;
@@ -1797,6 +1880,15 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
prop = v;
break;
}
+
+ case kpidWarningFlags:
+ {
+ UInt32 v = 0;
+ if (_headersWarning) v |= kpv_ErrorFlags_HeadersError;
+ if (v != 0)
+ prop = v;
+ break;
+ }
}
prop.Detach(value);
@@ -1846,7 +1938,7 @@ STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentTyp
}
else
{
- int itemIndex = _nodes[item.ParentNode].ItemIndex;
+ int itemIndex = _nodes[_refs[item.ParentNode]].ItemIndex;
if (itemIndex >= 0)
*parent = itemIndex;
}
@@ -1952,7 +2044,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
const CItem &item = _items[index];
- const CNode &node = _nodes[item.Node];
+ const CNode &node = _nodes[_refs[item.Node]];
bool isDir = node.IsDir();
switch (propID)
@@ -1987,7 +2079,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
bool isDir2 = isDir;
if (item.SymLinkItemIndex >= 0)
- isDir2 = _nodes[_items[item.SymLinkItemIndex].Node].IsDir();
+ isDir2 = _nodes[_refs[_items[item.SymLinkItemIndex].Node]].IsDir();
prop = isDir2;
break;
}
@@ -2050,6 +2142,118 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
}
+class CClusterInStream2:
+ public IInStream,
+ public CMyUnknownImp
+{
+ UInt64 _virtPos;
+ UInt64 _physPos;
+ UInt32 _curRem;
+public:
+ unsigned BlockBits;
+ UInt64 Size;
+ CMyComPtr<IInStream> Stream;
+ CRecordVector<UInt32> Vector;
+
+ HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
+
+ HRESULT InitAndSeek()
+ {
+ _curRem = 0;
+ _virtPos = 0;
+ _physPos = 0;
+ if (Vector.Size() > 0)
+ {
+ _physPos = (Vector[0] << BlockBits);
+ return SeekToPhys();
+ }
+ return S_OK;
+ }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+
+
+STDMETHODIMP CClusterInStream2::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (_virtPos >= Size)
+ return S_OK;
+ {
+ UInt64 rem = Size - _virtPos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+ if (size == 0)
+ return S_OK;
+
+ if (_curRem == 0)
+ {
+ const UInt32 blockSize = (UInt32)1 << BlockBits;
+ const UInt32 virtBlock = (UInt32)(_virtPos >> BlockBits);
+ const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);
+ const UInt32 phyBlock = Vector[virtBlock];
+
+ if (phyBlock == 0)
+ {
+ UInt32 cur = blockSize - offsetInBlock;
+ if (cur > size)
+ cur = size;
+ memset(data, 0, cur);
+ _virtPos += cur;
+ if (processedSize)
+ *processedSize = cur;
+ return S_OK;
+ }
+
+ UInt64 newPos = ((UInt64)phyBlock << BlockBits) + offsetInBlock;
+ if (newPos != _physPos)
+ {
+ _physPos = newPos;
+ RINOK(SeekToPhys());
+ }
+
+ _curRem = blockSize - offsetInBlock;
+
+ for (unsigned i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++)
+ _curRem += (UInt32)1 << BlockBits;
+ }
+
+ if (size > _curRem)
+ size = _curRem;
+ HRESULT res = Stream->Read(data, size, &size);
+ if (processedSize)
+ *processedSize = size;
+ _physPos += size;
+ _virtPos += size;
+ _curRem -= size;
+ return res;
+}
+
+STDMETHODIMP CClusterInStream2::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ switch (seekOrigin)
+ {
+ case STREAM_SEEK_SET: break;
+ case STREAM_SEEK_CUR: offset += _virtPos; break;
+ case STREAM_SEEK_END: offset += Size; break;
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ if (_virtPos != (UInt64)offset)
+ _curRem = 0;
+ _virtPos = offset;
+ if (newPosition)
+ *newPosition = offset;
+ return S_OK;
+}
+
+
class CExtInStream:
public IInStream,
public CMyUnknownImp
@@ -2057,8 +2261,8 @@ class CExtInStream:
UInt64 _virtPos;
UInt64 _phyPos;
public:
- UInt64 _size;
unsigned BlockBits;
+ UInt64 Size;
CMyComPtr<IInStream> Stream;
CRecordVector<CExtent> Extents;
@@ -2080,11 +2284,13 @@ STDMETHODIMP CExtInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize)
*processedSize = 0;
- if (_virtPos >= _size)
+ if (_virtPos >= Size)
return S_OK;
- UInt64 rem = _size - _virtPos;
- if (size > rem)
- size = (UInt32)rem;
+ {
+ UInt64 rem = Size - _virtPos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
if (size == 0)
return S_OK;
@@ -2155,7 +2361,7 @@ STDMETHODIMP CExtInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosi
{
case STREAM_SEEK_SET: break;
case STREAM_SEEK_CUR: offset += _virtPos; break;
- case STREAM_SEEK_END: offset += _size; break;
+ case STREAM_SEEK_END: offset += Size; break;
default: return STG_E_INVALIDFUNCTION;
}
if (offset < 0)
@@ -2174,6 +2380,8 @@ HRESULT CHandler::FillFileBlocks2(UInt32 block, unsigned level, unsigned numBloc
CByteBuffer &tempBuf = _tempBufs[level];
tempBuf.Alloc(blockSize);
+ PRF2(printf("\n level = %d, block = %7d", level, (unsigned)block));
+
RINOK(SeekAndRead(_stream, block, tempBuf, blockSize));
const Byte *p = tempBuf;
@@ -2184,16 +2392,34 @@ HRESULT CHandler::FillFileBlocks2(UInt32 block, unsigned level, unsigned numBloc
if (blocks.Size() == numBlocks)
break;
UInt32 val = GetUi32(p + 4 * i);
- if (val == 0 || val >= _h.NumBlocks)
+ if (val >= _h.NumBlocks)
return S_FALSE;
if (level != 0)
{
+ if (val == 0)
+ {
+ /*
+ size_t num = (size_t)1 << ((_h.BlockBits - 2) * (level));
+ PRF2(printf("\n num empty = %3d", (unsigned)num));
+ for (size_t k = 0; k < num; k++)
+ {
+ blocks.Add(0);
+ if (blocks.Size() == numBlocks)
+ return S_OK;
+ }
+ continue;
+ */
+ return S_FALSE;
+ }
+
RINOK(FillFileBlocks2(val, level - 1, numBlocks, blocks));
continue;
}
- PRF(printf("\n i = %3d, start = %5d ", (unsigned)val));
+ PRF2(printf("\n i = %3d, blocks.Size() = %6d, block = %5d ", i, blocks.Size(), (unsigned)val));
+
+ PRF(printf("\n i = %3d, start = %5d ", (unsigned)i, (unsigned)val));
blocks.Add(val);
}
@@ -2206,28 +2432,44 @@ static const unsigned kNumDirectNodeBlocks = 12;
HRESULT CHandler::FillFileBlocks(const Byte *p, unsigned numBlocks, CRecordVector<UInt32> &blocks)
{
+ // ext2 supports zero blocks (blockIndex == 0).
+
blocks.ClearAndReserve(numBlocks);
- unsigned i;
-
- for (i = 0; i < kNumDirectNodeBlocks; i++)
+ for (unsigned i = 0; i < kNumDirectNodeBlocks; i++)
{
if (i == numBlocks)
return S_OK;
UInt32 val = GetUi32(p + 4 * i);
- if (val == 0 || val >= _h.NumBlocks)
+ if (val >= _h.NumBlocks)
return S_FALSE;
blocks.Add(val);
}
- for (i = 0; i < 3; i++)
+ for (unsigned level = 0; level < 3; level++)
{
if (blocks.Size() == numBlocks)
break;
- UInt32 val = GetUi32(p + 4 * (kNumDirectNodeBlocks + i));
- if (val == 0 || val >= _h.NumBlocks)
+ UInt32 val = GetUi32(p + 4 * (kNumDirectNodeBlocks + level));
+ if (val >= _h.NumBlocks)
+ return S_FALSE;
+
+ if (val == 0)
+ {
+ /*
+ size_t num = (size_t)1 << ((_h.BlockBits - 2) * (level + 1));
+ for (size_t k = 0; k < num; k++)
+ {
+ blocks.Add(0);
+ if (blocks.Size() == numBlocks)
+ return S_OK;
+ }
+ continue;
+ */
return S_FALSE;
- RINOK(FillFileBlocks2(val, i, numBlocks, blocks));
+ }
+
+ RINOK(FillFileBlocks2(val, level, numBlocks, blocks));
}
return S_OK;
@@ -2331,7 +2573,7 @@ HRESULT CHandler::FillExtents(const Byte *p, size_t size, CRecordVector<CExtent>
}
-HRESULT CHandler::GetStream_Node(UInt32 nodeIndex, ISequentialInStream **stream)
+HRESULT CHandler::GetStream_Node(unsigned nodeIndex, ISequentialInStream **stream)
{
COM_TRY_BEGIN
@@ -2341,7 +2583,12 @@ HRESULT CHandler::GetStream_Node(UInt32 nodeIndex, ISequentialInStream **stream)
if (!node.IsFlags_EXTENTS())
{
- // maybe sparse file can have NumBlocks == 0 ?
+ // maybe sparse file can have (node.NumBlocks == 0) ?
+
+ /* The following code doesn't work correctly for some CentOS images,
+ where there are nodes with inline data and (node.NumBlocks != 0).
+ If you know better way to detect inline data, please notify 7-Zip developers. */
+
if (node.NumBlocks == 0 && node.FileSize < kNodeBlockFieldSize)
{
Create_BufInStream_WithNewBuffer(node.Block, (size_t)node.FileSize, stream);
@@ -2365,7 +2612,7 @@ HRESULT CHandler::GetStream_Node(UInt32 nodeIndex, ISequentialInStream **stream)
streamTemp = streamSpec;
streamSpec->BlockBits = _h.BlockBits;
- streamSpec->_size = node.FileSize;
+ streamSpec->Size = node.FileSize;
streamSpec->Stream = _stream;
RINOK(FillExtents(node.Block, kNodeBlockFieldSize, streamSpec->Extents, -1));
@@ -2421,11 +2668,10 @@ HRESULT CHandler::GetStream_Node(UInt32 nodeIndex, ISequentialInStream **stream)
if (numBlocks != numBlocks64)
return S_FALSE;
- CClusterInStream *streamSpec = new CClusterInStream;
+ CClusterInStream2 *streamSpec = new CClusterInStream2;
streamTemp = streamSpec;
- streamSpec->BlockSizeLog = _h.BlockBits;
- streamSpec->StartOffset = 0;
+ streamSpec->BlockBits = _h.BlockBits;
streamSpec->Size = node.FileSize;
streamSpec->Stream = _stream;
@@ -2477,7 +2723,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (index >= _items.Size())
continue;
const CItem &item = _items[index];
- const CNode &node = _nodes[item.Node];
+ const CNode &node = _nodes[_refs[item.Node]];
if (!node.IsDir())
totalSize += node.FileSize;
}
@@ -2520,7 +2766,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
const CItem &item = _items[index];
- const CNode &node = _nodes[item.Node];
+ const CNode &node = _nodes[_refs[item.Node]];
if (node.IsDir())
{
@@ -2583,7 +2829,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
*stream = NULL;
if (index >= _items.Size())
return S_FALSE;
- return GetStream_Node(_items[index].Node, stream);
+ return GetStream_Node(_refs[_items[index].Node], stream);
}
@@ -2601,7 +2847,7 @@ API_FUNC_static_IsArc IsArc_Ext(const Byte *p, size_t size)
static const Byte k_Signature[] = { 0x53, 0xEF };
REGISTER_ARC_I(
- "Ext", "ext ext3 ext4", 0, 0xC7,
+ "Ext", "ext ext2 ext3 ext4 img", 0, 0xC7,
k_Signature,
0x438,
0,
diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp
index e16a8860..e8340f1d 100644
--- a/CPP/7zip/Archive/FatHandler.cpp
+++ b/CPP/7zip/Archive/FatHandler.cpp
@@ -133,15 +133,23 @@ bool CHeader::Parse(const Byte *p)
default: return false;
}
{
- int s = GetLog(Get16(p + 11));
- if (s < 9 || s > 12)
- return false;
- SectorSizeLog = (Byte)s;
- s = GetLog(p[13]);
- if (s < 0)
- return false;
- SectorsPerClusterLog = (Byte)s;
+ {
+ UInt32 val32 = Get16(p + 11);
+ int s = GetLog(val32);
+ if (s < 9 || s > 12)
+ return false;
+ SectorSizeLog = (Byte)s;
+ }
+ {
+ UInt32 val32 = p[13];
+ int s = GetLog(val32);
+ if (s < 0)
+ return false;
+ SectorsPerClusterLog = (Byte)s;
+ }
ClusterSizeLog = (Byte)(SectorSizeLog + SectorsPerClusterLog);
+ if (ClusterSizeLog > 24)
+ return false;
}
NumReservedSectors = Get16(p + 14);
diff --git a/CPP/7zip/Archive/GptHandler.cpp b/CPP/7zip/Archive/GptHandler.cpp
index 2e0e7a57..e54b1477 100644
--- a/CPP/7zip/Archive/GptHandler.cpp
+++ b/CPP/7zip/Archive/GptHandler.cpp
@@ -156,8 +156,15 @@ class CHandler: public CHandlerCont
CByteBuffer _buffer;
HRESULT Open2(IInStream *stream);
- virtual UInt64 GetItemPos(UInt32 index) const { return _items[index].GetPos(); }
- virtual UInt64 GetItemSize(UInt32 index) const { return _items[index].GetSize(); }
+
+ virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const
+ {
+ const CPartition &item = _items[index];
+ pos = item.GetPos();
+ size = item.GetSize();
+ return NExtract::NOperationResult::kOK;
+ }
+
public:
INTERFACE_IInArchive_Cont(;)
};
diff --git a/CPP/7zip/Archive/HandlerCont.cpp b/CPP/7zip/Archive/HandlerCont.cpp
index ca9153b8..c2d5c70c 100644
--- a/CPP/7zip/Archive/HandlerCont.cpp
+++ b/CPP/7zip/Archive/HandlerCont.cpp
@@ -28,7 +28,11 @@ STDMETHODIMP CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 totalSize = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
- totalSize += GetItemSize(allFilesMode ? i : indices[i]);
+ {
+ UInt64 pos, size;
+ GetItem_ExtractInfo(allFilesMode ? i : indices[i], pos, size);
+ totalSize += size;
+ }
extractCallback->SetTotal(totalSize);
totalSize = 0;
@@ -56,21 +60,31 @@ STDMETHODIMP CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems,
Int32 index = allFilesMode ? i : indices[i];
RINOK(extractCallback->GetStream(index, &outStream, askMode));
- UInt64 size = GetItemSize(index);
+
+ UInt64 pos, size;
+ int opRes = GetItem_ExtractInfo(index, pos, size);
totalSize += size;
if (!testMode && !outStream)
continue;
+
RINOK(extractCallback->PrepareOperation(askMode));
- RINOK(_stream->Seek(GetItemPos(index), STREAM_SEEK_SET, NULL));
- streamSpec->Init(size);
- RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+ if (opRes == NExtract::NOperationResult::kOK)
+ {
+ RINOK(_stream->Seek(pos, STREAM_SEEK_SET, NULL));
+ streamSpec->Init(size);
+
+ RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+
+ opRes = NExtract::NOperationResult::kDataError;
+
+ if (copyCoderSpec->TotalSize == size)
+ opRes = NExtract::NOperationResult::kOK;
+ else if (copyCoderSpec->TotalSize < size)
+ opRes = NExtract::NOperationResult::kUnexpectedEnd;
+ }
+
outStream.Release();
- int opRes = NExtract::NOperationResult::kDataError;
- if (copyCoderSpec->TotalSize == size)
- opRes = NExtract::NOperationResult::kOK;
- else if (copyCoderSpec->TotalSize < size)
- opRes = NExtract::NOperationResult::kUnexpectedEnd;
RINOK(extractCallback->SetOperationResult(opRes));
}
@@ -81,13 +95,22 @@ STDMETHODIMP CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems,
STDMETHODIMP CHandlerCont::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
- // const CPartition &item = _items[index];
- return CreateLimitedInStream(_stream, GetItemPos(index), GetItemSize(index), stream);
+ *stream = NULL;
+ UInt64 pos, size;
+ if (GetItem_ExtractInfo(index, pos, size) != NExtract::NOperationResult::kOK)
+ return S_FALSE;
+ return CreateLimitedInStream(_stream, pos, size, stream);
COM_TRY_END
}
+CHandlerImg::CHandlerImg():
+ _imgExt(NULL)
+{
+ ClearStreamVars();
+}
+
STDMETHODIMP CHandlerImg::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
switch (seekOrigin)
@@ -190,6 +213,8 @@ STDMETHODIMP CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems,
int opRes = NExtract::NOperationResult::kDataError;
+ ClearStreamVars();
+
CMyComPtr<ISequentialInStream> inStream;
HRESULT hres = GetStream(0, &inStream);
if (hres == S_FALSE)
@@ -205,6 +230,13 @@ STDMETHODIMP CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems,
{
if (copyCoderSpec->TotalSize == _size)
opRes = NExtract::NOperationResult::kOK;
+
+ if (_stream_unavailData)
+ opRes = NExtract::NOperationResult::kUnavailable;
+ else if (_stream_unsupportedMethod)
+ opRes = NExtract::NOperationResult::kUnsupportedMethod;
+ else if (_stream_dataError)
+ opRes = NExtract::NOperationResult::kDataError;
else if (copyCoderSpec->TotalSize < _size)
opRes = NExtract::NOperationResult::kUnexpectedEnd;
}
diff --git a/CPP/7zip/Archive/HandlerCont.h b/CPP/7zip/Archive/HandlerCont.h
index 58b45d54..50a72895 100644
--- a/CPP/7zip/Archive/HandlerCont.h
+++ b/CPP/7zip/Archive/HandlerCont.h
@@ -30,8 +30,8 @@ class CHandlerCont:
protected:
CMyComPtr<IInStream> _stream;
- virtual UInt64 GetItemPos(UInt32 index) const = 0;
- virtual UInt64 GetItemSize(UInt32 index) const = 0;
+ virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const = 0;
+
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive_Cont(PURE)
@@ -39,6 +39,9 @@ public:
STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) MY_NO_THROW_DECL_ONLY;
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+
+ // destructor must be virtual for this class
+ virtual ~CHandlerCont() {}
};
@@ -68,6 +71,22 @@ protected:
UInt64 _size;
CMyComPtr<IInStream> Stream;
const char *_imgExt;
+
+ bool _stream_unavailData;
+ bool _stream_unsupportedMethod;
+ bool _stream_dataError;
+ // bool _stream_UsePackSize;
+ // UInt64 _stream_PackSize;
+
+ void ClearStreamVars()
+ {
+ _stream_unavailData = false;
+ _stream_unsupportedMethod = false;
+ _stream_dataError = false;
+ // _stream_UsePackSize = false;
+ // _stream_PackSize = 0;
+ }
+
virtual HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) = 0;
virtual void CloseAtError();
@@ -83,6 +102,10 @@ public:
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) = 0;
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+
+ CHandlerImg();
+ // destructor must be virtual for this class
+ virtual ~CHandlerImg() {}
};
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp
index 713764d9..91bf1a25 100644
--- a/CPP/7zip/Archive/Iso/IsoHandler.cpp
+++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp
@@ -323,7 +323,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
lps->InSize = lps->OutSize = currentTotalSize + offset;
const CDir &item2 = ref.Dir->_subItems[ref.Index + e];
- RINOK(_stream->Seek((UInt64)item2.ExtentLocation * _archive.BlockSize, STREAM_SEEK_SET, NULL));
+ RINOK(_stream->Seek((UInt64)item2.ExtentLocation * kBlockSize, STREAM_SEEK_SET, NULL));
streamSpec->Init(item2.Size);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != item2.Size)
@@ -336,7 +336,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
else
{
- RINOK(_stream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL));
+ RINOK(_stream->Seek((UInt64)blockIndex * kBlockSize, STREAM_SEEK_SET, NULL));
streamSpec->Init(currentItemSize);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != currentItemSize)
@@ -379,7 +379,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
if (item.Size == 0)
continue;
CSeekExtent se;
- se.Phy = (UInt64)item.ExtentLocation * _archive.BlockSize;
+ se.Phy = (UInt64)item.ExtentLocation * kBlockSize;
se.Virt = virtOffset;
extentStreamSpec->Extents.Add(se);
virtOffset += item.Size;
@@ -405,7 +405,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
blockIndex = be.LoadRBA;
}
- return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream);
+ return CreateLimitedInStream(_stream, (UInt64)blockIndex * kBlockSize, currentItemSize, stream);
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp
index 39034b63..1c7dd11e 100644
--- a/CPP/7zip/Archive/Iso/IsoIn.cpp
+++ b/CPP/7zip/Archive/Iso/IsoIn.cpp
@@ -88,15 +88,15 @@ AString CBootInitialEntry::GetName() const
Byte CInArchive::ReadByte()
{
- if (m_BufferPos >= BlockSize)
+ if (m_BufferPos >= kBlockSize)
m_BufferPos = 0;
if (m_BufferPos == 0)
{
- size_t processed = BlockSize;
+ size_t processed = kBlockSize;
HRESULT res = ReadStream(_stream, m_Buffer, &processed);
if (res != S_OK)
throw CSystemException(res);
- if (processed != BlockSize)
+ if (processed != kBlockSize)
throw CUnexpectedEndException();
UInt64 end = _position + processed;
if (PhySize < end)
@@ -511,7 +511,7 @@ HRESULT CInArchive::Open2()
PhySize = _position;
m_BufferPos = 0;
- BlockSize = kBlockSize;
+ // BlockSize = kBlockSize;
for (;;)
{
diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h
index c2007bce..5c1a4bcf 100644
--- a/CPP/7zip/Archive/Iso/IsoIn.h
+++ b/CPP/7zip/Archive/Iso/IsoIn.h
@@ -282,7 +282,7 @@ public:
CRecordVector<CRef> Refs;
CObjectVector<CVolumeDescriptor> VolDescs;
int MainVolDescIndex;
- UInt32 BlockSize;
+ // UInt32 BlockSize;
CObjectVector<CBootInitialEntry> BootEntries;
bool IsArc;
@@ -297,8 +297,8 @@ public:
void UpdatePhySize(UInt32 blockIndex, UInt64 size)
{
- UInt64 alignedSize = (size + BlockSize - 1) & ~((UInt64)BlockSize - 1);
- UInt64 end = blockIndex * BlockSize + alignedSize;
+ const UInt64 alignedSize = (size + kBlockSize - 1) & ~((UInt64)kBlockSize - 1);
+ const UInt64 end = (UInt64)blockIndex * kBlockSize + alignedSize;
if (PhySize < end)
PhySize = end;
}
@@ -315,7 +315,7 @@ public:
size = (1440 << 10);
else if (be.BootMediaType == NBootMediaType::k2d88Floppy)
size = (2880 << 10);
- UInt64 startPos = (UInt64)be.LoadRBA * BlockSize;
+ UInt64 startPos = (UInt64)be.LoadRBA * kBlockSize;
if (startPos < _fileSize)
{
if (_fileSize - startPos < size)
diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp
index 93b615d2..b92755ae 100644
--- a/CPP/7zip/Archive/MbrHandler.cpp
+++ b/CPP/7zip/Archive/MbrHandler.cpp
@@ -158,6 +158,7 @@ static const CPartType kPartTypes[] =
{ 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" },
{ 0x82, 0, "Solaris x86 / Linux swap" },
{ 0x83, 0, "Linux" },
+ { 0x8E, "lvm", "Linux LVM" },
{ 0xA5, 0, "BSD slice" },
{ 0xBE, 0, "Solaris 8 boot" },
{ 0xBF, 0, "New Solaris x86" },
@@ -189,8 +190,14 @@ class CHandler: public CHandlerCont
UInt64 _totalSize;
CByteBuffer _buffer;
- virtual UInt64 GetItemPos(UInt32 index) const { return _items[index].Part.GetPos(); }
- virtual UInt64 GetItemSize(UInt32 index) const { return _items[index].Size; }
+ virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const
+ {
+ const CItem &item = _items[index];
+ pos = item.Part.GetPos();
+ size = item.Size;
+ return NExtract::NOperationResult::kOK;
+ }
+
HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level);
public:
INTERFACE_IInArchive_Cont(;)
diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp
index 05ea4d9f..56b8aa32 100644
--- a/CPP/7zip/Archive/MubHandler.cpp
+++ b/CPP/7zip/Archive/MubHandler.cpp
@@ -56,8 +56,15 @@ class CHandler: public CHandlerCont
CItem _items[kNumFilesMax];
HRESULT Open2(IInStream *stream);
- virtual UInt64 GetItemPos(UInt32 index) const { return _items[index].Offset; }
- virtual UInt64 GetItemSize(UInt32 index) const { return _items[index].Size; }
+
+ virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const
+ {
+ const CItem &item = _items[index];
+ pos = item.Offset;
+ size = item.Size;
+ return NExtract::NOperationResult::kOK;
+ }
+
public:
INTERFACE_IInArchive_Cont(;)
};
diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp
index 70023fe4..fa4bbc9c 100644
--- a/CPP/7zip/Archive/NtfsHandler.cpp
+++ b/CPP/7zip/Archive/NtfsHandler.cpp
@@ -576,20 +576,20 @@ class CInStream:
UInt64 _physPos;
UInt64 _curRem;
bool _sparseMode;
- size_t _compressedPos;
- UInt64 _tags[kNumCacheChunks];
+
unsigned _chunkSizeLog;
+ UInt64 _tags[kNumCacheChunks];
CByteBuffer _inBuf;
CByteBuffer _outBuf;
public:
- CMyComPtr<IInStream> Stream;
UInt64 Size;
UInt64 InitializedSize;
unsigned BlockSizeLog;
unsigned CompressionUnit;
- bool InUse;
CRecordVector<CExtent> Extents;
+ bool InUse;
+ CMyComPtr<IInStream> Stream;
HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
@@ -597,11 +597,11 @@ public:
HRESULT InitAndSeek(unsigned compressionUnit)
{
CompressionUnit = compressionUnit;
+ _chunkSizeLog = BlockSizeLog + CompressionUnit;
if (compressionUnit != 0)
{
UInt32 cuSize = GetCuSize();
_inBuf.Alloc(cuSize);
- _chunkSizeLog = BlockSizeLog + CompressionUnit;
_outBuf.Alloc(kNumCacheChunks << _chunkSizeLog);
}
for (size_t i = 0; i < kNumCacheChunks; i++)
diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp
index f3ae78aa..08df1ae7 100644
--- a/CPP/7zip/Archive/RpmHandler.cpp
+++ b/CPP/7zip/Archive/RpmHandler.cpp
@@ -226,8 +226,13 @@ class CHandler: public CHandlerCont
HRESULT ReadHeader(ISequentialInStream *stream, bool isMainHeader);
HRESULT Open2(ISequentialInStream *stream);
- virtual UInt64 GetItemPos(UInt32) const { return _headersSize; }
- virtual UInt64 GetItemSize(UInt32) const { return _size; }
+ virtual int GetItem_ExtractInfo(UInt32 /* index */, UInt64 &pos, UInt64 &size) const
+ {
+ pos = _headersSize;
+ size = _size;
+ return NExtract::NOperationResult::kOK;
+ }
+
public:
INTERFACE_IInArchive_Cont(;)
};
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp
index 62df64dc..6be035cb 100644
--- a/CPP/7zip/Archive/Udf/UdfIn.cpp
+++ b/CPP/7zip/Archive/Udf/UdfIn.cpp
@@ -564,7 +564,7 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la
return S_OK;
}
-HRESULT CInArchive::FillRefs(CFileSet &fs, int fileIndex, int parent, int numRecurseAllowed)
+HRESULT CInArchive::FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed)
{
if ((_numRefs & 0xFFF) == 0)
{
diff --git a/CPP/7zip/Archive/Udf/UdfIn.h b/CPP/7zip/Archive/Udf/UdfIn.h
index 23693a71..3851062e 100644
--- a/CPP/7zip/Archive/Udf/UdfIn.h
+++ b/CPP/7zip/Archive/Udf/UdfIn.h
@@ -252,7 +252,7 @@ struct CItem
bool IsInline;
CByteBuffer InlineData;
CRecordVector<CMyExtent> Extents;
- CRecordVector<int> SubFiles;
+ CUIntVector SubFiles;
void Parse(const Byte *buf);
@@ -282,7 +282,7 @@ struct CItem
struct CRef
{
int Parent;
- int FileIndex;
+ unsigned FileIndex;
};
@@ -346,7 +346,7 @@ class CInArchive
HRESULT ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed);
HRESULT Open2();
- HRESULT FillRefs(CFileSet &fs, int fileIndex, int parent, int numRecurseAllowed);
+ HRESULT FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed);
UInt64 _processedProgressBytes;
diff --git a/CPP/7zip/Archive/VmdkHandler.cpp b/CPP/7zip/Archive/VmdkHandler.cpp
index 4b404e14..83e38d02 100644
--- a/CPP/7zip/Archive/VmdkHandler.cpp
+++ b/CPP/7zip/Archive/VmdkHandler.cpp
@@ -8,6 +8,9 @@
#include "../../Common/ComTry.h"
#include "../../Common/IntToString.h"
+#include "../../Common/StringConvert.h"
+#include "../../Common/StringToInt.h"
+#include "../../Common/UTFConvert.h"
#include "../../Windows/PropVariant.h"
@@ -19,24 +22,29 @@
#include "HandlerCont.h"
+using namespace NWindows;
+
+namespace NArchive {
+namespace NVmdk {
+
#define Get16(p) GetUi16(p)
#define Get32(p) GetUi32(p)
#define Get64(p) GetUi64(p)
-using namespace NWindows;
+#define LE_16(offs, dest) dest = Get16(p + (offs));
+#define LE_32(offs, dest) dest = Get32(p + (offs));
+#define LE_64(offs, dest) dest = Get64(p + (offs));
-namespace NArchive {
-namespace NVmdk {
#define SIGNATURE { 'K', 'D', 'M', 'V' }
static const Byte k_Signature[] = SIGNATURE;
-static const UInt32 k_Flags_NL = (UInt32)1 << 0;
-static const UInt32 k_Flags_RGD = (UInt32)1 << 1;
-static const UInt32 k_Flags_ZeroGrain = (UInt32)1 << 2;
+static const UInt32 k_Flags_NL = (UInt32)1 << 0;
+static const UInt32 k_Flags_RGD = (UInt32)1 << 1;
+static const UInt32 k_Flags_ZeroGrain = (UInt32)1 << 2;
static const UInt32 k_Flags_Compressed = (UInt32)1 << 16;
-static const UInt32 k_Flags_Marker = (UInt32)1 << 17;
+static const UInt32 k_Flags_Marker = (UInt32)1 << 17;
static const unsigned k_NumMidBits = 9; // num bits for index in Grain Table
@@ -57,12 +65,12 @@ struct CHeader
UInt64 gdOffset;
UInt64 overHead;
- bool Is_NL() const { return (flags & k_Flags_NL) != 0; };
- bool Is_ZeroGrain() const { return (flags & k_Flags_ZeroGrain) != 0; };
+ bool Is_NL() const { return (flags & k_Flags_NL) != 0; };
+ bool Is_ZeroGrain() const { return (flags & k_Flags_ZeroGrain) != 0; };
bool Is_Compressed() const { return (flags & k_Flags_Compressed) != 0; };
- bool Is_Marker() const { return (flags & k_Flags_Marker) != 0; };
+ bool Is_Marker() const { return (flags & k_Flags_Marker) != 0; };
- bool Parse(const Byte *buf);
+ bool Parse(const Byte *p);
bool IsSameImageFor(const CHeader &h) const
{
@@ -74,25 +82,25 @@ struct CHeader
}
};
-bool CHeader::Parse(const Byte *buf)
+bool CHeader::Parse(const Byte *p)
{
- if (memcmp(buf, k_Signature, sizeof(k_Signature)) != 0)
+ if (memcmp(p, k_Signature, sizeof(k_Signature)) != 0)
return false;
- version = Get32(buf + 0x4);
- flags = Get32(buf + 0x8);
- capacity = Get64(buf + 0xC);
- grainSize = Get64(buf + 0x14);
- descriptorOffset = Get64(buf + 0x1C);
- descriptorSize = Get64(buf + 0x24);
- numGTEsPerGT = Get32(buf + 0x2C);
- // rgdOffset = Get64(buf + 0x30);
- gdOffset = Get64(buf + 0x38);
- overHead = Get64(buf + 0x40);
+ LE_32 (0x04, version);
+ LE_32 (0x08, flags);
+ LE_64 (0x0C, capacity);
+ LE_64 (0x14, grainSize);
+ LE_64 (0x1C, descriptorOffset);
+ LE_64 (0x24, descriptorSize);
+ LE_32 (0x2C, numGTEsPerGT);
+ // LE_64 (0x30, rgdOffset);
+ LE_64 (0x38, gdOffset);
+ LE_64 (0x40, overHead);
// uncleanShutdown = buf[0x48];
- algo = Get16(buf + 0x4D);
+ LE_16(0x4D, algo);
- if (Is_NL() && Get32(buf + 0x49) != 0x0A0D200A) // do we need Is_NL() check here?
+ if (Is_NL() && Get32(p + 0x49) != 0x0A0D200A) // do we need Is_NL() check here?
return false;
return (numGTEsPerGT == (1 << k_NumMidBits)) && (version <= 3);
@@ -115,21 +123,154 @@ struct CMarker
void Parse(const Byte *p)
{
- NumSectors = Get64(p);
- SpecSize = Get32(p + 8);
- Type = Get32(p + 12);
+ LE_64 (0, NumSectors);
+ LE_32 (8, SpecSize);
+ LE_32 (12, Type);
+ }
+};
+
+
+static bool Str_to_ValName(const AString &s, AString &name, AString &val)
+{
+ name.Empty();
+ val.Empty();
+ int qu = s.Find('"');
+ int eq = s.Find('=');
+ if (eq < 0 || (qu >= 0 && eq > qu))
+ return false;
+ name = s.Left(eq);
+ name.Trim();
+ val = s.Ptr(eq + 1);
+ val.Trim();
+ return true;
+}
+
+static inline bool IsSpaceChar(char c)
+{
+ return (c == ' ' || c == '\t');
+}
+
+static const char *SkipSpaces(const char *s)
+{
+ for (;; s++)
+ {
+ char c = *s;
+ if (c == 0 || !IsSpaceChar(c))
+ return s;
}
+}
+
+#define SKIP_SPACES(s) s = SkipSpaces(s);
+
+static const char *GetNextWord(const char *s, AString &dest)
+{
+ dest.Empty();
+ SKIP_SPACES(s);
+ const char *start = s;
+ for (;; s++)
+ {
+ char c = *s;
+ if (c == 0 || IsSpaceChar(c))
+ {
+ dest.SetFrom(start, (unsigned)(s - start));
+ return s;
+ }
+ }
+}
+
+static const char *GetNextNumber(const char *s, UInt64 &val)
+{
+ SKIP_SPACES(s);
+ if (*s == 0)
+ return s;
+ const char *end;
+ val = ConvertStringToUInt64(s, &end);
+ char c = *end;
+ if (c != 0 && !IsSpaceChar(c))
+ return NULL;
+ return end;
+}
+
+
+struct CExtentInfo
+{
+ AString Access; // RW, RDONLY, or NOACCESS
+ UInt64 NumSectors; // 512 bytes sectors
+ AString Type; // FLAT, SPARSE, ZERO, VMFS, VMFSSPARSE, VMFSRDM, VMFSRAW
+ AString FileName;
+ UInt64 StartSector; // used for FLAT
+
+ // for VMWare Player 9:
+ // PartitionUUID
+ // DeviceIdentifier
+
+ bool IsType_ZERO() const { return Type == "ZERO"; }
+ // bool IsType_FLAT() const { return Type == "FLAT"; }
+ bool IsType_Flat() const { return Type == "FLAT" || Type == "VMFS" || Type == "VMFSRAW"; }
+
+ bool Parse(const char *s);
};
+bool CExtentInfo::Parse(const char *s)
+{
+ NumSectors = 0;
+ StartSector = 0;
+ Access.Empty();
+ Type.Empty();
+ FileName.Empty();
+
+ s = GetNextWord(s, Access);
+ s = GetNextNumber(s, NumSectors);
+ if (!s)
+ return false;
+ s = GetNextWord(s, Type);
+
+ if (Type.IsEmpty())
+ return false;
+
+ SKIP_SPACES(s);
+
+ if (IsType_ZERO())
+ return (*s == 0);
+
+ if (*s != '\"')
+ return false;
+ s++;
+ {
+ const char *s2 = strchr(s, '\"');
+ if (!s2)
+ return false;
+ FileName.SetFrom(s, (unsigned)(s2 - s));
+ s = s2 + 1;
+ }
+ SKIP_SPACES(s);
+ if (*s == 0)
+ return true;
+
+ s = GetNextNumber(s, StartSector);
+ if (!s)
+ return false;
+ return true;
+ // SKIP_SPACES(s);
+ // return (*s == 0);
+}
+
struct CDescriptor
{
AString CID;
AString parentCID;
AString createType;
+ // AString encoding; // UTF-8, windows-1252 - default is UTF-8
+
+ CObjectVector<CExtentInfo> Extents;
+
+ static void GetUnicodeName(const AString &s, UString &res)
+ {
+ if (!ConvertUTF8ToUnicode(s, res))
+ MultiByteToUnicodeString2(res, s);
+ }
- AStringVector Extents;
-
void Clear()
{
CID.Empty();
@@ -138,25 +279,16 @@ struct CDescriptor
Extents.Clear();
}
- void Parse(const Byte *p, size_t size);
+ bool IsThere_Parent() const
+ {
+ return !parentCID.IsEmpty() && !parentCID.IsEqualTo_Ascii_NoCase("ffffffff");
+ }
+
+ bool Parse(const Byte *p, size_t size);
};
-static bool Str_to_ValName(const AString &s, AString &name, AString &val)
-{
- name.Empty();
- val.Empty();
- int qu = s.Find('"');
- int eq = s.Find('=');
- if (eq < 0 || (qu >= 0 && eq > qu))
- return false;
- name = s.Left(eq);
- name.Trim();
- val = s.Ptr(eq + 1);
- val.Trim();
- return true;
-}
-void CDescriptor::Parse(const Byte *p, size_t size)
+bool CDescriptor::Parse(const Byte *p, size_t size)
{
Clear();
@@ -166,7 +298,7 @@ void CDescriptor::Parse(const Byte *p, size_t size)
for (size_t i = 0;; i++)
{
- char c = p[i];
+ const char c = p[i];
if (i == size || c == 0 || c == 0xA || c == 0xD)
{
if (!s.IsEmpty() && s[0] != '#')
@@ -181,8 +313,14 @@ void CDescriptor::Parse(const Byte *p, size_t size)
createType = val;
}
else
- Extents.Add(s);
+ {
+ CExtentInfo ei;
+ if (!ei.Parse(s))
+ return false;
+ Extents.Add(ei);
+ }
}
+
s.Empty();
if (c == 0 || i >= size)
break;
@@ -190,25 +328,116 @@ void CDescriptor::Parse(const Byte *p, size_t size)
else
s += (char)c;
}
+
+ return true;
}
+struct CExtent
+{
+ bool IsOK;
+ bool IsArc;
+ bool NeedDeflate;
+ bool Unsupported;
+ bool IsZero;
+ bool IsFlat;
+ bool DescriptorOK;
+ bool HeadersError;
+
+ unsigned ClusterBits;
+ UInt32 ZeroSector;
+
+ CObjectVector<CByteBuffer> Tables;
+
+ CMyComPtr<IInStream> Stream;
+ UInt64 PosInArc;
+
+ UInt64 PhySize;
+ UInt64 VirtSize; // from vmdk header of volume
+
+ UInt64 StartOffset; // virtual offset of this extent
+ UInt64 NumBytes; // from main descriptor, if multi-vol
+ UInt64 FlatOffset; // in Stream
+
+ CByteBuffer DescriptorBuf;
+ CDescriptor Descriptor;
+
+ CHeader h;
+
+ UInt64 GetEndOffset() const { return StartOffset + NumBytes; }
+
+ bool IsVmdk() const { return !IsZero && !IsFlat; };
+ // if (IsOK && IsVmdk()), then VMDK header of this extent was read
+
+ CExtent():
+ IsOK(false),
+ IsArc(false),
+ NeedDeflate(false),
+ Unsupported(false),
+ IsZero(false),
+ IsFlat(false),
+ DescriptorOK(false),
+ HeadersError(false),
+
+ ClusterBits(0),
+ ZeroSector(0),
+
+ PosInArc(0),
+
+ PhySize(0),
+ VirtSize(0),
+
+ StartOffset(0),
+ NumBytes(0),
+ FlatOffset(0)
+ {}
+
+
+ HRESULT ReadForHeader(IInStream *stream, UInt64 sector, void *data, size_t numSectors);
+ HRESULT Open3(IInStream *stream, IArchiveOpenCallback *openCallback,
+ unsigned numVols, unsigned volIndex, UInt64 &complexity);
+
+ HRESULT Seek(UInt64 offset)
+ {
+ PosInArc = offset;
+ return Stream->Seek(offset, STREAM_SEEK_SET, NULL);
+ }
+
+ HRESULT InitAndSeek()
+ {
+ if (Stream)
+ return Seek(0);
+ return S_OK;
+ }
+
+ HRESULT Read(void *data, size_t *size)
+ {
+ HRESULT res = ReadStream(Stream, data, size);
+ PosInArc += *size;
+ return res;
+ }
+};
+
+
class CHandler: public CHandlerImg
{
- unsigned _clusterBits;
+ bool _isArc;
+ bool _unsupported;
+ bool _unsupportedSome;
+ bool _headerError;
+ bool _missingVol;
+ bool _isMultiVol;
+ bool _needDeflate;
- CObjectVector<CByteBuffer> _tables;
UInt64 _cacheCluster;
+ unsigned _cacheExtent;
CByteBuffer _cache;
CByteBuffer _cacheCompressed;
-
+
+ unsigned _clusterBitsMax;
UInt64 _phySize;
- UInt32 _zeroSector;
- bool _needDeflate;
- bool _isArc;
- bool _unsupported;
- // bool _headerError;
+ CObjectVector<CExtent> _extents;
CBufInStream *_bufInStreamSpec;
CMyComPtr<ISequentialInStream> _bufInStream;
@@ -222,24 +451,13 @@ class CHandler: public CHandlerImg
CByteBuffer _descriptorBuf;
CDescriptor _descriptor;
- CHeader h;
-
-
- HRESULT Seek(UInt64 offset)
- {
- _posInArc = offset;
- return Stream->Seek(offset, STREAM_SEEK_SET, NULL);
- }
-
- HRESULT InitAndSeek()
+ void InitAndSeekMain()
{
_virtPos = 0;
- return Seek(0);
}
- HRESULT ReadForHeader(IInStream *stream, UInt64 sector, void *data, size_t numSectors);
virtual HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback);
-
+ virtual void CloseAtError();
public:
INTERFACE_IInArchive_Img(;)
@@ -261,19 +479,130 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
if (size == 0)
return S_OK;
}
-
+
+ unsigned extentIndex;
+ {
+ unsigned left = 0, right = _extents.Size();
+ for (;;)
+ {
+ unsigned mid = (left + right) / 2;
+ if (mid == left)
+ break;
+ if (_virtPos < _extents[mid].StartOffset)
+ right = mid;
+ else
+ left = mid;
+ }
+ extentIndex = left;
+ }
+
+ CExtent &extent = _extents[extentIndex];
+
+ {
+ const UInt64 vir = _virtPos - extent.StartOffset;
+ if (vir >= extent.NumBytes)
+ {
+ return E_FAIL;
+ /*
+ if (vir > extent.NumBytes)
+ _stream_dataError = true;
+ memset(data, 0, size);
+ _virtPos += size;
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+ */
+ }
+
+ {
+ const UInt64 rem = extent.NumBytes - vir;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+
+ if (vir >= extent.VirtSize)
+ {
+ // if vmdk's VirtSize is smaller than VirtSize from main multi-volume descriptor
+ _stream_dataError = true;
+ return S_FALSE;
+ /*
+ memset(data, 0, size);
+ _virtPos += size;
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+ */
+ }
+
+ {
+ const UInt64 rem = extent.VirtSize - vir;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+
+ if (extent.IsZero || !extent.IsOK || !extent.Stream || extent.Unsupported)
+ {
+ if (extent.Unsupported)
+ {
+ _stream_unsupportedMethod = true;
+ return S_FALSE;
+ }
+ if (!extent.IsOK || !extent.Stream)
+ {
+ _stream_unavailData = true;
+ return S_FALSE;
+ }
+ memset(data, 0, size);
+ _virtPos += size;
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+ }
+
+ if (extent.IsFlat)
+ {
+ UInt64 offset = extent.FlatOffset + vir;
+ if (offset != extent.PosInArc)
+ {
+ RINOK(extent.Seek(offset));
+ }
+ UInt32 size2 = 0;
+ HRESULT res = extent.Stream->Read(data, size, &size2);
+ if (res == S_OK && size2 == 0)
+ {
+ _stream_unavailData = true;
+ /*
+ memset(data, 0, size);
+ _virtPos += size;
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+ */
+ }
+ // _stream_PackSize += size2;
+ extent.PosInArc += size2;
+ _virtPos += size2;
+ if (processedSize)
+ *processedSize = size2;
+ return res;
+ }
+ }
+
+
for (;;)
{
- const UInt64 cluster = _virtPos >> _clusterBits;
- const size_t clusterSize = (size_t)1 << _clusterBits;
- const size_t lowBits = (size_t)_virtPos & (clusterSize - 1);
+ const UInt64 vir = _virtPos - extent.StartOffset;
+ const unsigned clusterBits = extent.ClusterBits;
+ const UInt64 cluster = vir >> clusterBits;
+ const size_t clusterSize = (size_t)1 << clusterBits;
+ const size_t lowBits = (size_t)vir & (clusterSize - 1);
{
size_t rem = clusterSize - lowBits;
if (size > rem)
size = (UInt32)rem;
}
- if (cluster == _cacheCluster)
+ if (extentIndex == _cacheExtent && cluster == _cacheCluster)
{
memcpy(data, _cache + lowBits, size);
_virtPos += size;
@@ -284,9 +613,9 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
const UInt64 high = cluster >> k_NumMidBits;
- if (high < _tables.Size())
+ if (high < extent.Tables.Size())
{
- const CByteBuffer &table = _tables[(unsigned)high];
+ const CByteBuffer &table = extent.Tables[(unsigned)high];
if (table.Size() != 0)
{
@@ -294,28 +623,27 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
const Byte *p = (const Byte *)table + (midBits << 2);
const UInt32 v = Get32(p);
- if (v != 0 && v != _zeroSector)
+ if (v != 0 && v != extent.ZeroSector)
{
UInt64 offset = (UInt64)v << 9;
- if (_needDeflate)
+ if (extent.NeedDeflate)
{
- if (offset != _posInArc)
+ if (offset != extent.PosInArc)
{
- // printf("\n%12x %12x\n", (unsigned)offset, (unsigned)(offset - _posInArc));
- RINOK(Seek(offset));
+ // printf("\n%12x %12x\n", (unsigned)offset, (unsigned)(offset - extent.PosInArc));
+ RINOK(extent.Seek(offset));
}
const size_t kStartSize = 1 << 9;
{
size_t curSize = kStartSize;
- HRESULT res = ReadStream(Stream, _cacheCompressed, &curSize);
- _posInArc += curSize;
- RINOK(res);
+ RINOK(extent.Read(_cacheCompressed, &curSize));
+ // _stream_PackSize += curSize;
if (curSize != kStartSize)
return S_FALSE;
}
- if (Get64(_cacheCompressed) != (cluster << (_clusterBits - 9)))
+ if (Get64(_cacheCompressed) != (cluster << (clusterBits - 9)))
return S_FALSE;
UInt32 dataSize = Get32(_cacheCompressed + 8);
@@ -331,9 +659,8 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
return S_FALSE;
size_t curSize = dataSize2 - kStartSize;
const size_t curSize2 = curSize;
- HRESULT res = ReadStream(Stream, _cacheCompressed + kStartSize, &curSize);
- _posInArc += curSize;
- RINOK(res);
+ RINOK(extent.Read(_cacheCompressed + kStartSize, &curSize));
+ // _stream_PackSize += curSize;
if (curSize != curSize2)
return S_FALSE;
}
@@ -341,6 +668,8 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
_bufInStreamSpec->Init(_cacheCompressed + 12, dataSize);
_cacheCluster = (UInt64)(Int64)-1;
+ _cacheExtent = (unsigned)(int)-1;
+
if (_cache.Size() < clusterSize)
return E_FAIL;
_bufOutStreamSpec->Init(_cache, clusterSize);
@@ -349,16 +678,26 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
UInt64 blockSize64 = clusterSize;
HRESULT res = _zlibDecoderSpec->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL);
- // if (_bufOutStreamSpec->GetPos() != clusterSize)
- // memset(_cache + _bufOutStreamSpec->GetPos(), 0, clusterSize - _bufOutStreamSpec->GetPos());
+ /*
+ if (_bufOutStreamSpec->GetPos() != clusterSize)
+ {
+ _stream_dataError = true;
+ memset(_cache + _bufOutStreamSpec->GetPos(), 0, clusterSize - _bufOutStreamSpec->GetPos());
+ }
+ */
- if (res == S_OK)
if (_bufOutStreamSpec->GetPos() != clusterSize
|| _zlibDecoderSpec->GetInputProcessedSize() != dataSize)
- res = S_FALSE;
+ {
+ _stream_dataError = true;
+ if (res == S_OK)
+ res = S_FALSE;
+ }
RINOK(res);
+
_cacheCluster = cluster;
+ _cacheExtent = extentIndex;
continue;
/*
@@ -371,16 +710,29 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
}
{
offset += lowBits;
- if (offset != _posInArc)
+ if (offset != extent.PosInArc)
{
- // printf("\n%12x %12x\n", (unsigned)offset, (unsigned)(offset - _posInArc));
- RINOK(Seek(offset));
+ // printf("\n%12x %12x\n", (unsigned)offset, (unsigned)(offset - extent.PosInArc));
+ RINOK(extent.Seek(offset));
}
- HRESULT res = Stream->Read(data, size, &size);
- _posInArc += size;
- _virtPos += size;
+ UInt32 size2 = 0;
+ HRESULT res = extent.Stream->Read(data, size, &size2);
+ if (res == S_OK && size2 == 0)
+ {
+ _stream_unavailData = true;
+ /*
+ memset(data, 0, size);
+ _virtPos += size;
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+ */
+ }
+ extent.PosInArc += size2;
+ // _stream_PackSize += size2;
+ _virtPos += size2;
if (processedSize)
- *processedSize = size;
+ *processedSize = size2;
return res;
}
}
@@ -404,9 +756,10 @@ static const Byte kProps[] =
static const Byte kArcProps[] =
{
+ kpidNumVolumes,
+ kpidMethod,
kpidClusterSize,
kpidHeadersSize,
- kpidMethod,
kpidId,
kpidName,
kpidComment
@@ -421,38 +774,72 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
COM_TRY_BEGIN
NCOM::CPropVariant prop;
+ const CExtent *e = NULL;
+ const CDescriptor *desc = NULL;
+
+ if (_isMultiVol)
+ desc = &_descriptor;
+ else if (_extents.Size() == 1)
+ {
+ e = &_extents[0];
+ desc = &e->Descriptor;
+ }
+
switch (propID)
{
case kpidMainSubfile: prop = (UInt32)0; break;
case kpidPhySize: if (_phySize != 0) prop = _phySize; break;
- case kpidClusterSize: prop = (UInt32)1 << _clusterBits; break;
- case kpidHeadersSize: prop = (h.overHead << 9); break;
+ case kpidClusterSize: prop = (UInt32)((UInt32)1 << _clusterBitsMax); break;
+ case kpidHeadersSize: if (e) prop = (e->h.overHead << 9); break;
case kpidMethod:
{
AString s;
- if (!_descriptor.createType.IsEmpty())
- s = _descriptor.createType;
-
- if (h.algo != 0)
+ if (desc && !desc->createType.IsEmpty())
+ s = desc->createType;
+
+ bool zlib = false;
+ bool marker = false;
+ int algo = -1;
+
+ FOR_VECTOR (i, _extents)
{
- s.Add_Space_if_NotEmpty();
- if (h.algo == 1)
- s += "zlib";
- else
+ const CExtent &extent = _extents[i];
+ if (!extent.IsOK || !extent.IsVmdk())
+ continue;
+
+ const CHeader &h = extent.h;
+
+ if (h.algo != 0)
{
- char temp[16];
- ConvertUInt32ToString(h.algo, temp);
- s += temp;
+ if (h.algo == 1)
+ zlib = true;
+ else if (algo != (int)h.algo)
+ {
+ s.Add_Space_if_NotEmpty();
+ char temp[16];
+ ConvertUInt32ToString(h.algo, temp);
+ s += temp;
+ algo = h.algo;
+ }
}
+
+ if (h.Is_Marker())
+ marker = true;
}
-
- if (h.Is_Marker())
+
+ if (zlib)
+ {
+ s.Add_Space_if_NotEmpty();
+ s += "zlib";
+ }
+
+ if (marker)
{
s.Add_Space_if_NotEmpty();
s += "Marker";
}
-
+
if (!s.IsEmpty())
prop = s;
break;
@@ -460,10 +847,10 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidComment:
{
- if (_descriptorBuf.Size() != 0)
+ if (e && e->DescriptorBuf.Size() != 0)
{
AString s;
- s.SetFrom_CalcLen((const char *)(const Byte *)_descriptorBuf, (unsigned)_descriptorBuf.Size());
+ s.SetFrom_CalcLen((const char *)(const Byte *)e->DescriptorBuf, (unsigned)e->DescriptorBuf.Size());
if (!s.IsEmpty() && s.Len() <= (1 << 16))
prop = s;
}
@@ -471,46 +858,38 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
case kpidId:
- if (!_descriptor.CID.IsEmpty())
+ if (desc && !desc->CID.IsEmpty())
{
- prop = _descriptor.CID;
+ prop = desc->CID;
break;
}
case kpidName:
{
- if (_descriptor.Extents.Size() == 1)
+ if (!_isMultiVol && desc && desc->Extents.Size() == 1)
{
- const AString &s = _descriptor.Extents[0];
- if (!s.IsEmpty())
+ const CExtentInfo &ei = desc->Extents[0];
+ if (!ei.FileName.IsEmpty())
{
- if (s.Back() == '"')
- {
- AString s2 = s;
- s2.DeleteBack();
- if (s2.Len() > 5 && StringsAreEqualNoCase_Ascii(s2.RightPtr(5), ".vmdk"))
- {
- int pos = s2.ReverseFind('"');
- if (pos >= 0)
- {
- s2.DeleteFrontal(pos + 1);
- prop = s2;
- }
- }
- }
+ UString u;
+ CDescriptor::GetUnicodeName(ei.FileName, u);
+ if (!u.IsEmpty())
+ prop = u;
}
}
break;
}
-
+
+ case kpidNumVolumes: if (_isMultiVol) prop = (UInt32)_extents.Size(); break;
+
case kpidErrorFlags:
{
UInt32 v = 0;
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;;
if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
- // if (_headerError) v |= kpv_ErrorFlags_HeadersError;
- if (!Stream && v == 0 && _isArc)
- v = kpv_ErrorFlags_HeadersError;
+ if (_unsupportedSome) v |= kpv_ErrorFlags_UnsupportedMethod;
+ if (_headerError) v |= kpv_ErrorFlags_HeadersError;
+ if (_missingVol) v |= kpv_ErrorFlags_UnexpectedEnd;
if (v != 0)
prop = v;
break;
@@ -533,9 +912,22 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
case kpidSize: prop = _size; break;
case kpidPackSize:
{
- UInt64 ov = (h.overHead << 9);
- if (_phySize >= ov)
- prop = _phySize - ov;
+ UInt64 packSize = 0;
+ FOR_VECTOR (i, _extents)
+ {
+ const CExtent &e = _extents[i];
+ if (!e.IsOK)
+ continue;
+ if (e.IsVmdk() && !_isMultiVol)
+ {
+ UInt64 ov = (e.h.overHead << 9);
+ if (e.PhySize >= ov)
+ packSize += e.PhySize - ov;
+ }
+ else
+ packSize += e.PhySize;
+ }
+ prop = packSize;
break;
}
case kpidExtension: prop = (_imgExt ? _imgExt : "img"); break;
@@ -556,19 +948,26 @@ static int inline GetLog(UInt64 num)
}
-HRESULT CHandler::ReadForHeader(IInStream *stream, UInt64 sector, void *data, size_t numSectors)
+HRESULT CExtent::ReadForHeader(IInStream *stream, UInt64 sector, void *data, size_t numSectors)
{
sector <<= 9;
RINOK(stream->Seek(sector, STREAM_SEEK_SET, NULL));
size_t size = numSectors << 9;
RINOK(ReadStream_FALSE(stream, data, size));
UInt64 end = sector + size;
- if (_phySize < end)
- _phySize = end;
+ if (PhySize < end)
+ PhySize = end;
return S_OK;
}
+void CHandler::CloseAtError()
+{
+ _extents.Clear();
+ CHandlerImg::CloseAtError();
+}
+
+
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
{
const unsigned kSectoreSize = 512;
@@ -578,43 +977,242 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
if (headerSize < sizeof(k_Signature))
return S_FALSE;
+
+ CMyComPtr<IArchiveOpenVolumeCallback> volumeCallback;
+
if (memcmp(buf, k_Signature, sizeof(k_Signature)) != 0)
{
const char *kSignature_Descriptor = "# Disk DescriptorFile";
- size_t k_SigDesc_Size = strlen(kSignature_Descriptor);
- if (headerSize >= k_SigDesc_Size)
- if (memcmp(buf, kSignature_Descriptor, k_SigDesc_Size) == 0)
+ const size_t k_SigDesc_Size = strlen(kSignature_Descriptor);
+ if (headerSize < k_SigDesc_Size)
+ return S_FALSE;
+ if (memcmp(buf, kSignature_Descriptor, k_SigDesc_Size) != 0)
+ return S_FALSE;
+
+ UInt64 endPos;
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
+ if (endPos > (1 << 20))
+ return S_FALSE;
+ const size_t numBytes = (size_t)endPos;
+ _descriptorBuf.Alloc(numBytes);
+ RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
+ RINOK(ReadStream_FALSE(stream, _descriptorBuf, numBytes));
+
+ if (!_descriptor.Parse(_descriptorBuf, _descriptorBuf.Size()))
+ return S_FALSE;
+ _isMultiVol = true;
+ _isArc = true;
+ _phySize = numBytes;
+ if (_descriptor.IsThere_Parent())
+ _unsupported = true;
+
+ if (openCallback)
+ {
+ openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback);
+ }
+ if (!volumeCallback)
+ {
+ _unsupported = true;
+ return E_NOTIMPL;
+ }
+
+ /*
+ UInt64 totalVirtSize = 0;
+ FOR_VECTOR (i, _descriptor.Extents)
+ {
+ const CExtentInfo &ei = _descriptor.Extents[i];
+ if (ei.NumSectors >= ((UInt64)1 << (63 - 9)))
+ return S_FALSE;
+ totalVirtSize += ei.NumSectors;
+ if (totalVirtSize >= ((UInt64)1 << (63 - 9)))
+ return S_FALSE;
+ }
+ totalVirtSize <<= 9;
+ */
+
+ if (_descriptor.Extents.Size() > 1)
+ {
+ const UInt64 numFiles = _descriptor.Extents.Size();
+ RINOK(openCallback->SetTotal(&numFiles, NULL));
+ }
+ }
+
+ UInt64 complexity = 0;
+
+ for (;;)
+ {
+ CExtent *e = NULL;
+ CMyComPtr<IInStream> nextStream;
+
+ if (_isMultiVol)
+ {
+ const unsigned extentIndex = _extents.Size();
+ if (extentIndex >= _descriptor.Extents.Size())
+ break;
+ const CExtentInfo &ei = _descriptor.Extents[extentIndex];
+ e = &_extents.AddNew();
+ e->StartOffset = 0;
+ if (ei.NumSectors >= ((UInt64)1 << (62 - 9)) ||
+ ei.StartSector >= ((UInt64)1 << (62 - 9)))
+ return S_FALSE;
+ e->NumBytes = ei.NumSectors << 9;
+ e->IsZero = ei.IsType_ZERO();
+ if (extentIndex != 0)
+ e->StartOffset = _extents[extentIndex - 1].GetEndOffset();
+ if (e->GetEndOffset() < e->StartOffset)
+ return S_FALSE;
+
+ e->VirtSize = e->NumBytes;
+ if (e->IsZero)
{
- _unsupported = true;
- _isArc = true;
- // return E_NOTIMPL;
+ e->IsOK = true;
+ continue;
}
- return S_FALSE;
+
+ e->IsFlat = ei.IsType_Flat();
+ e->FlatOffset = ei.StartSector << 9;
+
+ UString u;
+ CDescriptor::GetUnicodeName(ei.FileName, u);
+ if (u.IsEmpty())
+ {
+ _missingVol = true;
+ continue;
+ }
+
+ HRESULT result = volumeCallback->GetStream(u, &nextStream);
+ if (result == S_FALSE)
+ {
+ _missingVol = true;
+ continue;
+ }
+ if (result != S_OK)
+ return result;
+ if (!nextStream)
+ {
+ _missingVol = true;
+ continue;
+ }
+
+ if (e->IsFlat)
+ {
+ e->IsOK = true;
+ e->Stream = nextStream;
+ e->PhySize = e->NumBytes;
+ continue;
+ }
+
+ stream = nextStream;
+
+ headerSize = kSectoreSize;
+ RINOK(ReadStream(stream, buf, &headerSize));
+
+ if (headerSize != kSectoreSize)
+ continue;
+ if (memcmp(buf, k_Signature, sizeof(k_Signature)) != 0)
+ continue;
+ }
+ else
+ {
+ if (headerSize != kSectoreSize)
+ return S_FALSE;
+ e = &_extents.AddNew();
+ e->StartOffset = 0;
+ }
+
+ HRESULT res = S_FALSE;
+ if (e->h.Parse(buf))
+ res = e->Open3(stream, openCallback, _isMultiVol ? _descriptor.Extents.Size() : 1, _extents.Size() - 1, complexity);
+
+ if (!_isMultiVol)
+ {
+ _isArc = e->IsArc;
+ _phySize = e->PhySize;
+ _unsupported = e->Unsupported;
+ }
+
+ if (e->Unsupported)
+ _unsupportedSome = true;
+ if (e->HeadersError)
+ _headerError = true;
+
+ if (res != S_OK)
+ {
+ if (res != S_FALSE)
+ return res;
+ if (!_isMultiVol)
+ return res;
+ continue;
+ }
+
+ e->Stream = stream;
+ e->IsOK = true;
+
+ if (!_isMultiVol)
+ {
+ e->NumBytes = e->VirtSize;
+ break;
+ }
+
+ if (e->NumBytes != e->VirtSize)
+ _headerError = true;
}
- if (headerSize != kSectoreSize)
- return S_FALSE;
+ if (!_extents.IsEmpty())
+ _size = _extents.Back().GetEndOffset();
- // CHeader h;
+ _needDeflate = false;
+ _clusterBitsMax = 0;
+
+ unsigned numOKs = 0;
+ unsigned numUnsupported = 0;
- if (!h.Parse(buf))
- return S_FALSE;
+ FOR_VECTOR (i, _extents)
+ {
+ const CExtent &e = _extents[i];
+ if (e.Unsupported)
+ numUnsupported++;
+ if (!e.IsOK)
+ continue;
+ numOKs++;
+ if (e.IsVmdk())
+ {
+ if (e.NeedDeflate)
+ _needDeflate = true;
+ if (_clusterBitsMax < e.ClusterBits)
+ _clusterBitsMax = e.ClusterBits;
+ }
+ }
+
+ if (numUnsupported != 0 && numUnsupported == _extents.Size())
+ _unsupported = true;
+
+ return S_OK;
+}
+
+HRESULT CExtent::Open3(IInStream *stream, IArchiveOpenCallback *openCallback,
+ unsigned numVols, unsigned volIndex, UInt64 &complexity)
+{
if (h.descriptorSize != 0)
{
- if (h.descriptorOffset < 1)
- return S_FALSE;
- if (h.descriptorSize > (1 << 20))
+ if (h.descriptorOffset == 0 ||
+ h.descriptorSize > (1 << 10))
return S_FALSE;
- size_t numBytes = (size_t)h.descriptorSize << 9;
- _descriptorBuf.Alloc(numBytes);
- RINOK(ReadForHeader(stream, h.descriptorOffset, _descriptorBuf, (size_t)h.descriptorSize));
- if (h.descriptorOffset == 1 && h.Is_Marker() && Get64(_descriptorBuf) == 0)
+ DescriptorBuf.Alloc((size_t)h.descriptorSize << 9);
+ RINOK(ReadForHeader(stream, h.descriptorOffset, DescriptorBuf, (size_t)h.descriptorSize));
+ if (h.descriptorOffset == 1 && h.Is_Marker() && Get64(DescriptorBuf) == 0)
{
// We check data as end marker.
// and if probably it's footer's copy of header, we don't want to open it.
return S_FALSE;
}
+
+ DescriptorOK = Descriptor.Parse(DescriptorBuf, DescriptorBuf.Size());
+ if (!DescriptorOK)
+ HeadersError = true;
+ if (Descriptor.IsThere_Parent())
+ Unsupported = true;
}
if (h.gdOffset == (UInt64)(Int64)-1)
@@ -647,7 +1245,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
m.Parse(buf2 + 512 * 2);
if (m.NumSectors != 0 || m.SpecSize != 0 || m.Type != k_Marker_END_OF_STREAM)
return S_FALSE;
- _phySize = endPos;
+ PhySize = endPos;
}
int grainSize_Log = GetLog(h.grainSize);
@@ -658,27 +1256,27 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
if (h.overHead >= ((UInt64)1 << (63 - 9)))
return S_FALSE;
- _isArc = true;
- _clusterBits = (9 + grainSize_Log);
- _size = h.capacity << 9;
- _needDeflate = (h.algo >= 1);
+ IsArc = true;
+ ClusterBits = (9 + grainSize_Log);
+ VirtSize = h.capacity << 9;
+ NeedDeflate = (h.algo >= 1);
if (h.Is_Compressed() ? (h.algo > 1 || !h.Is_Marker()) : (h.algo != 0))
{
- _unsupported = true;
- _phySize = 0;
+ Unsupported = true;
+ PhySize = 0;
return S_FALSE;
}
{
UInt64 overHeadBytes = h.overHead << 9;
- if (_phySize < overHeadBytes)
- _phySize = overHeadBytes;
+ if (PhySize < overHeadBytes)
+ PhySize = overHeadBytes;
}
- _zeroSector = 0;
+ ZeroSector = 0;
if (h.Is_ZeroGrain())
- _zeroSector = 1;
+ ZeroSector = 1;
const UInt64 numSectorsPerGde = (UInt64)1 << (grainSize_Log + k_NumMidBits);
const UInt64 numGdeEntries = (h.capacity + numSectorsPerGde - 1) >> (grainSize_Log + k_NumMidBits);
@@ -713,12 +1311,22 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
RINOK(ReadForHeader(stream, h.gdOffset, table, numSectors));
}
- size_t clusterSize = (size_t)1 << _clusterBits;
+ const size_t clusterSize = (size_t)1 << ClusterBits;
+
+ const UInt64 complexityStart = complexity;
if (openCallback)
{
- UInt64 totalBytes = (UInt64)numGdeEntries << (k_NumMidBits + 2);
- RINOK(openCallback->SetTotal(NULL, &totalBytes));
+ complexity += (UInt64)numGdeEntries << (k_NumMidBits + 2);
+ {
+ const UInt64 numVols2 = numVols;
+ RINOK(openCallback->SetTotal((numVols == 1) ? NULL : &numVols2, &complexity));
+ }
+ if (numVols != 1)
+ {
+ const UInt64 volIndex2 = volIndex;
+ RINOK(openCallback->SetCompleted(numVols == 1 ? NULL : &volIndex2, &complexityStart));
+ }
}
UInt64 lastSector = 0;
@@ -728,14 +1336,14 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
for (size_t i = 0; i < numGdeEntries; i++)
{
UInt32 v = Get32((const Byte *)table + (size_t)i * 4);
- CByteBuffer &buf = _tables.AddNew();
- if (v == 0 || v == _zeroSector)
+ CByteBuffer &buf = Tables.AddNew();
+ if (v == 0 || v == ZeroSector)
continue;
-
- if (openCallback && ((i - numProcessed_Prev) & 0xFFF) == 0)
+ if (openCallback && (i - numProcessed_Prev) >= 1024)
{
- UInt64 numBytes = (UInt64)i << (k_NumMidBits + 2);
- RINOK(openCallback->SetCompleted(NULL, &numBytes));
+ const UInt64 comp = complexityStart + ((UInt64)i << (k_NumMidBits + 2));
+ const UInt64 volIndex2 = volIndex;
+ RINOK(openCallback->SetCompleted(numVols == 1 ? NULL : &volIndex2, &comp));
numProcessed_Prev = i;
}
@@ -764,25 +1372,24 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
for (size_t k = 0; k < k_NumMidItems; k++)
{
UInt32 v = Get32((const Byte *)buf + (size_t)k * 4);
- if (v == 0 || v == _zeroSector)
+ if (v == 0 || v == ZeroSector)
continue;
if (v < h.overHead)
return S_FALSE;
if (lastSector < v)
{
lastSector = v;
- if (_needDeflate)
+ if (NeedDeflate)
lastVirtCluster = ((UInt64)i << k_NumMidBits) + k;
}
}
}
-
- if (!_needDeflate)
+ if (!NeedDeflate)
{
UInt64 end = ((UInt64)lastSector << 9) + clusterSize;
- if (_phySize < end)
- _phySize = end;
+ if (PhySize < end)
+ PhySize = end;
}
else if (lastSector != 0)
{
@@ -790,27 +1397,18 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
if (ReadForHeader(stream, lastSector, buf, 1) == S_OK)
{
UInt64 lba = Get64(buf);
- if (lba == (lastVirtCluster << (_clusterBits - 9)))
+ if (lba == (lastVirtCluster << (ClusterBits - 9)))
{
UInt32 dataSize = Get32(buf + 8);
size_t dataSize2 = (size_t)dataSize + 12;
dataSize2 = (dataSize2 + 511) & ~(size_t)511;
UInt64 end = ((UInt64)lastSector << 9) + dataSize2;
- if (_phySize < end)
- _phySize = end;
+ if (PhySize < end)
+ PhySize = end;
}
}
}
- if (_descriptorBuf.Size() != 0)
- {
- _descriptor.Parse(_descriptorBuf, _descriptorBuf.Size());
- if (!_descriptor.parentCID.IsEmpty())
- if (!_descriptor.parentCID.IsEqualTo_Ascii_NoCase("ffffffff"))
- _unsupported = true;
- }
-
- Stream = stream;
return S_OK;
}
@@ -819,21 +1417,26 @@ STDMETHODIMP CHandler::Close()
{
_phySize = 0;
_size = 0;
+
_cacheCluster = (UInt64)(Int64)-1;
- _zeroSector = 0;
- _clusterBits = 0;
+ _cacheExtent = (unsigned)(int)-1;
+
+ _clusterBitsMax = 0;
- _needDeflate = false;
_isArc = false;
_unsupported = false;
- // _headerError = false;
+ _unsupportedSome = false;
+ _headerError = false;
+ _missingVol = false;
+ _isMultiVol = false;
+ _needDeflate = false;
- _tables.Clear();
_descriptorBuf.Free();
_descriptor.Clear();
_imgExt = NULL;
- Stream.Release();
+ Stream.Release(); // Stream vriable is unused
+ _extents.Clear();
return S_OK;
}
@@ -846,6 +1449,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
if (_unsupported)
return S_FALSE;
+ ClearStreamVars();
+ // _stream_UsePackSize = true;
if (_needDeflate)
{
@@ -867,13 +1472,18 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
_zlibDecoder = _zlibDecoderSpec;
}
- size_t clusterSize = (size_t)1 << _clusterBits;
+ const size_t clusterSize = (size_t)1 << _clusterBitsMax;
_cache.AllocAtLeast(clusterSize);
_cacheCompressed.AllocAtLeast(clusterSize * 2);
}
+ FOR_VECTOR (i, _extents)
+ {
+ RINOK(_extents[i].InitAndSeek());
+ }
+
CMyComPtr<ISequentialInStream> streamTemp = this;
- RINOK(InitAndSeek());
+ InitAndSeekMain();
*stream = streamTemp.Detach();
return S_OK;
COM_TRY_END
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index d4b321dc..3128939e 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -723,7 +723,7 @@ static HRESULT Update2(
CThreads threads;
CRecordVector<HANDLE> compressingCompletedEvents;
- CRecordVector<int> threadIndices; // list threads in order of updateItems
+ CUIntVector threadIndices; // list threads in order of updateItems
{
RINOK(memManager.AllocateSpaceAlways((size_t)numThreads * (kMemPerThread / kBlockSize)));
@@ -759,7 +759,7 @@ static HRESULT Update2(
while (itemIndex < updateItems.Size())
{
- if ((UInt32)threadIndices.Size() < numThreads && mtItemIndex < updateItems.Size())
+ if (threadIndices.Size() < numThreads && mtItemIndex < updateItems.Size())
{
CUpdateItem &ui = updateItems[mtItemIndex++];
if (!ui.NewData)
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
index 0e8586e9..5ca288f4 100644
--- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
@@ -513,10 +513,11 @@ static int main2(int numArgs, const char *args[])
if (parser[NKey::kEOS].ThereIs || stdInMode)
throw "Can not use stdin in this mode";
- if (fileSize > 0xF0000000)
- throw "File is too big";
-
size_t inSize = (size_t)fileSize;
+
+ if (inSize != fileSize)
+ throw "File is too big";
+
Byte *inBuffer = NULL;
if (inSize != 0)
@@ -535,7 +536,13 @@ static int main2(int numArgs, const char *args[])
if (encodeMode)
{
// we allocate 105% of original size for output buffer
- outSize = (size_t)fileSize / 20 * 21 + (1 << 16);
+ UInt64 outSize64 = fileSize / 20 * 21 + (1 << 16);
+
+ outSize = (size_t)outSize64;
+
+ if (outSize != outSize64)
+ throw "File is too big";
+
if (outSize != 0)
{
outBuffer = (Byte *)MyAlloc((size_t)outSize);
@@ -561,7 +568,7 @@ static int main2(int numArgs, const char *args[])
outSize = (size_t)outSize64;
if (outSize != outSize64)
- throw "too big";
+ throw "Unpack size is too big";
if (outSize != 0)
{
outBuffer = (Byte *)MyAlloc(outSize);
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
index 47f36c84..f8267a11 100644
--- a/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
@@ -366,6 +366,10 @@ SOURCE=..\..\..\..\C\7zCrcOpt.c
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\7zTypes.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Alloc.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
@@ -464,10 +468,6 @@ SOURCE=..\..\..\..\C\Threads.c
SOURCE=..\..\..\..\C\Threads.h
# End Source File
-# Begin Source File
-
-SOURCE=..\..\..\..\C\Types.h
-# End Source File
# End Group
# Begin Source File
diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp
index 77665ae1..c7962167 100644
--- a/CPP/7zip/Common/LimitedStreams.cpp
+++ b/CPP/7zip/Common/LimitedStreams.cpp
@@ -86,26 +86,34 @@ STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSi
*processedSize = 0;
if (_virtPos >= Size)
return S_OK;
+ {
+ UInt64 rem = Size - _virtPos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+ if (size == 0)
+ return S_OK;
if (_curRem == 0)
{
- UInt32 blockSize = (UInt32)1 << BlockSizeLog;
- UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog);
- UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);
- UInt32 phyBlock = Vector[virtBlock];
+ const UInt32 blockSize = (UInt32)1 << BlockSizeLog;
+ const UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog);
+ const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);
+ const UInt32 phyBlock = Vector[virtBlock];
+
UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock;
if (newPos != _physPos)
{
_physPos = newPos;
RINOK(SeekToPhys());
}
+
_curRem = blockSize - offsetInBlock;
+
for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++)
_curRem += (UInt32)1 << BlockSizeLog;
- UInt64 rem = Size - _virtPos;
- if (_curRem > rem)
- _curRem = (UInt32)rem;
}
+
if (size > _curRem)
size = _curRem;
HRESULT res = Stream->Read(data, size, &size);
diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h
index a9378491..b521eeb9 100644
--- a/CPP/7zip/Common/LimitedStreams.h
+++ b/CPP/7zip/Common/LimitedStreams.h
@@ -73,11 +73,11 @@ class CClusterInStream:
UInt64 _physPos;
UInt32 _curRem;
public:
- CMyComPtr<IInStream> Stream;
- UInt64 StartOffset;
- UInt64 Size;
unsigned BlockSizeLog;
+ UInt64 Size;
+ CMyComPtr<IInStream> Stream;
CRecordVector<UInt32> Vector;
+ UInt64 StartOffset;
HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp
index 7c1e9979..a5149ab5 100644
--- a/CPP/7zip/Common/MethodProps.cpp
+++ b/CPP/7zip/Common/MethodProps.cpp
@@ -90,51 +90,65 @@ HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 default
return ParsePropToUInt32(name, prop, numThreads);
}
-static HRESULT StringToDictSize(const UString &s, UInt32 &dicSize)
+
+static HRESULT StringToDictSize(const UString &s, NCOM::CPropVariant &destProp)
{
const wchar_t *end;
UInt32 number = ConvertStringToUInt32(s, &end);
unsigned numDigits = (unsigned)(end - s);
if (numDigits == 0 || s.Len() > numDigits + 1)
return E_INVALIDARG;
- const unsigned kLogDictSizeLimit = 32;
+
if (s.Len() == numDigits)
{
- if (number >= kLogDictSizeLimit)
+ if (number >= 64)
return E_INVALIDARG;
- dicSize = (UInt32)1 << (unsigned)number;
+ if (number < 32)
+ destProp = (UInt32)((UInt32)1 << (unsigned)number);
+ else
+ destProp = (UInt64)((UInt64)1 << (unsigned)number);
return S_OK;
}
+
unsigned numBits;
+
switch (MyCharLower_Ascii(s[numDigits]))
{
- case 'b': dicSize = number; return S_OK;
+ case 'b': destProp = number; return S_OK;
case 'k': numBits = 10; break;
case 'm': numBits = 20; break;
case 'g': numBits = 30; break;
default: return E_INVALIDARG;
}
- if (number >= ((UInt32)1 << (kLogDictSizeLimit - numBits)))
- return E_INVALIDARG;
- dicSize = number << numBits;
+
+ if (number < ((UInt32)1 << (32 - numBits)))
+ destProp = (UInt32)(number << numBits);
+ else
+ destProp = (UInt64)((UInt64)number << numBits);
+
return S_OK;
}
-static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, UInt32 &resValue)
+
+static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, NCOM::CPropVariant &destProp)
{
if (prop.vt == VT_UI4)
{
UInt32 v = prop.ulVal;
- if (v >= 32)
+ if (v >= 64)
return E_INVALIDARG;
- resValue = (UInt32)1 << v;
+ if (v < 32)
+ destProp = (UInt32)((UInt32)1 << (unsigned)v);
+ else
+ destProp = (UInt64)((UInt64)1 << (unsigned)v);
return S_OK;
}
if (prop.vt == VT_BSTR)
- return StringToDictSize(prop.bstrVal, resValue);
+ return StringToDictSize(prop.bstrVal, destProp);
return E_INVALIDARG;
}
+
void CProps::AddProp32(PROPID propid, UInt32 level)
{
CProp &prop = Props.AddNew();
@@ -275,10 +289,10 @@ static void SplitParams(const UString &srcString, UStringVector &subStrings)
{
subStrings.Clear();
UString s;
- int len = srcString.Len();
+ unsigned len = srcString.Len();
if (len == 0)
return;
- for (int i = 0; i < len; i++)
+ for (unsigned i = 0; i < len; i++)
{
wchar_t c = srcString[i];
if (c == L':')
@@ -336,9 +350,7 @@ HRESULT CMethodProps::SetParam(const UString &name, const UString &value)
if (IsLogSizeProp(prop.Id))
{
- UInt32 dicSize;
- RINOK(StringToDictSize(value, dicSize));
- prop.Value = dicSize;
+ RINOK(StringToDictSize(value, prop.Value));
}
else
{
@@ -406,9 +418,7 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const
if (IsLogSizeProp(prop.Id))
{
- UInt32 dicSize;
- RINOK(PROPVARIANT_to_DictSize(value, dicSize));
- prop.Value = dicSize;
+ RINOK(PROPVARIANT_to_DictSize(value, prop.Value));
}
else
{
diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp
index dea297c4..06a11f10 100644
--- a/CPP/7zip/Compress/Lzma2Encoder.cpp
+++ b/CPP/7zip/Compress/Lzma2Encoder.cpp
@@ -38,7 +38,20 @@ HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzm
switch (propID)
{
case NCoderPropID::kBlockSize:
- if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.blockSize = prop.ulVal; break;
+ {
+ if (prop.vt == VT_UI4)
+ lzma2Props.blockSize = prop.ulVal;
+ else if (prop.vt == VT_UI8)
+ {
+ size_t v = (size_t)prop.uhVal.QuadPart;
+ if (v != prop.uhVal.QuadPart)
+ return E_INVALIDARG;
+ lzma2Props.blockSize = v;
+ }
+ else
+ return E_INVALIDARG;
+ break;
+ }
case NCoderPropID::kNumThreads:
if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.numTotalThreads = (int)(prop.ulVal); break;
default:
diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp
index e13061ae..c6522fe7 100644
--- a/CPP/7zip/UI/Client7z/Client7z.cpp
+++ b/CPP/7zip/UI/Client7z/Client7z.cpp
@@ -441,7 +441,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
}
}
- if (_outFileStream != NULL)
+ if (_outFileStream)
{
if (_processedFileInfo.MTimeDefined)
_outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);
@@ -499,7 +499,6 @@ public:
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
// IUpdateCallback2
- STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);
STDMETHOD(GetUpdateItemInfo)(UInt32 index,
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
@@ -551,20 +550,14 @@ STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValu
return S_OK;
}
-
-STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */)
-{
- return E_NOTIMPL;
-}
-
STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */,
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
{
- if (newData != NULL)
+ if (newData)
*newData = BoolToInt(true);
- if (newProperties != NULL)
+ if (newProperties)
*newProperties = BoolToInt(true);
- if (indexInArchive != NULL)
+ if (indexInArchive)
*indexInArchive = (UInt32)(Int32)-1;
return S_OK;
}
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
index b07b1dc6..cc0b1f93 100644
--- a/CPP/7zip/UI/Console/Main.cpp
+++ b/CPP/7zip/UI/Console/Main.cpp
@@ -108,34 +108,52 @@ static const char *kHelpString =
" h : Calculate hash values for files\n"
" i : Show information about supported formats\n"
" l : List contents of archive\n"
-// " l[a|t][f] : List contents of archive\n"
-// " a - with Additional fields\n"
-// " t - with all fields\n"
-// " f - with Full pathnames\n"
" rn : Rename files in archive\n"
" t : Test integrity of archive\n"
" u : Update files to archive\n"
" x : eXtract files with full paths\n"
+ "\n"
"<Switches>\n"
" -- : Stop switches parsing\n"
" -ai[r[-|0]]{@listfile|!wildcard} : Include archives\n"
" -ax[r[-|0]]{@listfile|!wildcard} : eXclude archives\n"
- " -bd : Disable percentage indicator\n"
+ " -ao{a|s|t|u} : set Overwrite mode\n"
+ " -an : disable archive_name field\n"
+ " -bb[0-3] : set output log level\n"
+ " -bd : disable progress indicator\n"
+ " -bs{o|e|p}{0|1|2} : set output stream for output/error/progress line\n"
+ " -bt : show execution time statistics\n"
" -i[r[-|0]]{@listfile|!wildcard} : Include filenames\n"
" -m{Parameters} : set compression Method\n"
+ " -mmt[N] : set number of CPU threads\n"
" -o{Directory} : set Output directory\n"
#ifndef _NO_CRYPTO
" -p{Password} : set Password\n"
#endif
" -r[-|0] : Recurse subdirectories\n"
+ " -sa{a|e|s} : set Archive name mode\n"
+ " -scc{UTF-8|WIN|DOS} : set charset for for console input/output\n"
" -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n"
- " -sdel : Delete files after compression\n"
+ " -scrc[CRC32|CRC64|SHA1|SHA256|*] : set hash function for x, e, h commands\n"
+ " -sdel : delete files after compression\n"
+ " -seml[.] : send archive by email\n"
" -sfx[{name}] : Create SFX archive\n"
" -si[{name}] : read data from stdin\n"
+ " -slp : set Large Pages mode\n"
" -slt : show technical information for l (List) command\n"
+ " -snh : store hard links as links\n"
+ " -snl : store symbolic links as links\n"
+ " -sni : store NT security information\n"
+ " -sns[-] : store NTFS alternate streams\n"
" -so : write data to stdout\n"
+ " -spd : disable wildcard matching for file names\n"
+ " -spe : eliminate duplication of root folder for extract command\n"
+ " -spf : use fully qualified file paths\n"
" -ssc[-] : set sensitive case mode\n"
" -ssw : compress shared files\n"
+ " -stl : set archive timestamp from the most recently modified file\n"
+ " -stm{HexMask} : set CPU thread affinity mask (hexadecimal number)\n"
+ " -stx{Type} : exclude archive type\n"
" -t{Type} : Set type of archive\n"
" -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n"
" -v{Size}[b|k|m|g] : Create volumes\n"
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
index 8bf40f5e..6658923f 100644
--- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
+++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
@@ -85,7 +85,7 @@ public:
CRecordVector<bool> NeedWait;
~CChildProcesses() { CloseAll(); }
- void DisableWait(int index) { NeedWait[index] = false; }
+ void DisableWait(unsigned index) { NeedWait[index] = false; }
void CloseAll()
{
@@ -491,7 +491,19 @@ typedef BOOL (WINAPI * ShellExecuteExWP)(LPSHELLEXECUTEINFOW lpExecInfo);
static HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process)
{
+ UString path2 = path;
+
+ #ifdef _WIN32
+ {
+ int dot = path2.ReverseFind_Dot();
+ int separ = path2.ReverseFind_PathSepar();
+ if (dot < 0 || dot < separ)
+ path2 += L'.';
+ }
+ #endif
+
UINT32 result;
+
#ifndef _UNICODE
if (g_IsNT)
{
@@ -500,14 +512,14 @@ static HRESULT StartApplication(const UString &dir, const UString &path, HWND wi
execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
execInfo.hwnd = NULL;
execInfo.lpVerb = NULL;
- execInfo.lpFile = path;
+ execInfo.lpFile = path2;
execInfo.lpParameters = NULL;
execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir;
execInfo.nShow = SW_SHOWNORMAL;
execInfo.hProcess = 0;
ShellExecuteExWP shellExecuteExW = (ShellExecuteExWP)
::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "ShellExecuteExW");
- if (shellExecuteExW == 0)
+ if (!shellExecuteExW)
return 0;
shellExecuteExW(&execInfo);
result = (UINT32)(UINT_PTR)execInfo.hInstApp;
@@ -525,23 +537,24 @@ static HRESULT StartApplication(const UString &dir, const UString &path, HWND wi
;
execInfo.hwnd = NULL;
execInfo.lpVerb = NULL;
- const CSysString sysPath = GetSystemString(path);
+ const CSysString sysPath = GetSystemString(path2);
const CSysString sysDir = GetSystemString(dir);
execInfo.lpFile = sysPath;
execInfo.lpParameters = NULL;
execInfo.lpDirectory =
- #ifdef UNDER_CE
- NULL
- #else
- sysDir.IsEmpty() ? NULL : (LPCTSTR)sysDir
- #endif
- ;
+ #ifdef UNDER_CE
+ NULL
+ #else
+ sysDir.IsEmpty() ? NULL : (LPCTSTR)sysDir
+ #endif
+ ;
execInfo.nShow = SW_SHOWNORMAL;
execInfo.hProcess = 0;
::ShellExecuteEx(&execInfo);
result = (UINT32)(UINT_PTR)execInfo.hInstApp;
process.Attach(execInfo.hProcess);
}
+
if (result <= 32)
{
switch (result)
@@ -553,6 +566,7 @@ static HRESULT StartApplication(const UString &dir, const UString &path, HWND wi
L"7-Zip", MB_OK | MB_ICONSTOP);
}
}
+
return S_OK;
}
@@ -795,7 +809,7 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param)
for (;;)
{
CRecordVector<HANDLE> handles;
- CRecordVector<int> indices;
+ CUIntVector indices;
FOR_VECTOR (i, processes.Handles)
{
@@ -992,6 +1006,17 @@ static HRESULT GetTime(IFolderFolder *folder, UInt32 index, PROPID propID, FILET
}
*/
+
+/*
+tryInternal tryExternal
+ false false : unused
+ false true : external
+ true false : internal
+ true true : smart based on file extension:
+ !alwaysStart(name) : both
+ alwaysStart(name) : external
+*/
+
void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode, bool useEditor, const wchar_t *type)
{
const UString name = GetItemName(index);
@@ -1008,7 +1033,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
bool tryAsArchive = tryInternal && (!tryExternal || !DoItemAlwaysStart(name));
- UString fullVirtPath = _currentFolderPrefix + relPath;
+ const UString fullVirtPath = _currentFolderPrefix + relPath;
CTempDir tempDirectory;
if (!tempDirectory.Create(kTempDirPrefix))
@@ -1058,6 +1083,8 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
// probably we must show some message here
// return;
}
+ if (!tryExternal)
+ return;
}
}
}
@@ -1126,6 +1153,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
options.folder = fs2us(tempDirNorm);
options.showErrorMessages = true;
+
HRESULT result = CopyTo(options, indices, &messages, usePassword, password);
if (_parentFolders.Size() > 0)
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
index dc828e72..378ad903 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
@@ -8,12 +8,13 @@
#include "../../../Windows/Control/Static.h"
#include "../../../Windows/ErrorMsg.h"
-#include "ProgressDialog2.h"
-#include "DialogSize.h"
+#include "../GUI/ExtractRes.h"
-#include "ProgressDialog2Res.h"
+#include "LangUtils.h"
-#include "../GUI/ExtractRes.h"
+#include "DialogSize.h"
+#include "ProgressDialog2.h"
+#include "ProgressDialog2Res.h"
using namespace NWindows;
@@ -42,8 +43,6 @@ static const UINT kCreateDelay =
static const DWORD kPauseSleepTime = 100;
-#include "LangUtils.h"
-
#ifdef LANG
static const UInt32 kLangIDs[] =
@@ -705,10 +704,9 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
UInt32 curTime = ::GetTickCount();
+ const UInt64 progressTotal = bytesProgressMode ? total : totalFiles;
+ const UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles;
{
- UInt64 progressTotal = bytesProgressMode ? total : totalFiles;
- UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles;
-
if (IS_UNDEFINED_VAL(progressTotal))
{
// SetPos(0);
@@ -757,9 +755,9 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
}
}
- if (completed != 0)
+ if (progressCompleted != 0)
{
- if (IS_UNDEFINED_VAL(total))
+ if (IS_UNDEFINED_VAL(progressTotal))
{
if (IS_DEFINED_VAL(_prevRemainingSec))
{
@@ -770,8 +768,8 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
else
{
UInt64 remainingTime = 0;
- if (completed < total)
- remainingTime = MyMultAndDiv(_elapsedTime, total - completed, completed);
+ if (progressCompleted < progressTotal)
+ remainingTime = MyMultAndDiv(_elapsedTime, progressTotal - progressCompleted, progressCompleted);
UInt64 remainingSec = remainingTime / 1000;
if (remainingSec != _prevRemainingSec)
{
@@ -783,7 +781,7 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
}
{
UInt64 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime;
- UInt64 v = (completed * 1000) / elapsedTime;
+ UInt64 v = (progressCompleted * 1000) / elapsedTime;
Byte c = 0;
unsigned moveBits = 0;
if (v >= ((UInt64)10000 << 10)) { moveBits = 20; c = 'M'; }
@@ -811,11 +809,11 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
{
UInt64 percent = 0;
{
- if (IS_DEFINED_VAL(total))
+ if (IS_DEFINED_VAL(progressTotal))
{
- percent = completed * 100;
- if (total != 0)
- percent /= total;
+ percent = progressCompleted * 100;
+ if (progressTotal != 0)
+ percent /= progressTotal;
}
}
if (percent != _prevPercentValue)
diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp
index 9e36c634..e95cbd2b 100644
--- a/CPP/Windows/PropVariant.cpp
+++ b/CPP/Windows/PropVariant.cpp
@@ -40,7 +40,10 @@ HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw()
{
p->bstrVal = AllocBstrFromAscii(s);
if (p->bstrVal)
+ {
+ p->vt = VT_BSTR;
return S_OK;
+ }
p->vt = VT_ERROR;
p->scode = E_OUTOFMEMORY;
return E_OUTOFMEMORY;
diff --git a/DOC/7zip.inf b/DOC/7zip.inf
index ab3dcf0b..aa04c257 100644
--- a/DOC/7zip.inf
+++ b/DOC/7zip.inf
@@ -10,8 +10,8 @@ AppName = "7-Zip"
InstallDir = %CE1%\%AppName%
[Strings]
-AppVer = "15.08"
-AppDate = "2015-10-01"
+AppVer = "15.09"
+AppDate = "2015-10-16"
[CEDevice]
; ProcessorType = 2577 ; ARM
diff --git a/DOC/7zip.nsi b/DOC/7zip.nsi
index b8bbe319..89104873 100644
--- a/DOC/7zip.nsi
+++ b/DOC/7zip.nsi
@@ -2,7 +2,7 @@
;Defines
!define VERSION_MAJOR 15
-!define VERSION_MINOR 08
+!define VERSION_MINOR 09
!define VERSION_POSTFIX_FULL " beta"
!ifdef WIN64
!ifdef IA64
diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs
index fe7e115a..c8945429 100644
--- a/DOC/7zip.wxs
+++ b/DOC/7zip.wxs
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<?define VerMajor = "15" ?>
-<?define VerMinor = "08" ?>
+<?define VerMinor = "09" ?>
<?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>
diff --git a/DOC/readme.txt b/DOC/readme.txt
index 4f5f9124..b08f4a72 100644
--- a/DOC/readme.txt
+++ b/DOC/readme.txt
@@ -1,4 +1,4 @@
-7-Zip 15.08 Sources
+7-Zip 15.09 Sources
-------------------
7-Zip is a file archiver for Windows.
diff --git a/DOC/src-history.txt b/DOC/src-history.txt
index c17689c1..9f0b9488 100644
--- a/DOC/src-history.txt
+++ b/DOC/src-history.txt
@@ -1,6 +1,20 @@
HISTORY of the 7-Zip source code
--------------------------------
+15.09 beta 2015-10-16
+-------------------------
+- The BUG in LZMA / LZMA2 encoding code was fixed.
+ The BUG in LzFind.c::MatchFinder_ReadBlock() function.
+ If input data size is larger than (4 GiB - dictionary_size),
+ the following code worked incorrectly:
+ - LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions
+ for compressing from memory to memory.
+ That BUG is not related to LZMA encoder version that works via streams.
+ - LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if
+ default value of chunk size (CLzma2EncProps::blockSize) is changed
+ to value larger than (4 GiB - dictionary_size).
+
+
9.38 beta 2015-01-03
-------------------------
- The BUG in 9.31-9.37 was fixed: