This commit is contained in:
Igor Pavlov
2015-10-18 00:00:00 +00:00
committed by Kornel Lesiński
parent 6543c28020
commit a663a6deb7
44 changed files with 1659 additions and 565 deletions

View File

@@ -1,9 +1,9 @@
#define MY_VER_MAJOR 15 #define MY_VER_MAJOR 15
#define MY_VER_MINOR 8 #define MY_VER_MINOR 9
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION_NUMBERS "15.08" #define MY_VERSION_NUMBERS "15.09"
#define MY_VERSION "15.08 beta" #define MY_VERSION "15.09 beta"
#define MY_DATE "2015-10-01" #define MY_DATE "2015-10-16"
#undef MY_COPYRIGHT #undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE #undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov" #define MY_AUTHOR_NAME "Igor Pavlov"

View File

@@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms /* LzFind.c -- Match finder for LZ algorithms
2015-05-15 : Igor Pavlov : Public domain */ 2015-10-15 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -11,7 +11,7 @@
#define kEmptyHashValue 0 #define kEmptyHashValue 0
#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #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 kMaxHistorySize ((UInt32)7 << 29)
#define kStartMaxLen 3 #define kStartMaxLen 3
@@ -60,9 +60,11 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
if (p->streamEndWasReached || p->result != SZ_OK) if (p->streamEndWasReached || p->result != SZ_OK)
return; return;
/* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */
if (p->directInput) if (p->directInput)
{ {
UInt32 curSize = 0xFFFFFFFF - p->streamPos; UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos);
if (curSize > p->directInputRem) if (curSize > p->directInputRem)
curSize = (UInt32)p->directInputRem; curSize = (UInt32)p->directInputRem;
p->directInputRem -= curSize; p->directInputRem -= curSize;
@@ -97,7 +99,7 @@ void MatchFinder_MoveBlock(CMatchFinder *p)
{ {
memmove(p->bufferBase, memmove(p->bufferBase,
p->buffer - p->keepSizeBefore, 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; p->buffer = p->bufferBase + p->keepSizeBefore;
} }
@@ -290,7 +292,7 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
p->posLimit = p->pos + limit; p->posLimit = p->pos + limit;
} }
void MatchFinder_Init(CMatchFinder *p) void MatchFinder_Init_2(CMatchFinder *p, int readData)
{ {
UInt32 i; UInt32 i;
UInt32 *hash = p->hash; UInt32 *hash = p->hash;
@@ -303,10 +305,18 @@ void MatchFinder_Init(CMatchFinder *p)
p->pos = p->streamPos = p->cyclicBufferSize; p->pos = p->streamPos = p->cyclicBufferSize;
p->result = SZ_OK; p->result = SZ_OK;
p->streamEndWasReached = 0; p->streamEndWasReached = 0;
if (readData)
MatchFinder_ReadBlock(p); MatchFinder_ReadBlock(p);
MatchFinder_SetLimits(p); MatchFinder_SetLimits(p);
} }
void MatchFinder_Init(CMatchFinder *p)
{
MatchFinder_Init_2(p, True);
}
static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
{ {
return (p->pos - p->historySize - 1) & kNormalizeMask; return (p->pos - p->historySize - 1) & kNormalizeMask;

View File

@@ -1,5 +1,5 @@
/* LzFind.h -- Match finder for LZ algorithms /* 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 #ifndef __LZ_FIND_H
#define __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_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); int MatchFinder_NeedMove(CMatchFinder *p);
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p);
@@ -98,9 +103,12 @@ typedef struct _IMatchFinder
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
void MatchFinder_Init_2(CMatchFinder *p, int readData);
void MatchFinder_Init(CMatchFinder *p); void MatchFinder_Init(CMatchFinder *p);
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);

View File

@@ -1,5 +1,5 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms /* 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" #include "Precomp.h"
@@ -173,12 +173,12 @@ static void HashThreadFunc(CMatchFinderMt *mt)
CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->btSync.cs);
CriticalSection_Enter(&mt->hashSync.cs); CriticalSection_Enter(&mt->hashSync.cs);
{ {
const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf);
const Byte *afterPtr; ptrdiff_t offset;
MatchFinder_MoveBlock(mf); MatchFinder_MoveBlock(mf);
afterPtr = MatchFinder_GetPointerToCurrentPos(mf); offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf);
mt->pointerToCurPos -= beforePtr - afterPtr; mt->pointerToCurPos -= offset;
mt->buffer -= beforePtr - afterPtr; mt->buffer -= offset;
} }
CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->btSync.cs);
CriticalSection_Leave(&mt->hashSync.cs); CriticalSection_Leave(&mt->hashSync.cs);
@@ -501,8 +501,11 @@ void MatchFinderMt_Init(CMatchFinderMt *p)
CMatchFinder *mf = p->MatchFinder; CMatchFinder *mf = p->MatchFinder;
p->btBufPos = p->btBufPosLimit = 0; p->btBufPos = p->btBufPosLimit = 0;
p->hashBufPos = p->hashBufPosLimit = 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->btNumAvailBytes = 0;
p->lzPos = p->historySize + 1; p->lzPos = p->historySize + 1;

View File

@@ -1,5 +1,5 @@
/* Lzma2Enc.c -- LZMA2 Encoder /* Lzma2Enc.c -- LZMA2 Encoder
2015-09-16 : Igor Pavlov : Public domain */ 2015-10-04 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -479,7 +479,7 @@ SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
for (i = 0; i < p->props.numBlockThreads; i++) for (i = 0; i < p->props.numBlockThreads; i++)
{ {
CLzma2EncInt *t = &p->coders[i]; CLzma2EncInt *t = &p->coders[(unsigned)i];
if (!t->enc) if (!t->enc)
{ {
t->enc = LzmaEnc_Create(p->alloc); t->enc = LzmaEnc_Create(p->alloc);
@@ -489,11 +489,7 @@ SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
} }
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
if (p->props.numBlockThreads <= 1) if (p->props.numBlockThreads > 1)
#endif
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
#ifndef _7ZIP_ST
{ {
CMtCallbackImp mtCallback; CMtCallbackImp mtCallback;
@@ -508,9 +504,17 @@ SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
p->mtCoder.blockSize = p->props.blockSize; p->mtCoder.blockSize = p->props.blockSize;
p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16; 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; p->mtCoder.numThreads = p->props.numBlockThreads;
return MtCoder_Code(&p->mtCoder); return MtCoder_Code(&p->mtCoder);
} }
#endif #endif
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
} }

View File

@@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder /* LzmaEnc.c -- LZMA Encoder
2015-05-15 Igor Pavlov : Public domain */ 2015-10-15 Igor Pavlov : Public domain */
#include "Precomp.h" #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) static void RangeEnc_Construct(CRangeEnc *p)
{ {
p->outStream = 0; p->outStream = NULL;
p->bufBase = 0; p->bufBase = NULL;
} }
#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) #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) #define RC_BUF_SIZE (1 << 16)
static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
{ {
if (p->bufBase == 0) if (!p->bufBase)
{ {
p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
if (p->bufBase == 0) if (!p->bufBase)
return 0; return 0;
p->bufLim = p->bufBase + RC_BUF_SIZE; p->bufLim = p->bufBase + RC_BUF_SIZE;
} }
@@ -1749,15 +1749,15 @@ void LzmaEnc_Construct(CLzmaEnc *p)
#endif #endif
LzmaEnc_InitPriceTables(p->ProbPrices); LzmaEnc_InitPriceTables(p->ProbPrices);
p->litProbs = 0; p->litProbs = NULL;
p->saveState.litProbs = 0; p->saveState.litProbs = NULL;
} }
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
{ {
void *p; void *p;
p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
if (p != 0) if (p)
LzmaEnc_Construct((CLzmaEnc *)p); LzmaEnc_Construct((CLzmaEnc *)p);
return p; return p;
} }
@@ -1766,8 +1766,8 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
{ {
alloc->Free(alloc, p->litProbs); alloc->Free(alloc, p->litProbs);
alloc->Free(alloc, p->saveState.litProbs); alloc->Free(alloc, p->saveState.litProbs);
p->litProbs = 0; p->litProbs = NULL;
p->saveState.litProbs = 0; p->saveState.litProbs = NULL;
} }
void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) 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; 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); LzmaEnc_FreeLits(p, alloc);
p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
p->saveState.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); LzmaEnc_FreeLits(p, alloc);
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
@@ -2140,6 +2140,7 @@ void LzmaEnc_Finish(CLzmaEncHandle pp)
#endif #endif
} }
typedef struct typedef struct
{ {
ISeqOutStream funcTable; ISeqOutStream funcTable;
@@ -2169,12 +2170,14 @@ UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
} }
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
{ {
const CLzmaEnc *p = (CLzmaEnc *)pp; const CLzmaEnc *p = (CLzmaEnc *)pp;
return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
} }
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
{ {
@@ -2209,6 +2212,7 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
return res; return res;
} }
static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
@@ -2222,9 +2226,9 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
for (;;) for (;;)
{ {
res = LzmaEnc_CodeOneBlock(p, False, 0, 0); res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
if (res != SZ_OK || p->finished != 0) if (res != SZ_OK || p->finished)
break; break;
if (progress != 0) if (progress)
{ {
res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
if (res != SZ_OK) if (res != SZ_OK)
@@ -2234,10 +2238,19 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
} }
} }
} }
LzmaEnc_Finish(p); LzmaEnc_Finish(p);
/*
if (res == S_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))
res = SZ_ERROR_FAIL;
}
*/
return res; return res;
} }
SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
ISzAlloc *alloc, ISzAlloc *allocBig) ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
@@ -2245,6 +2258,7 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i
return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
} }
SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
{ {
CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEnc *p = (CLzmaEnc *)pp;
@@ -2272,6 +2286,7 @@ SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
return SZ_OK; return SZ_OK;
} }
SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) 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; CSeqOutStreamBuf outStream;
LzmaEnc_SetInputBuf(p, src, srcLen);
outStream.funcTable.Write = MyWrite; outStream.funcTable.Write = MyWrite;
outStream.data = dest; outStream.data = dest;
outStream.rem = *destLen; outStream.rem = *destLen;
outStream.overflow = False; outStream.overflow = False;
p->writeEndMark = writeEndMark; p->writeEndMark = writeEndMark;
p->rc.outStream = &outStream.funcTable; p->rc.outStream = &outStream.funcTable;
res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
if (res == SZ_OK) if (res == SZ_OK)
{
res = LzmaEnc_Encode2(p, progress); res = LzmaEnc_Encode2(p, progress);
if (res == SZ_OK && p->nowPos64 != srcLen)
res = SZ_ERROR_FAIL;
}
*destLen -= outStream.rem; *destLen -= outStream.rem;
if (outStream.overflow) if (outStream.overflow)
@@ -2300,13 +2318,14 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
return res; return res;
} }
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
SRes res; SRes res;
if (p == 0) if (!p)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
res = LzmaEnc_SetProps(p, props); res = LzmaEnc_SetProps(p, props);

View File

@@ -1,10 +1,8 @@
/* MtCoder.c -- Multi-thread Coder /* MtCoder.c -- Multi-thread Coder
2015-09-28 : Igor Pavlov : Public domain */ 2015-10-13 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include <stdio.h>
#include "MtCoder.h" #include "MtCoder.h"
void LoopThread_Construct(CLoopThread *p) void LoopThread_Construct(CLoopThread *p)

View File

@@ -83,8 +83,14 @@ class CHandler: public CHandlerCont
HRESULT ReadTables(IInStream *stream); HRESULT ReadTables(IInStream *stream);
UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; } UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; }
virtual UInt64 GetItemPos(UInt32 index) const { return BlocksToBytes(_items[index].StartBlock); } virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const
virtual UInt64 GetItemSize(UInt32 index) const { return BlocksToBytes(_items[index].NumBlocks); } {
const CItem &item = _items[index];
pos = BlocksToBytes(item.StartBlock);
size = BlocksToBytes(item.NumBlocks);
return NExtract::NOperationResult::kOK;
}
public: public:
INTERFACE_IInArchive_Cont(;) INTERFACE_IInArchive_Cont(;)
}; };

View File

@@ -101,6 +101,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
NCOM::CPropVariant prop; NCOM::CPropVariant prop;
if (m_Database.NewFormat) if (m_Database.NewFormat)
{ {
switch (propID) switch (propID)
@@ -112,12 +113,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;
} }
int entryIndex;
unsigned entryIndex;
if (m_Database.LowLevel) if (m_Database.LowLevel)
entryIndex = index; entryIndex = index;
else else
entryIndex = m_Database.Indices[index]; entryIndex = m_Database.Indices[index];
const CItem &item = m_Database.Items[entryIndex]; const CItem &item = m_Database.Items[entryIndex];
switch (propID) switch (propID)
{ {
case kpidPath: case kpidPath:
@@ -161,6 +165,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
#endif #endif
} }
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END
@@ -244,9 +249,9 @@ public:
UInt64 m_PosInFolder; UInt64 m_PosInFolder;
UInt64 m_PosInSection; UInt64 m_PosInSection;
const CRecordVector<bool> *m_ExtractStatuses; const CRecordVector<bool> *m_ExtractStatuses;
int m_StartIndex; unsigned m_StartIndex;
int m_CurrentIndex; unsigned m_CurrentIndex;
int m_NumFiles; unsigned m_NumFiles;
private: private:
const CFilesDatabase *m_Database; const CFilesDatabase *m_Database;
@@ -368,7 +373,7 @@ HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *proce
// return E_FAIL; // return E_FAIL;
} }
int fullIndex = m_StartIndex + m_CurrentIndex; unsigned fullIndex = m_StartIndex + m_CurrentIndex;
m_RemainFileSize = m_Database->GetFileSize(fullIndex); m_RemainFileSize = m_Database->GetFileSize(fullIndex);
UInt64 fileOffset = m_Database->GetFileOffset(fullIndex); UInt64 fileOffset = m_Database->GetFileOffset(fullIndex);
if (fileOffset < m_PosInSection) if (fileOffset < m_PosInSection)
@@ -408,7 +413,7 @@ HRESULT CChmFolderOutStream::FlushCorrupted(UInt64 maxSize)
{ {
const UInt32 kBufferSize = (1 << 10); const UInt32 kBufferSize = (1 << 10);
Byte buffer[kBufferSize]; Byte buffer[kBufferSize];
for (int i = 0; i < kBufferSize; i++) for (unsigned i = 0; i < kBufferSize; i++)
buffer[i] = 0; buffer[i] = 0;
if (maxSize > m_FolderSize) if (maxSize > m_FolderSize)
maxSize = m_FolderSize; maxSize = m_FolderSize;
@@ -531,9 +536,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
for (i = 0; i < numItems; i++) for (i = 0; i < numItems; i++)
{ {
UInt32 index = allFilesMode ? i : indices[i]; UInt32 index = allFilesMode ? i : indices[i];
int entryIndex = m_Database.Indices[index]; const CItem &item = m_Database.Items[m_Database.Indices[index]];
const CItem &item = m_Database.Items[entryIndex]; const UInt64 sectionIndex = item.Section;
UInt64 sectionIndex = item.Section;
if (item.IsDir() || item.Size == 0) if (item.IsDir() || item.Size == 0)
continue; continue;
if (sectionIndex == 0) if (sectionIndex == 0)
@@ -567,14 +571,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CByteBuffer packBuf; CByteBuffer packBuf;
for (i = 0; i < numItems;) for (i = 0;;)
{ {
RINOK(extractCallback->SetCompleted(&currentTotalSize)); RINOK(extractCallback->SetCompleted(&currentTotalSize));
if (i >= numItems)
break;
UInt32 index = allFilesMode ? i : indices[i]; UInt32 index = allFilesMode ? i : indices[i];
i++; i++;
int entryIndex = m_Database.Indices[index]; const CItem &item = m_Database.Items[m_Database.Indices[index]];
const CItem &item = m_Database.Items[entryIndex]; const UInt64 sectionIndex = item.Section;
UInt64 sectionIndex = item.Section;
Int32 askMode= testMode ? Int32 askMode= testMode ?
NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
@@ -645,7 +652,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 folderIndex = m_Database.GetFolder(index); 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())); RINOK(lzxDecoderSpec->SetParams_and_Alloc(lzxInfo.GetNumDictBits()));
const CItem *lastItem = &item; const CItem *lastItem = &item;
@@ -673,9 +680,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{ {
for (; i < numItems; i++) for (; i < numItems; i++)
{ {
UInt32 nextIndex = allFilesMode ? i : indices[i]; const UInt32 nextIndex = allFilesMode ? i : indices[i];
int entryIndex = m_Database.Indices[nextIndex]; const CItem &nextItem = m_Database.Items[m_Database.Indices[nextIndex]];
const CItem &nextItem = m_Database.Items[entryIndex];
if (nextItem.Section != sectionIndex) if (nextItem.Section != sectionIndex)
break; break;
UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex); UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex);

View File

@@ -656,7 +656,7 @@ static AString GetSectionPrefix(const AString &name)
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } #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 CObjectVector<CItem> &items = *(const CObjectVector<CItem> *)param;
const CItem &item1 = items[*p1]; const CItem &item1 = items[*p1];
@@ -731,7 +731,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
RINOK(DecompressStream(inStream, database, kNameList)); RINOK(DecompressStream(inStream, database, kNameList));
/* UInt16 length = */ ReadUInt16(); /* UInt16 length = */ ReadUInt16();
UInt16 numSections = ReadUInt16(); UInt16 numSections = ReadUInt16();
for (int i = 0; i < numSections; i++) for (unsigned i = 0; i < numSections; i++)
{ {
CSectionInfo section; CSectionInfo section;
UInt16 nameLen = ReadUInt16(); UInt16 nameLen = ReadUInt16();
@@ -766,10 +766,10 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
RINOK(DecompressStream(inStream, database, transformPrefix + kTransformList)); RINOK(DecompressStream(inStream, database, transformPrefix + kTransformList));
if ((_chunkSize & 0xF) != 0) if ((_chunkSize & 0xF) != 0)
return S_FALSE; return S_FALSE;
int numGuids = (int)(_chunkSize / 0x10); unsigned numGuids = (unsigned)(_chunkSize / 0x10);
if (numGuids < 1) if (numGuids < 1)
return S_FALSE; return S_FALSE;
for (int i = 0; i < numGuids; i++) for (unsigned i = 0; i < numGuids; i++)
{ {
CMethodInfo method; CMethodInfo method;
ReadGUID(method.Guid); ReadGUID(method.Guid);
@@ -803,14 +803,17 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
return S_FALSE; 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) if (n < 0 || n > 16)
return S_FALSE; return S_FALSE;
li.ResetIntervalBits = n; li.ResetIntervalBits = n;
} }
{ {
int n = GetLog(ReadUInt32()); UInt32 val32 = ReadUInt32();
int n = GetLog(val32);
if (n < 0 || n > 16) if (n < 0 || n > 16)
return S_FALSE; return S_FALSE;
li.WindowSizeBits = n; li.WindowSizeBits = n;

View File

@@ -177,25 +177,25 @@ class CFilesDatabase: public CDatabase
{ {
public: public:
bool LowLevel; bool LowLevel;
CRecordVector<int> Indices; CUIntVector Indices;
CObjectVector<CSectionInfo> Sections; CObjectVector<CSectionInfo> Sections;
UInt64 GetFileSize(int fileIndex) const { return Items[Indices[fileIndex]].Size; } UInt64 GetFileSize(unsigned fileIndex) const { return Items[Indices[fileIndex]].Size; }
UInt64 GetFileOffset(int fileIndex) const { return Items[Indices[fileIndex]].Offset; } 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 CItem &item = Items[Indices[fileIndex]];
const CSectionInfo &section = Sections[(int)item.Section]; const CSectionInfo &section = Sections[(unsigned)item.Section];
if (section.IsLzx()) if (section.IsLzx())
return section.Methods[0].LzxInfo.GetFolder(item.Offset); return section.Methods[0].LzxInfo.GetFolder(item.Offset);
return 0; return 0;
} }
UInt64 GetLastFolder(int fileIndex) const UInt64 GetLastFolder(unsigned fileIndex) const
{ {
const CItem &item = Items[Indices[fileIndex]]; const CItem &item = Items[Indices[fileIndex]];
const CSectionInfo &section = Sections[(int)item.Section]; const CSectionInfo &section = Sections[(unsigned)item.Section];
if (section.IsLzx()) if (section.IsLzx())
return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1); return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1);
return 0; return 0;

View File

@@ -433,9 +433,9 @@ HRESULT CDatabase::Open(IInStream *inStream)
SectorSizeBits = sectorSizeBits; SectorSizeBits = sectorSizeBits;
MiniSectorSizeBits = miniSectorSizeBits; MiniSectorSizeBits = miniSectorSizeBits;
if (sectorSizeBits > 28 || if (sectorSizeBits > 24 ||
sectorSizeBits < 7 || sectorSizeBits < 7 ||
miniSectorSizeBits > 28 || miniSectorSizeBits > 24 ||
miniSectorSizeBits < 2 || miniSectorSizeBits < 2 ||
miniSectorSizeBits > sectorSizeBits) miniSectorSizeBits > sectorSizeBits)
return S_FALSE; return S_FALSE;

View File

@@ -4,6 +4,11 @@
// #define SHOW_DEBUG_INFO // #define SHOW_DEBUG_INFO
// #include <stdio.h>
// #define PRF2(x) x
#define PRF2(x)
#ifdef SHOW_DEBUG_INFO #ifdef SHOW_DEBUG_INFO
#include <stdio.h> #include <stdio.h>
#define PRF(x) x #define PRF(x) x
@@ -23,7 +28,6 @@
#include "../../Windows/PropVariantUtils.h" #include "../../Windows/PropVariantUtils.h"
#include "../../Windows/TimeUtils.h" #include "../../Windows/TimeUtils.h"
#include "../Common/LimitedStreams.h"
#include "../Common/ProgressUtils.h" #include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h" #include "../Common/RegisterArc.h"
#include "../Common/StreamObjects.h" #include "../Common/StreamObjects.h"
@@ -300,7 +304,7 @@ struct CHeader
// UInt64 NumBlocksSuper; // UInt64 NumBlocksSuper;
UInt64 NumFreeBlocks; UInt64 NumFreeBlocks;
UInt32 NumFreeInodes; UInt32 NumFreeInodes;
UInt32 FirstDataBlock; // UInt32 FirstDataBlock;
UInt32 BlocksPerGroup; UInt32 BlocksPerGroup;
UInt32 ClustersPerGroup; UInt32 ClustersPerGroup;
@@ -349,6 +353,7 @@ struct CHeader
bool IsOldRev() const { return RevLevel == EXT4_GOOD_OLD_REV; } bool IsOldRev() const { return RevLevel == EXT4_GOOD_OLD_REV; }
UInt64 GetNumGroups() const { return (NumBlocks + BlocksPerGroup - 1) / BlocksPerGroup; } 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 IsThereFileType() const { return (FeatureIncompat & EXT4_FEATURE_INCOMPAT_FILETYPE) != 0; }
bool Is64Bit() const { return (FeatureIncompat & EXT4_FEATURE_INCOMPAT_64BIT) != 0; } bool Is64Bit() const { return (FeatureIncompat & EXT4_FEATURE_INCOMPAT_64BIT) != 0; }
@@ -367,6 +372,15 @@ static int inline GetLog(UInt32 num)
return -1; 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) bool CHeader::Parse(const Byte *p)
{ {
if (GetUi16(p + 0x38) != 0xEF53) if (GetUi16(p + 0x38) != 0xEF53)
@@ -378,18 +392,22 @@ bool CHeader::Parse(const Byte *p)
if (ClusterBits != 0 && BlockBits != ClusterBits) if (ClusterBits != 0 && BlockBits != ClusterBits)
return false; return false;
if (BlockBits > 16 - 10) return false; if (BlockBits > 16 - 10)
return false;
BlockBits += 10; BlockBits += 10;
if (ClusterBits > 16) return false;
LE_32 (0x00, NumInodes); LE_32 (0x00, NumInodes);
LE_32 (0x04, NumBlocks); LE_32 (0x04, NumBlocks);
// LE_32 (0x08, NumBlocksSuper); // LE_32 (0x08, NumBlocksSuper);
LE_32 (0x0C, NumFreeBlocks); LE_32 (0x0C, NumFreeBlocks);
LE_32 (0x10, NumFreeInodes); 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; return false;
LE_32 (0x20, BlocksPerGroup); LE_32 (0x20, BlocksPerGroup);
@@ -397,11 +415,19 @@ bool CHeader::Parse(const Byte *p)
if (BlocksPerGroup != ClustersPerGroup) if (BlocksPerGroup != ClustersPerGroup)
return false; return false;
if (BlocksPerGroup != ((UInt32)1 << (BlockBits + 3))) if (BlocksPerGroup == 0)
return false; return false;
if (BlocksPerGroup != ((UInt32)1 << (BlockBits + 3)))
{
// it's allowed in ext2
// return false;
}
LE_32 (0x28, InodesPerGroup); LE_32 (0x28, InodesPerGroup);
if (InodesPerGroup < 1 || InodesPerGroup > NumInodes)
return false;
LE_32 (0x2C, MountTime); LE_32 (0x2C, MountTime);
LE_32 (0x30, WriteTime); LE_32 (0x30, WriteTime);
@@ -485,6 +511,9 @@ bool CHeader::Parse(const Byte *p)
if (NumFreeBlocks > NumBlocks) if (NumFreeBlocks > NumBlocks)
return false; return false;
if (GetNumGroups() != GetNumGroups2())
return false;
return true; return true;
} }
@@ -612,7 +641,7 @@ struct CExtTime
struct CNode struct CNode
{ {
Int32 ParentNode; // in _nodes[], -1 if not dir Int32 ParentNode; // in _refs[], -1 if not dir
int ItemIndex; // in _items[] int ItemIndex; // in _items[]
int SymLinkIndex; // in _symLinks[] int SymLinkIndex; // in _symLinks[]
int DirIndex; // in _dirs[] int DirIndex; // in _dirs[]
@@ -621,7 +650,6 @@ struct CNode
UInt16 Uid; UInt16 Uid;
UInt16 Gid; UInt16 Gid;
// UInt16 Checksum; // UInt16 Checksum;
bool IsEmpty;
UInt64 FileSize; UInt64 FileSize;
CExtTime MTime; CExtTime MTime;
@@ -662,6 +690,7 @@ bool CNode::Parse(const Byte *p, const CHeader &_h)
MTime.Extra = 0; MTime.Extra = 0;
ATime.Extra = 0; ATime.Extra = 0;
CTime.Extra = 0; CTime.Extra = 0;
CTime.Val = 0;
// InodeChangeTime.Extra = 0; // InodeChangeTime.Extra = 0;
// DTime.Extra = 0; // DTime.Extra = 0;
@@ -692,14 +721,21 @@ bool CNode::Parse(const Byte *p, const CHeader &_h)
FileSize |= ((UInt64)highSize << 32); FileSize |= ((UInt64)highSize << 32);
} }
// UInt32 fragmentAddress;
// LE_32 (0x70, fragmentAddress); // LE_32 (0x70, fragmentAddress);
// osd2 // osd2
{ {
// Linux; // Linux;
// ext2:
// Byte FragmentNumber = p[0x74];
// Byte FragmentSize = p[0x74 + 1];
// ext4:
UInt32 numBlocksHigh; UInt32 numBlocksHigh;
LE_16 (0x74, numBlocksHigh); LE_16 (0x74, numBlocksHigh);
NumBlocks |= (UInt64)numBlocksHigh << 32; NumBlocks |= (UInt64)numBlocksHigh << 32;
HI_16 (0x74 + 4, Uid); HI_16 (0x74 + 4, Uid);
HI_16 (0x74 + 6, Gid); HI_16 (0x74 + 6, Gid);
/* /*
@@ -738,8 +774,8 @@ bool CNode::Parse(const Byte *p, const CHeader &_h)
struct CItem struct CItem
{ {
unsigned Node; // in _nodes[] unsigned Node; // in _refs[]
int ParentNode; // in _nodes[] int ParentNode; // in _refs[]
int SymLinkItemIndex; // in _items[], if the Node contains SymLink to existing dir int SymLinkItemIndex; // in _items[], if the Node contains SymLink to existing dir
Byte Type; Byte Type;
@@ -778,6 +814,7 @@ class CHandler:
public CMyUnknownImp public CMyUnknownImp
{ {
CObjectVector<CItem> _items; CObjectVector<CItem> _items;
CIntVector _refs;
CRecordVector<CNode> _nodes; CRecordVector<CNode> _nodes;
CObjectVector<CUIntVector> _dirs; // each CUIntVector contains indexes in _items[] only for dir items; CObjectVector<CUIntVector> _dirs; // each CUIntVector contains indexes in _items[] only for dir items;
AStringVector _symLinks; AStringVector _symLinks;
@@ -789,6 +826,7 @@ class CHandler:
UInt64 _phySize; UInt64 _phySize;
bool _isArc; bool _isArc;
bool _headersError; bool _headersError;
bool _headersWarning;
bool _linksError; bool _linksError;
bool _isUTF; bool _isUTF;
@@ -831,14 +869,14 @@ class CHandler:
} }
HRESULT SeekAndRead(IInStream *inStream, UInt64 block, Byte *data, size_t size); 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; int FindTargetItem_for_SymLink(unsigned dirNode, const AString &path) const;
HRESULT FillFileBlocks2(UInt32 block, unsigned level, unsigned numBlocks, CRecordVector<UInt32> &blocks); HRESULT FillFileBlocks2(UInt32 block, unsigned level, unsigned numBlocks, CRecordVector<UInt32> &blocks);
HRESULT FillFileBlocks(const Byte *p, 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 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); HRESULT ExtractNode(unsigned nodeIndex, CByteBuffer &data);
void ClearRefs(); 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; 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(); nodeDir.DirIndex = _dirs.Size();
CUIntVector &dir = _dirs.AddNew(); CUIntVector &dir = _dirs.AddNew();
int parentNode = -1; int parentNode = -1;
@@ -891,7 +929,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
if (nameLen + 8 > recLen) if (nameLen + 8 > recLen)
return S_FALSE; return S_FALSE;
if (iNode >= _nodes.Size()) if (iNode >= _refs.Size())
return S_FALSE; return S_FALSE;
item.Clear(); item.Clear();
@@ -901,7 +939,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
else if (type != 0) else if (type != 0)
return S_FALSE; return S_FALSE;
item.ParentNode = nodeIndex; item.ParentNode = iNodeDir;
item.Node = iNode; item.Node = iNode;
item.Name.SetFrom_CalcLen((const char *)(p + 8), nameLen); 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; 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) if (type == 0xDE)
{ {
// checksum // checksum
@@ -930,9 +968,10 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
continue; continue;
} }
CNode &node = _nodes[iNode]; int nodeIndex = _refs[iNode];
if (node.IsEmpty) if (nodeIndex < 0)
return S_FALSE; return S_FALSE;
CNode &node = _nodes[nodeIndex];
if (_h.IsThereFileType() && type != 0) if (_h.IsThereFileType() && type != 0)
{ {
@@ -944,7 +983,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
node.NumLinksCalced++; 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] == '.') if (item.Name[0] == '.')
{ {
@@ -953,7 +992,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
if (isThereSelfLink) if (isThereSelfLink)
return S_FALSE; return S_FALSE;
isThereSelfLink = true; isThereSelfLink = true;
if (nodeIndex != nodeIndex) if (iNode != iNodeDir)
return S_FALSE; return S_FALSE;
continue; continue;
} }
@@ -964,7 +1003,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
return S_FALSE; return S_FALSE;
if (!node.IsDir()) if (!node.IsDir())
return S_FALSE; return S_FALSE;
if (iNode == nodeIndex && iNode != k_INODE_ROOT) if (iNode == iNodeDir && iNode != k_INODE_ROOT)
return S_FALSE; return S_FALSE;
parentNode = iNode; 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; return S_FALSE;
if (parentNode < 0) if (parentNode < 0)
@@ -987,8 +1026,8 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned nodeIndex)
if (node.IsDir()) if (node.IsDir())
{ {
if (node.ParentNode < 0) if (node.ParentNode < 0)
node.ParentNode = nodeIndex; node.ParentNode = iNodeDir;
else if ((unsigned)node.ParentNode != nodeIndex) else if ((unsigned)node.ParentNode != iNodeDir)
return S_FALSE; return S_FALSE;
const unsigned itemIndex = _items.Size(); const unsigned itemIndex = _items.Size();
dir.Add(itemIndex); 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; unsigned pos = 0;
@@ -1014,8 +1053,8 @@ int CHandler::FindTargetItem_for_SymLink(unsigned nodeIndex, const AString &path
if (path[0] == '/') if (path[0] == '/')
{ {
nodeIndex = k_INODE_ROOT; iNode = k_INODE_ROOT;
if (nodeIndex >= _nodes.Size()) if (iNode >= _refs.Size())
return -1; return -1;
pos = 1; pos = 1;
} }
@@ -1024,7 +1063,7 @@ int CHandler::FindTargetItem_for_SymLink(unsigned nodeIndex, const AString &path
while (pos != path.Len()) while (pos != path.Len())
{ {
const CNode &node = _nodes[nodeIndex]; const CNode &node = _nodes[_refs[iNode]];
int slash = path.Find('/', pos); int slash = path.Find('/', pos);
if (slash < 0) if (slash < 0)
@@ -1046,9 +1085,9 @@ int CHandler::FindTargetItem_for_SymLink(unsigned nodeIndex, const AString &path
{ {
if (node.ParentNode < 0) if (node.ParentNode < 0)
return -1; return -1;
if (nodeIndex == k_INODE_ROOT) if (iNode == k_INODE_ROOT)
return -1; return -1;
nodeIndex = node.ParentNode; iNode = node.ParentNode;
continue; continue;
} }
} }
@@ -1065,13 +1104,13 @@ int CHandler::FindTargetItem_for_SymLink(unsigned nodeIndex, const AString &path
const CItem &item = _items[dir[i]]; const CItem &item = _items[dir[i]];
if (item.Name == s) if (item.Name == s)
{ {
nodeIndex = item.Node; iNode = item.Node;
break; 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; UInt32 numReserveInodes = _h.NumInodes - _h.NumFreeInodes + 1;
// numReserveInodes = _h.NumInodes + 1; // numReserveInodes = _h.NumInodes + 1;
if (numReserveInodes != 0) if (numReserveInodes != 0)
{
_nodes.Reserve(numReserveInodes); _nodes.Reserve(numReserveInodes);
_refs.Reserve(numReserveInodes);
}
UInt32 numNodes = _h.InodesPerGroup; UInt32 numNodes = _h.InodesPerGroup;
if (numNodes > _h.NumInodes) if (numNodes > _h.NumInodes)
@@ -1195,6 +1237,8 @@ HRESULT CHandler::Open2(IInStream *inStream)
nodesMap.Alloc(blockSize); nodesMap.Alloc(blockSize);
unsigned globalNodeIndex = 0; unsigned globalNodeIndex = 0;
// unsigned numEmpty = 0;
unsigned numEmpty_in_Maps = 0;
FOR_VECTOR (gi, groups) FOR_VECTOR (gi, groups)
{ {
@@ -1203,40 +1247,40 @@ HRESULT CHandler::Open2(IInStream *inStream)
const CGroupDescriptor &gd = groups[gi]; 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.InodeBitmap, nodesMap, blockSize));
RINOK(SeekAndRead(inStream, gd.InodeTable, nodesData, nodesDataSize)); RINOK(SeekAndRead(inStream, gd.InodeTable, nodesData, nodesDataSize));
unsigned numEmpty_in_Map = 0;
for (size_t n = 0; n < numNodes && globalNodeIndex < _h.NumInodes; n++, globalNodeIndex++) for (size_t n = 0; n < numNodes && globalNodeIndex < _h.NumInodes; n++, globalNodeIndex++)
{ {
if ((nodesMap[n >> 3] & ((unsigned)1 << (n & 7))) == 0) if ((nodesMap[n >> 3] & ((unsigned)1 << (n & 7))) == 0)
{
numEmpty_in_Map++;
continue; continue;
}
const Byte *p = nodesData + (size_t)n * _h.InodeSize; const Byte *p = nodesData + (size_t)n * _h.InodeSize;
unsigned j = 0; if (IsEmptyData(p, _h.InodeSize))
for (j = 0; j < _h.InodeSize; j++)
if (p[j] != 0)
break;
if (j == _h.InodeSize)
{ {
if (_nodes.Size() >= _h.FirstInode) if (globalNodeIndex + 1 >= _h.FirstInode)
{ {
_headersError = true;
// return S_FALSE; // return S_FALSE;
} }
continue; continue;
} }
CNode node; CNode node;
node.IsEmpty = false;
PRF(printf("\nnode = %5d ", (unsigned)n)); PRF(printf("\nnode = %5d ", (unsigned)n));
if (!node.Parse(p, _h)) if (!node.Parse(p, _h))
return S_FALSE; return S_FALSE;
// PRF(printf("\n %6d", n)); // PRF(printf("\n %6d", (unsigned)n));
/* /*
SetUi32(p + 0x7C, 0) SetUi32(p + 0x7C, 0)
SetUi32(p + 0x82, 0) SetUi32(p + 0x82, 0)
@@ -1249,19 +1293,36 @@ HRESULT CHandler::Open2(IInStream *inStream)
if (crc != node.Checksum) return S_FALSE; if (crc != node.Checksum) return S_FALSE;
*/ */
while (_nodes.Size() < globalNodeIndex + 1) while (_refs.Size() < globalNodeIndex + 1)
{ {
CNode node2; // numEmpty++;
node2.IsEmpty = true; _refs.Add(-1);
_nodes.Add(node2);
} }
_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; 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; CByteBuffer dataBuf;
FOR_VECTOR (i, _nodes) FOR_VECTOR (i, _refs)
{ {
int nodeIndex = _refs[i];
{ {
const CNode &node = _nodes[i]; if (nodeIndex < 0)
if (node.IsEmpty || !node.IsDir()) continue;
const CNode &node = _nodes[nodeIndex];
if (!node.IsDir())
continue; continue;
} }
RINOK(ExtractNode(i, dataBuf)); RINOK(ExtractNode(nodeIndex, dataBuf));
if (dataBuf.Size() == 0) if (dataBuf.Size() == 0)
{ {
// _headersError = true; // _headersError = true;
@@ -1292,18 +1356,19 @@ HRESULT CHandler::Open2(IInStream *inStream)
RINOK(CheckProgress()); RINOK(CheckProgress());
} }
if (_nodes[k_INODE_ROOT].ParentNode != k_INODE_ROOT) if (_nodes[_refs[k_INODE_ROOT]].ParentNode != k_INODE_ROOT)
return S_FALSE; return S_FALSE;
} }
{ {
// ---------- Check NumLinks and unreferenced dir nodes ---------- // ---------- Check NumLinks and unreferenced dir nodes ----------
FOR_VECTOR (i, _nodes) FOR_VECTOR (i, _refs)
{ {
const CNode &node = _nodes[i]; int nodeIndex = _refs[i];
if (node.IsEmpty) if (nodeIndex < 0)
continue; continue;
const CNode &node = _nodes[nodeIndex];
if (node.NumLinks != node.NumLinksCalced) if (node.NumLinks != node.NumLinksCalced)
{ {
@@ -1331,19 +1396,23 @@ HRESULT CHandler::Open2(IInStream *inStream)
{ {
// ---------- Check that there is no loops in parents list ---------- // ---------- Check that there is no loops in parents list ----------
unsigned numNodes = _nodes.Size(); unsigned numNodes = _refs.Size();
CIntArr UsedByNode(numNodes); CIntArr UsedByNode(numNodes);
{
{ {
for (unsigned i = 0; i < numNodes; i++) for (unsigned i = 0; i < numNodes; i++)
UsedByNode[i] = -1; UsedByNode[i] = -1;
} }
}
FOR_VECTOR (i, _nodes) FOR_VECTOR (i, _refs)
{ {
{ {
CNode &node = _nodes[i]; int nodeIndex = _refs[i];
if (node.IsEmpty if (nodeIndex < 0)
|| node.ParentNode < 0 // not dir continue;
const CNode &node = _nodes[nodeIndex];
if (node.ParentNode < 0 // not dir
|| i == k_INODE_ROOT) || i == k_INODE_ROOT)
continue; continue;
} }
@@ -1352,9 +1421,10 @@ HRESULT CHandler::Open2(IInStream *inStream)
for (;;) for (;;)
{ {
CNode &node = _nodes[c]; int nodeIndex = _refs[c];
if (node.IsEmpty) if (nodeIndex < 0)
return S_FALSE; return S_FALSE;
CNode &node = _nodes[nodeIndex];
if (UsedByNode[c] != -1) if (UsedByNode[c] != -1)
{ {
@@ -1380,14 +1450,17 @@ HRESULT CHandler::Open2(IInStream *inStream)
CByteBuffer data; CByteBuffer data;
unsigned i; unsigned i;
for (i = 0; i < _nodes.Size(); i++) for (i = 0; i < _refs.Size(); i++)
{ {
CNode &node = _nodes[i]; int nodeIndex = _refs[i];
if (node.IsEmpty || !node.IsLink()) if (nodeIndex < 0)
continue;
CNode &node = _nodes[nodeIndex];
if (!node.IsLink())
continue; continue;
if (node.FileSize > ((UInt32)1 << 14)) if (node.FileSize > ((UInt32)1 << 14))
continue; 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()); s.SetFrom_CalcLen((const char *)(const Byte *)data, (unsigned)data.Size());
if (s.Len() == data.Size()) if (s.Len() == data.Size())
@@ -1402,7 +1475,7 @@ HRESULT CHandler::Open2(IInStream *inStream)
for (i = 0; i < _items.Size(); i++) for (i = 0; i < _items.Size(); i++)
{ {
CItem &item = _items[i]; CItem &item = _items[i];
int sym = _nodes[item.Node].SymLinkIndex; int sym = _nodes[_refs[item.Node]].SymLinkIndex;
if (sym >= 0 && item.ParentNode >= 0) if (sym >= 0 && item.ParentNode >= 0)
{ {
item.SymLinkItemIndex = FindTargetItem_for_SymLink(item.ParentNode, _symLinks[sym]); item.SymLinkItemIndex = FindTargetItem_for_SymLink(item.ParentNode, _symLinks[sym]);
@@ -1425,11 +1498,12 @@ HRESULT CHandler::Open2(IInStream *inStream)
bool useSys = false; bool useSys = false;
bool useUnknown = false; bool useUnknown = false;
for (unsigned i = 0; i < _nodes.Size(); i++) FOR_VECTOR (i, _refs)
{ {
const CNode &node = _nodes[i]; int nodeIndex = _refs[i];
if (node.IsEmpty) if (nodeIndex < 0)
continue; continue;
const CNode &node = _nodes[nodeIndex];
if (node.NumLinksCalced == 0 /* || i > 100 && i < 150 */) // for debug if (node.NumLinksCalced == 0 /* || i > 100 && i < 150 */) // for debug
{ {
@@ -1509,6 +1583,7 @@ void CHandler::ClearRefs()
_stream.Release(); _stream.Release();
_items.Clear(); _items.Clear();
_nodes.Clear(); _nodes.Clear();
_refs.Clear();
_auxItems.Clear(); _auxItems.Clear();
_symLinks.Clear(); _symLinks.Clear();
_dirs.Clear(); _dirs.Clear();
@@ -1524,6 +1599,7 @@ STDMETHODIMP CHandler::Close()
_phySize = 0; _phySize = 0;
_isArc = false; _isArc = false;
_headersError = false; _headersError = false;
_headersWarning = false;
_linksError = false; _linksError = false;
_isUTF = true; _isUTF = true;
@@ -1562,7 +1638,7 @@ void CHandler::GetPath(unsigned index, AString &s) const
return; return;
} }
const CNode &node = _nodes[item.ParentNode]; const CNode &node = _nodes[_refs[item.ParentNode]];
if (node.ItemIndex < 0) if (node.ItemIndex < 0)
return; return;
index = node.ItemIndex; index = node.ItemIndex;
@@ -1585,7 +1661,7 @@ bool CHandler::GetPackSize(unsigned index, UInt64 &totalPack) const
} }
const CItem &item = _items[index]; const CItem &item = _items[index];
const CNode &node = _nodes[item.Node]; const CNode &node = _nodes[_refs[item.Node]];
// if (!node.IsFlags_EXTENTS()) // if (!node.IsFlags_EXTENTS())
{ {
@@ -1765,23 +1841,30 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidINodeSize: prop = _h.InodeSize; break; case kpidINodeSize: prop = _h.InodeSize; break;
case kpidId: case kpidId:
{
if (!IsEmptyData(_h.Uuid, 16))
{ {
char s[16 * 2 + 2]; char s[16 * 2 + 2];
for (unsigned i = 0; i < 16; i++) for (unsigned i = 0; i < 16; i++)
PrintHex(_h.Uuid[i], s + i * 2); PrintHex(_h.Uuid[i], s + i * 2);
s[16 * 2] = 0; s[16 * 2] = 0;
prop = s; prop = s;
}
break; break;
} }
case kpidCodePage: if (_isUTF) prop = "UTF-8"; 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 kpidLastMount: StringToProp(_isUTF, _h.LastMount, sizeof(_h.LastMount), prop); break;
case kpidCharacts: FLAGS_TO_PROP(g_FeatureCompat_Flags, _h.FeatureCompat, 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 kpidFeatureIncompat: FLAGS_TO_PROP(g_FeatureIncompat_Flags, _h.FeatureIncompat, prop); break;
case kpidFeatureRoCompat: FLAGS_TO_PROP(g_FeatureRoCompat_Flags, _h.FeatureRoCompat, 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; case kpidPhySize: prop = _phySize; break;
@@ -1797,6 +1880,15 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
prop = v; prop = v;
break; break;
} }
case kpidWarningFlags:
{
UInt32 v = 0;
if (_headersWarning) v |= kpv_ErrorFlags_HeadersError;
if (v != 0)
prop = v;
break;
}
} }
prop.Detach(value); prop.Detach(value);
@@ -1846,7 +1938,7 @@ STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentTyp
} }
else else
{ {
int itemIndex = _nodes[item.ParentNode].ItemIndex; int itemIndex = _nodes[_refs[item.ParentNode]].ItemIndex;
if (itemIndex >= 0) if (itemIndex >= 0)
*parent = itemIndex; *parent = itemIndex;
} }
@@ -1952,7 +2044,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{ {
const CItem &item = _items[index]; const CItem &item = _items[index];
const CNode &node = _nodes[item.Node]; const CNode &node = _nodes[_refs[item.Node]];
bool isDir = node.IsDir(); bool isDir = node.IsDir();
switch (propID) switch (propID)
@@ -1987,7 +2079,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{ {
bool isDir2 = isDir; bool isDir2 = isDir;
if (item.SymLinkItemIndex >= 0) if (item.SymLinkItemIndex >= 0)
isDir2 = _nodes[_items[item.SymLinkItemIndex].Node].IsDir(); isDir2 = _nodes[_refs[_items[item.SymLinkItemIndex].Node]].IsDir();
prop = isDir2; prop = isDir2;
break; 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: class CExtInStream:
public IInStream, public IInStream,
public CMyUnknownImp public CMyUnknownImp
@@ -2057,8 +2261,8 @@ class CExtInStream:
UInt64 _virtPos; UInt64 _virtPos;
UInt64 _phyPos; UInt64 _phyPos;
public: public:
UInt64 _size;
unsigned BlockBits; unsigned BlockBits;
UInt64 Size;
CMyComPtr<IInStream> Stream; CMyComPtr<IInStream> Stream;
CRecordVector<CExtent> Extents; CRecordVector<CExtent> Extents;
@@ -2080,11 +2284,13 @@ STDMETHODIMP CExtInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{ {
if (processedSize) if (processedSize)
*processedSize = 0; *processedSize = 0;
if (_virtPos >= _size) if (_virtPos >= Size)
return S_OK; return S_OK;
UInt64 rem = _size - _virtPos; {
UInt64 rem = Size - _virtPos;
if (size > rem) if (size > rem)
size = (UInt32)rem; size = (UInt32)rem;
}
if (size == 0) if (size == 0)
return S_OK; return S_OK;
@@ -2155,7 +2361,7 @@ STDMETHODIMP CExtInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosi
{ {
case STREAM_SEEK_SET: break; case STREAM_SEEK_SET: break;
case STREAM_SEEK_CUR: offset += _virtPos; 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; default: return STG_E_INVALIDFUNCTION;
} }
if (offset < 0) if (offset < 0)
@@ -2174,6 +2380,8 @@ HRESULT CHandler::FillFileBlocks2(UInt32 block, unsigned level, unsigned numBloc
CByteBuffer &tempBuf = _tempBufs[level]; CByteBuffer &tempBuf = _tempBufs[level];
tempBuf.Alloc(blockSize); tempBuf.Alloc(blockSize);
PRF2(printf("\n level = %d, block = %7d", level, (unsigned)block));
RINOK(SeekAndRead(_stream, block, tempBuf, blockSize)); RINOK(SeekAndRead(_stream, block, tempBuf, blockSize));
const Byte *p = tempBuf; const Byte *p = tempBuf;
@@ -2184,16 +2392,34 @@ HRESULT CHandler::FillFileBlocks2(UInt32 block, unsigned level, unsigned numBloc
if (blocks.Size() == numBlocks) if (blocks.Size() == numBlocks)
break; break;
UInt32 val = GetUi32(p + 4 * i); UInt32 val = GetUi32(p + 4 * i);
if (val == 0 || val >= _h.NumBlocks) if (val >= _h.NumBlocks)
return S_FALSE; return S_FALSE;
if (level != 0) 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)); RINOK(FillFileBlocks2(val, level - 1, numBlocks, blocks));
continue; 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); blocks.Add(val);
} }
@@ -2206,28 +2432,44 @@ static const unsigned kNumDirectNodeBlocks = 12;
HRESULT CHandler::FillFileBlocks(const Byte *p, unsigned numBlocks, CRecordVector<UInt32> &blocks) HRESULT CHandler::FillFileBlocks(const Byte *p, unsigned numBlocks, CRecordVector<UInt32> &blocks)
{ {
// ext2 supports zero blocks (blockIndex == 0).
blocks.ClearAndReserve(numBlocks); blocks.ClearAndReserve(numBlocks);
unsigned i; for (unsigned i = 0; i < kNumDirectNodeBlocks; i++)
for (i = 0; i < kNumDirectNodeBlocks; i++)
{ {
if (i == numBlocks) if (i == numBlocks)
return S_OK; return S_OK;
UInt32 val = GetUi32(p + 4 * i); UInt32 val = GetUi32(p + 4 * i);
if (val == 0 || val >= _h.NumBlocks) if (val >= _h.NumBlocks)
return S_FALSE; return S_FALSE;
blocks.Add(val); blocks.Add(val);
} }
for (i = 0; i < 3; i++) for (unsigned level = 0; level < 3; level++)
{ {
if (blocks.Size() == numBlocks) if (blocks.Size() == numBlocks)
break; break;
UInt32 val = GetUi32(p + 4 * (kNumDirectNodeBlocks + i)); UInt32 val = GetUi32(p + 4 * (kNumDirectNodeBlocks + level));
if (val == 0 || val >= _h.NumBlocks) if (val >= _h.NumBlocks)
return S_FALSE; return S_FALSE;
RINOK(FillFileBlocks2(val, i, numBlocks, blocks));
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, level, numBlocks, blocks));
} }
return S_OK; 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 COM_TRY_BEGIN
@@ -2341,7 +2583,12 @@ HRESULT CHandler::GetStream_Node(UInt32 nodeIndex, ISequentialInStream **stream)
if (!node.IsFlags_EXTENTS()) 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) if (node.NumBlocks == 0 && node.FileSize < kNodeBlockFieldSize)
{ {
Create_BufInStream_WithNewBuffer(node.Block, (size_t)node.FileSize, stream); Create_BufInStream_WithNewBuffer(node.Block, (size_t)node.FileSize, stream);
@@ -2365,7 +2612,7 @@ HRESULT CHandler::GetStream_Node(UInt32 nodeIndex, ISequentialInStream **stream)
streamTemp = streamSpec; streamTemp = streamSpec;
streamSpec->BlockBits = _h.BlockBits; streamSpec->BlockBits = _h.BlockBits;
streamSpec->_size = node.FileSize; streamSpec->Size = node.FileSize;
streamSpec->Stream = _stream; streamSpec->Stream = _stream;
RINOK(FillExtents(node.Block, kNodeBlockFieldSize, streamSpec->Extents, -1)); RINOK(FillExtents(node.Block, kNodeBlockFieldSize, streamSpec->Extents, -1));
@@ -2421,11 +2668,10 @@ HRESULT CHandler::GetStream_Node(UInt32 nodeIndex, ISequentialInStream **stream)
if (numBlocks != numBlocks64) if (numBlocks != numBlocks64)
return S_FALSE; return S_FALSE;
CClusterInStream *streamSpec = new CClusterInStream; CClusterInStream2 *streamSpec = new CClusterInStream2;
streamTemp = streamSpec; streamTemp = streamSpec;
streamSpec->BlockSizeLog = _h.BlockBits; streamSpec->BlockBits = _h.BlockBits;
streamSpec->StartOffset = 0;
streamSpec->Size = node.FileSize; streamSpec->Size = node.FileSize;
streamSpec->Stream = _stream; streamSpec->Stream = _stream;
@@ -2477,7 +2723,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (index >= _items.Size()) if (index >= _items.Size())
continue; continue;
const CItem &item = _items[index]; const CItem &item = _items[index];
const CNode &node = _nodes[item.Node]; const CNode &node = _nodes[_refs[item.Node]];
if (!node.IsDir()) if (!node.IsDir())
totalSize += node.FileSize; totalSize += node.FileSize;
} }
@@ -2520,7 +2766,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
} }
const CItem &item = _items[index]; const CItem &item = _items[index];
const CNode &node = _nodes[item.Node]; const CNode &node = _nodes[_refs[item.Node]];
if (node.IsDir()) if (node.IsDir())
{ {
@@ -2583,7 +2829,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
*stream = NULL; *stream = NULL;
if (index >= _items.Size()) if (index >= _items.Size())
return S_FALSE; 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 }; static const Byte k_Signature[] = { 0x53, 0xEF };
REGISTER_ARC_I( REGISTER_ARC_I(
"Ext", "ext ext3 ext4", 0, 0xC7, "Ext", "ext ext2 ext3 ext4 img", 0, 0xC7,
k_Signature, k_Signature,
0x438, 0x438,
0, 0,

View File

@@ -133,15 +133,23 @@ bool CHeader::Parse(const Byte *p)
default: return false; default: return false;
} }
{ {
int s = GetLog(Get16(p + 11)); {
UInt32 val32 = Get16(p + 11);
int s = GetLog(val32);
if (s < 9 || s > 12) if (s < 9 || s > 12)
return false; return false;
SectorSizeLog = (Byte)s; SectorSizeLog = (Byte)s;
s = GetLog(p[13]); }
{
UInt32 val32 = p[13];
int s = GetLog(val32);
if (s < 0) if (s < 0)
return false; return false;
SectorsPerClusterLog = (Byte)s; SectorsPerClusterLog = (Byte)s;
}
ClusterSizeLog = (Byte)(SectorSizeLog + SectorsPerClusterLog); ClusterSizeLog = (Byte)(SectorSizeLog + SectorsPerClusterLog);
if (ClusterSizeLog > 24)
return false;
} }
NumReservedSectors = Get16(p + 14); NumReservedSectors = Get16(p + 14);

View File

@@ -156,8 +156,15 @@ class CHandler: public CHandlerCont
CByteBuffer _buffer; CByteBuffer _buffer;
HRESULT Open2(IInStream *stream); 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: public:
INTERFACE_IInArchive_Cont(;) INTERFACE_IInArchive_Cont(;)
}; };

View File

@@ -28,7 +28,11 @@ STDMETHODIMP CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 totalSize = 0; UInt64 totalSize = 0;
UInt32 i; UInt32 i;
for (i = 0; i < numItems; 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); extractCallback->SetTotal(totalSize);
totalSize = 0; totalSize = 0;
@@ -56,21 +60,31 @@ STDMETHODIMP CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems,
Int32 index = allFilesMode ? i : indices[i]; Int32 index = allFilesMode ? i : indices[i];
RINOK(extractCallback->GetStream(index, &outStream, askMode)); RINOK(extractCallback->GetStream(index, &outStream, askMode));
UInt64 size = GetItemSize(index);
UInt64 pos, size;
int opRes = GetItem_ExtractInfo(index, pos, size);
totalSize += size; totalSize += size;
if (!testMode && !outStream) if (!testMode && !outStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
RINOK(_stream->Seek(GetItemPos(index), STREAM_SEEK_SET, NULL)); if (opRes == NExtract::NOperationResult::kOK)
{
RINOK(_stream->Seek(pos, STREAM_SEEK_SET, NULL));
streamSpec->Init(size); streamSpec->Init(size);
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
outStream.Release();
int opRes = NExtract::NOperationResult::kDataError; opRes = NExtract::NOperationResult::kDataError;
if (copyCoderSpec->TotalSize == size) if (copyCoderSpec->TotalSize == size)
opRes = NExtract::NOperationResult::kOK; opRes = NExtract::NOperationResult::kOK;
else if (copyCoderSpec->TotalSize < size) else if (copyCoderSpec->TotalSize < size)
opRes = NExtract::NOperationResult::kUnexpectedEnd; opRes = NExtract::NOperationResult::kUnexpectedEnd;
}
outStream.Release();
RINOK(extractCallback->SetOperationResult(opRes)); RINOK(extractCallback->SetOperationResult(opRes));
} }
@@ -81,13 +95,22 @@ STDMETHODIMP CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems,
STDMETHODIMP CHandlerCont::GetStream(UInt32 index, ISequentialInStream **stream) STDMETHODIMP CHandlerCont::GetStream(UInt32 index, ISequentialInStream **stream)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
// const CPartition &item = _items[index]; *stream = NULL;
return CreateLimitedInStream(_stream, GetItemPos(index), GetItemSize(index), stream); UInt64 pos, size;
if (GetItem_ExtractInfo(index, pos, size) != NExtract::NOperationResult::kOK)
return S_FALSE;
return CreateLimitedInStream(_stream, pos, size, stream);
COM_TRY_END COM_TRY_END
} }
CHandlerImg::CHandlerImg():
_imgExt(NULL)
{
ClearStreamVars();
}
STDMETHODIMP CHandlerImg::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) STDMETHODIMP CHandlerImg::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{ {
switch (seekOrigin) switch (seekOrigin)
@@ -190,6 +213,8 @@ STDMETHODIMP CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems,
int opRes = NExtract::NOperationResult::kDataError; int opRes = NExtract::NOperationResult::kDataError;
ClearStreamVars();
CMyComPtr<ISequentialInStream> inStream; CMyComPtr<ISequentialInStream> inStream;
HRESULT hres = GetStream(0, &inStream); HRESULT hres = GetStream(0, &inStream);
if (hres == S_FALSE) if (hres == S_FALSE)
@@ -205,6 +230,13 @@ STDMETHODIMP CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems,
{ {
if (copyCoderSpec->TotalSize == _size) if (copyCoderSpec->TotalSize == _size)
opRes = NExtract::NOperationResult::kOK; 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) else if (copyCoderSpec->TotalSize < _size)
opRes = NExtract::NOperationResult::kUnexpectedEnd; opRes = NExtract::NOperationResult::kUnexpectedEnd;
} }

View File

@@ -30,8 +30,8 @@ class CHandlerCont:
protected: protected:
CMyComPtr<IInStream> _stream; CMyComPtr<IInStream> _stream;
virtual UInt64 GetItemPos(UInt32 index) const = 0; virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const = 0;
virtual UInt64 GetItemSize(UInt32 index) const = 0;
public: public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive_Cont(PURE) 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(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) MY_NO_THROW_DECL_ONLY;
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
// destructor must be virtual for this class
virtual ~CHandlerCont() {}
}; };
@@ -69,6 +72,22 @@ protected:
CMyComPtr<IInStream> Stream; CMyComPtr<IInStream> Stream;
const char *_imgExt; 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 HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) = 0;
virtual void CloseAtError(); virtual void CloseAtError();
public: public:
@@ -83,6 +102,10 @@ public:
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) = 0; STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) = 0;
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
CHandlerImg();
// destructor must be virtual for this class
virtual ~CHandlerImg() {}
}; };

View File

@@ -323,7 +323,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{ {
lps->InSize = lps->OutSize = currentTotalSize + offset; lps->InSize = lps->OutSize = currentTotalSize + offset;
const CDir &item2 = ref.Dir->_subItems[ref.Index + e]; 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); streamSpec->Init(item2.Size);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != item2.Size) if (copyCoderSpec->TotalSize != item2.Size)
@@ -336,7 +336,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
} }
else else
{ {
RINOK(_stream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL)); RINOK(_stream->Seek((UInt64)blockIndex * kBlockSize, STREAM_SEEK_SET, NULL));
streamSpec->Init(currentItemSize); streamSpec->Init(currentItemSize);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != currentItemSize) if (copyCoderSpec->TotalSize != currentItemSize)
@@ -379,7 +379,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
if (item.Size == 0) if (item.Size == 0)
continue; continue;
CSeekExtent se; CSeekExtent se;
se.Phy = (UInt64)item.ExtentLocation * _archive.BlockSize; se.Phy = (UInt64)item.ExtentLocation * kBlockSize;
se.Virt = virtOffset; se.Virt = virtOffset;
extentStreamSpec->Extents.Add(se); extentStreamSpec->Extents.Add(se);
virtOffset += item.Size; virtOffset += item.Size;
@@ -405,7 +405,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
blockIndex = be.LoadRBA; blockIndex = be.LoadRBA;
} }
return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream); return CreateLimitedInStream(_stream, (UInt64)blockIndex * kBlockSize, currentItemSize, stream);
COM_TRY_END COM_TRY_END
} }

View File

@@ -88,15 +88,15 @@ AString CBootInitialEntry::GetName() const
Byte CInArchive::ReadByte() Byte CInArchive::ReadByte()
{ {
if (m_BufferPos >= BlockSize) if (m_BufferPos >= kBlockSize)
m_BufferPos = 0; m_BufferPos = 0;
if (m_BufferPos == 0) if (m_BufferPos == 0)
{ {
size_t processed = BlockSize; size_t processed = kBlockSize;
HRESULT res = ReadStream(_stream, m_Buffer, &processed); HRESULT res = ReadStream(_stream, m_Buffer, &processed);
if (res != S_OK) if (res != S_OK)
throw CSystemException(res); throw CSystemException(res);
if (processed != BlockSize) if (processed != kBlockSize)
throw CUnexpectedEndException(); throw CUnexpectedEndException();
UInt64 end = _position + processed; UInt64 end = _position + processed;
if (PhySize < end) if (PhySize < end)
@@ -511,7 +511,7 @@ HRESULT CInArchive::Open2()
PhySize = _position; PhySize = _position;
m_BufferPos = 0; m_BufferPos = 0;
BlockSize = kBlockSize; // BlockSize = kBlockSize;
for (;;) for (;;)
{ {

View File

@@ -282,7 +282,7 @@ public:
CRecordVector<CRef> Refs; CRecordVector<CRef> Refs;
CObjectVector<CVolumeDescriptor> VolDescs; CObjectVector<CVolumeDescriptor> VolDescs;
int MainVolDescIndex; int MainVolDescIndex;
UInt32 BlockSize; // UInt32 BlockSize;
CObjectVector<CBootInitialEntry> BootEntries; CObjectVector<CBootInitialEntry> BootEntries;
bool IsArc; bool IsArc;
@@ -297,8 +297,8 @@ public:
void UpdatePhySize(UInt32 blockIndex, UInt64 size) void UpdatePhySize(UInt32 blockIndex, UInt64 size)
{ {
UInt64 alignedSize = (size + BlockSize - 1) & ~((UInt64)BlockSize - 1); const UInt64 alignedSize = (size + kBlockSize - 1) & ~((UInt64)kBlockSize - 1);
UInt64 end = blockIndex * BlockSize + alignedSize; const UInt64 end = (UInt64)blockIndex * kBlockSize + alignedSize;
if (PhySize < end) if (PhySize < end)
PhySize = end; PhySize = end;
} }
@@ -315,7 +315,7 @@ public:
size = (1440 << 10); size = (1440 << 10);
else if (be.BootMediaType == NBootMediaType::k2d88Floppy) else if (be.BootMediaType == NBootMediaType::k2d88Floppy)
size = (2880 << 10); size = (2880 << 10);
UInt64 startPos = (UInt64)be.LoadRBA * BlockSize; UInt64 startPos = (UInt64)be.LoadRBA * kBlockSize;
if (startPos < _fileSize) if (startPos < _fileSize)
{ {
if (_fileSize - startPos < size) if (_fileSize - startPos < size)

View File

@@ -158,6 +158,7 @@ static const CPartType kPartTypes[] =
{ 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" }, { 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" },
{ 0x82, 0, "Solaris x86 / Linux swap" }, { 0x82, 0, "Solaris x86 / Linux swap" },
{ 0x83, 0, "Linux" }, { 0x83, 0, "Linux" },
{ 0x8E, "lvm", "Linux LVM" },
{ 0xA5, 0, "BSD slice" }, { 0xA5, 0, "BSD slice" },
{ 0xBE, 0, "Solaris 8 boot" }, { 0xBE, 0, "Solaris 8 boot" },
{ 0xBF, 0, "New Solaris x86" }, { 0xBF, 0, "New Solaris x86" },
@@ -189,8 +190,14 @@ class CHandler: public CHandlerCont
UInt64 _totalSize; UInt64 _totalSize;
CByteBuffer _buffer; CByteBuffer _buffer;
virtual UInt64 GetItemPos(UInt32 index) const { return _items[index].Part.GetPos(); } virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const
virtual UInt64 GetItemSize(UInt32 index) const { return _items[index].Size; } {
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); HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level);
public: public:
INTERFACE_IInArchive_Cont(;) INTERFACE_IInArchive_Cont(;)

View File

@@ -56,8 +56,15 @@ class CHandler: public CHandlerCont
CItem _items[kNumFilesMax]; CItem _items[kNumFilesMax];
HRESULT Open2(IInStream *stream); 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: public:
INTERFACE_IInArchive_Cont(;) INTERFACE_IInArchive_Cont(;)
}; };

View File

@@ -576,20 +576,20 @@ class CInStream:
UInt64 _physPos; UInt64 _physPos;
UInt64 _curRem; UInt64 _curRem;
bool _sparseMode; bool _sparseMode;
size_t _compressedPos;
UInt64 _tags[kNumCacheChunks];
unsigned _chunkSizeLog; unsigned _chunkSizeLog;
UInt64 _tags[kNumCacheChunks];
CByteBuffer _inBuf; CByteBuffer _inBuf;
CByteBuffer _outBuf; CByteBuffer _outBuf;
public: public:
CMyComPtr<IInStream> Stream;
UInt64 Size; UInt64 Size;
UInt64 InitializedSize; UInt64 InitializedSize;
unsigned BlockSizeLog; unsigned BlockSizeLog;
unsigned CompressionUnit; unsigned CompressionUnit;
bool InUse;
CRecordVector<CExtent> Extents; CRecordVector<CExtent> Extents;
bool InUse;
CMyComPtr<IInStream> Stream;
HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
@@ -597,11 +597,11 @@ public:
HRESULT InitAndSeek(unsigned compressionUnit) HRESULT InitAndSeek(unsigned compressionUnit)
{ {
CompressionUnit = compressionUnit; CompressionUnit = compressionUnit;
_chunkSizeLog = BlockSizeLog + CompressionUnit;
if (compressionUnit != 0) if (compressionUnit != 0)
{ {
UInt32 cuSize = GetCuSize(); UInt32 cuSize = GetCuSize();
_inBuf.Alloc(cuSize); _inBuf.Alloc(cuSize);
_chunkSizeLog = BlockSizeLog + CompressionUnit;
_outBuf.Alloc(kNumCacheChunks << _chunkSizeLog); _outBuf.Alloc(kNumCacheChunks << _chunkSizeLog);
} }
for (size_t i = 0; i < kNumCacheChunks; i++) for (size_t i = 0; i < kNumCacheChunks; i++)

View File

@@ -226,8 +226,13 @@ class CHandler: public CHandlerCont
HRESULT ReadHeader(ISequentialInStream *stream, bool isMainHeader); HRESULT ReadHeader(ISequentialInStream *stream, bool isMainHeader);
HRESULT Open2(ISequentialInStream *stream); HRESULT Open2(ISequentialInStream *stream);
virtual UInt64 GetItemPos(UInt32) const { return _headersSize; } virtual int GetItem_ExtractInfo(UInt32 /* index */, UInt64 &pos, UInt64 &size) const
virtual UInt64 GetItemSize(UInt32) const { return _size; } {
pos = _headersSize;
size = _size;
return NExtract::NOperationResult::kOK;
}
public: public:
INTERFACE_IInArchive_Cont(;) INTERFACE_IInArchive_Cont(;)
}; };

View File

@@ -564,7 +564,7 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la
return S_OK; 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) if ((_numRefs & 0xFFF) == 0)
{ {

View File

@@ -252,7 +252,7 @@ struct CItem
bool IsInline; bool IsInline;
CByteBuffer InlineData; CByteBuffer InlineData;
CRecordVector<CMyExtent> Extents; CRecordVector<CMyExtent> Extents;
CRecordVector<int> SubFiles; CUIntVector SubFiles;
void Parse(const Byte *buf); void Parse(const Byte *buf);
@@ -282,7 +282,7 @@ struct CItem
struct CRef struct CRef
{ {
int Parent; int Parent;
int FileIndex; unsigned FileIndex;
}; };
@@ -346,7 +346,7 @@ class CInArchive
HRESULT ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed); HRESULT ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed);
HRESULT Open2(); HRESULT Open2();
HRESULT FillRefs(CFileSet &fs, int fileIndex, int parent, int numRecurseAllowed); HRESULT FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed);
UInt64 _processedProgressBytes; UInt64 _processedProgressBytes;

View File

File diff suppressed because it is too large Load Diff

View File

@@ -723,7 +723,7 @@ static HRESULT Update2(
CThreads threads; CThreads threads;
CRecordVector<HANDLE> compressingCompletedEvents; 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))); RINOK(memManager.AllocateSpaceAlways((size_t)numThreads * (kMemPerThread / kBlockSize)));
@@ -759,7 +759,7 @@ static HRESULT Update2(
while (itemIndex < updateItems.Size()) while (itemIndex < updateItems.Size())
{ {
if ((UInt32)threadIndices.Size() < numThreads && mtItemIndex < updateItems.Size()) if (threadIndices.Size() < numThreads && mtItemIndex < updateItems.Size())
{ {
CUpdateItem &ui = updateItems[mtItemIndex++]; CUpdateItem &ui = updateItems[mtItemIndex++];
if (!ui.NewData) if (!ui.NewData)

View File

@@ -513,10 +513,11 @@ static int main2(int numArgs, const char *args[])
if (parser[NKey::kEOS].ThereIs || stdInMode) if (parser[NKey::kEOS].ThereIs || stdInMode)
throw "Can not use stdin in this mode"; throw "Can not use stdin in this mode";
if (fileSize > 0xF0000000) size_t inSize = (size_t)fileSize;
if (inSize != fileSize)
throw "File is too big"; throw "File is too big";
size_t inSize = (size_t)fileSize;
Byte *inBuffer = NULL; Byte *inBuffer = NULL;
if (inSize != 0) if (inSize != 0)
@@ -535,7 +536,13 @@ static int main2(int numArgs, const char *args[])
if (encodeMode) if (encodeMode)
{ {
// we allocate 105% of original size for output buffer // 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) if (outSize != 0)
{ {
outBuffer = (Byte *)MyAlloc((size_t)outSize); outBuffer = (Byte *)MyAlloc((size_t)outSize);
@@ -561,7 +568,7 @@ static int main2(int numArgs, const char *args[])
outSize = (size_t)outSize64; outSize = (size_t)outSize64;
if (outSize != outSize64) if (outSize != outSize64)
throw "too big"; throw "Unpack size is too big";
if (outSize != 0) if (outSize != 0)
{ {
outBuffer = (Byte *)MyAlloc(outSize); outBuffer = (Byte *)MyAlloc(outSize);

View File

@@ -366,6 +366,10 @@ SOURCE=..\..\..\..\C\7zCrcOpt.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\..\..\C\7zTypes.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Alloc.c SOURCE=..\..\..\..\C\Alloc.c
# SUBTRACT CPP /YX /Yc /Yu # SUBTRACT CPP /YX /Yc /Yu
# End Source File # End Source File
@@ -464,10 +468,6 @@ SOURCE=..\..\..\..\C\Threads.c
SOURCE=..\..\..\..\C\Threads.h SOURCE=..\..\..\..\C\Threads.h
# End Source File # End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Types.h
# End Source File
# End Group # End Group
# Begin Source File # Begin Source File

View File

@@ -86,26 +86,34 @@ STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSi
*processedSize = 0; *processedSize = 0;
if (_virtPos >= Size) if (_virtPos >= Size)
return S_OK; return S_OK;
{
UInt64 rem = Size - _virtPos;
if (size > rem)
size = (UInt32)rem;
}
if (size == 0)
return S_OK;
if (_curRem == 0) if (_curRem == 0)
{ {
UInt32 blockSize = (UInt32)1 << BlockSizeLog; const UInt32 blockSize = (UInt32)1 << BlockSizeLog;
UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog); const UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog);
UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1); const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);
UInt32 phyBlock = Vector[virtBlock]; const UInt32 phyBlock = Vector[virtBlock];
UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock; UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock;
if (newPos != _physPos) if (newPos != _physPos)
{ {
_physPos = newPos; _physPos = newPos;
RINOK(SeekToPhys()); RINOK(SeekToPhys());
} }
_curRem = blockSize - offsetInBlock; _curRem = blockSize - offsetInBlock;
for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++) for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++)
_curRem += (UInt32)1 << BlockSizeLog; _curRem += (UInt32)1 << BlockSizeLog;
UInt64 rem = Size - _virtPos;
if (_curRem > rem)
_curRem = (UInt32)rem;
} }
if (size > _curRem) if (size > _curRem)
size = _curRem; size = _curRem;
HRESULT res = Stream->Read(data, size, &size); HRESULT res = Stream->Read(data, size, &size);

View File

@@ -73,11 +73,11 @@ class CClusterInStream:
UInt64 _physPos; UInt64 _physPos;
UInt32 _curRem; UInt32 _curRem;
public: public:
CMyComPtr<IInStream> Stream;
UInt64 StartOffset;
UInt64 Size;
unsigned BlockSizeLog; unsigned BlockSizeLog;
UInt64 Size;
CMyComPtr<IInStream> Stream;
CRecordVector<UInt32> Vector; CRecordVector<UInt32> Vector;
UInt64 StartOffset;
HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }

View File

@@ -90,51 +90,65 @@ HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 default
return ParsePropToUInt32(name, prop, numThreads); 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; const wchar_t *end;
UInt32 number = ConvertStringToUInt32(s, &end); UInt32 number = ConvertStringToUInt32(s, &end);
unsigned numDigits = (unsigned)(end - s); unsigned numDigits = (unsigned)(end - s);
if (numDigits == 0 || s.Len() > numDigits + 1) if (numDigits == 0 || s.Len() > numDigits + 1)
return E_INVALIDARG; return E_INVALIDARG;
const unsigned kLogDictSizeLimit = 32;
if (s.Len() == numDigits) if (s.Len() == numDigits)
{ {
if (number >= kLogDictSizeLimit) if (number >= 64)
return E_INVALIDARG; 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; return S_OK;
} }
unsigned numBits; unsigned numBits;
switch (MyCharLower_Ascii(s[numDigits])) 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 'k': numBits = 10; break;
case 'm': numBits = 20; break; case 'm': numBits = 20; break;
case 'g': numBits = 30; break; case 'g': numBits = 30; break;
default: return E_INVALIDARG; default: return E_INVALIDARG;
} }
if (number >= ((UInt32)1 << (kLogDictSizeLimit - numBits)))
return E_INVALIDARG; if (number < ((UInt32)1 << (32 - numBits)))
dicSize = number << numBits; destProp = (UInt32)(number << numBits);
else
destProp = (UInt64)((UInt64)number << numBits);
return S_OK; 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) if (prop.vt == VT_UI4)
{ {
UInt32 v = prop.ulVal; UInt32 v = prop.ulVal;
if (v >= 32) if (v >= 64)
return E_INVALIDARG; 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; return S_OK;
} }
if (prop.vt == VT_BSTR) if (prop.vt == VT_BSTR)
return StringToDictSize(prop.bstrVal, resValue); return StringToDictSize(prop.bstrVal, destProp);
return E_INVALIDARG; return E_INVALIDARG;
} }
void CProps::AddProp32(PROPID propid, UInt32 level) void CProps::AddProp32(PROPID propid, UInt32 level)
{ {
CProp &prop = Props.AddNew(); CProp &prop = Props.AddNew();
@@ -275,10 +289,10 @@ static void SplitParams(const UString &srcString, UStringVector &subStrings)
{ {
subStrings.Clear(); subStrings.Clear();
UString s; UString s;
int len = srcString.Len(); unsigned len = srcString.Len();
if (len == 0) if (len == 0)
return; return;
for (int i = 0; i < len; i++) for (unsigned i = 0; i < len; i++)
{ {
wchar_t c = srcString[i]; wchar_t c = srcString[i];
if (c == L':') if (c == L':')
@@ -336,9 +350,7 @@ HRESULT CMethodProps::SetParam(const UString &name, const UString &value)
if (IsLogSizeProp(prop.Id)) if (IsLogSizeProp(prop.Id))
{ {
UInt32 dicSize; RINOK(StringToDictSize(value, prop.Value));
RINOK(StringToDictSize(value, dicSize));
prop.Value = dicSize;
} }
else else
{ {
@@ -406,9 +418,7 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const
if (IsLogSizeProp(prop.Id)) if (IsLogSizeProp(prop.Id))
{ {
UInt32 dicSize; RINOK(PROPVARIANT_to_DictSize(value, prop.Value));
RINOK(PROPVARIANT_to_DictSize(value, dicSize));
prop.Value = dicSize;
} }
else else
{ {

View File

@@ -38,7 +38,20 @@ HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzm
switch (propID) switch (propID)
{ {
case NCoderPropID::kBlockSize: 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: case NCoderPropID::kNumThreads:
if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.numTotalThreads = (int)(prop.ulVal); break; if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.numTotalThreads = (int)(prop.ulVal); break;
default: default:

View File

@@ -441,7 +441,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
} }
} }
if (_outFileStream != NULL) if (_outFileStream)
{ {
if (_processedFileInfo.MTimeDefined) if (_processedFileInfo.MTimeDefined)
_outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);
@@ -499,7 +499,6 @@ public:
STDMETHOD(SetCompleted)(const UInt64 *completeValue); STDMETHOD(SetCompleted)(const UInt64 *completeValue);
// IUpdateCallback2 // IUpdateCallback2
STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);
STDMETHOD(GetUpdateItemInfo)(UInt32 index, STDMETHOD(GetUpdateItemInfo)(UInt32 index,
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
@@ -551,20 +550,14 @@ STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValu
return S_OK; return S_OK;
} }
STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */)
{
return E_NOTIMPL;
}
STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */,
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
{ {
if (newData != NULL) if (newData)
*newData = BoolToInt(true); *newData = BoolToInt(true);
if (newProperties != NULL) if (newProperties)
*newProperties = BoolToInt(true); *newProperties = BoolToInt(true);
if (indexInArchive != NULL) if (indexInArchive)
*indexInArchive = (UInt32)(Int32)-1; *indexInArchive = (UInt32)(Int32)-1;
return S_OK; return S_OK;
} }

View File

@@ -108,34 +108,52 @@ static const char *kHelpString =
" h : Calculate hash values for files\n" " h : Calculate hash values for files\n"
" i : Show information about supported formats\n" " i : Show information about supported formats\n"
" l : List contents of archive\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" " rn : Rename files in archive\n"
" t : Test integrity of archive\n" " t : Test integrity of archive\n"
" u : Update files to archive\n" " u : Update files to archive\n"
" x : eXtract files with full paths\n" " x : eXtract files with full paths\n"
"\n"
"<Switches>\n" "<Switches>\n"
" -- : Stop switches parsing\n" " -- : Stop switches parsing\n"
" -ai[r[-|0]]{@listfile|!wildcard} : Include archives\n" " -ai[r[-|0]]{@listfile|!wildcard} : Include archives\n"
" -ax[r[-|0]]{@listfile|!wildcard} : eXclude 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" " -i[r[-|0]]{@listfile|!wildcard} : Include filenames\n"
" -m{Parameters} : set compression Method\n" " -m{Parameters} : set compression Method\n"
" -mmt[N] : set number of CPU threads\n"
" -o{Directory} : set Output directory\n" " -o{Directory} : set Output directory\n"
#ifndef _NO_CRYPTO #ifndef _NO_CRYPTO
" -p{Password} : set Password\n" " -p{Password} : set Password\n"
#endif #endif
" -r[-|0] : Recurse subdirectories\n" " -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" " -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" " -sfx[{name}] : Create SFX archive\n"
" -si[{name}] : read data from stdin\n" " -si[{name}] : read data from stdin\n"
" -slp : set Large Pages mode\n"
" -slt : show technical information for l (List) command\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" " -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" " -ssc[-] : set sensitive case mode\n"
" -ssw : compress shared files\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" " -t{Type} : Set type of archive\n"
" -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n" " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n"
" -v{Size}[b|k|m|g] : Create volumes\n" " -v{Size}[b|k|m|g] : Create volumes\n"

View File

@@ -85,7 +85,7 @@ public:
CRecordVector<bool> NeedWait; CRecordVector<bool> NeedWait;
~CChildProcesses() { CloseAll(); } ~CChildProcesses() { CloseAll(); }
void DisableWait(int index) { NeedWait[index] = false; } void DisableWait(unsigned index) { NeedWait[index] = false; }
void CloseAll() 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) 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; UINT32 result;
#ifndef _UNICODE #ifndef _UNICODE
if (g_IsNT) 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.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
execInfo.hwnd = NULL; execInfo.hwnd = NULL;
execInfo.lpVerb = NULL; execInfo.lpVerb = NULL;
execInfo.lpFile = path; execInfo.lpFile = path2;
execInfo.lpParameters = NULL; execInfo.lpParameters = NULL;
execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir; execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir;
execInfo.nShow = SW_SHOWNORMAL; execInfo.nShow = SW_SHOWNORMAL;
execInfo.hProcess = 0; execInfo.hProcess = 0;
ShellExecuteExWP shellExecuteExW = (ShellExecuteExWP) ShellExecuteExWP shellExecuteExW = (ShellExecuteExWP)
::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "ShellExecuteExW"); ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "ShellExecuteExW");
if (shellExecuteExW == 0) if (!shellExecuteExW)
return 0; return 0;
shellExecuteExW(&execInfo); shellExecuteExW(&execInfo);
result = (UINT32)(UINT_PTR)execInfo.hInstApp; result = (UINT32)(UINT_PTR)execInfo.hInstApp;
@@ -525,7 +537,7 @@ static HRESULT StartApplication(const UString &dir, const UString &path, HWND wi
; ;
execInfo.hwnd = NULL; execInfo.hwnd = NULL;
execInfo.lpVerb = NULL; execInfo.lpVerb = NULL;
const CSysString sysPath = GetSystemString(path); const CSysString sysPath = GetSystemString(path2);
const CSysString sysDir = GetSystemString(dir); const CSysString sysDir = GetSystemString(dir);
execInfo.lpFile = sysPath; execInfo.lpFile = sysPath;
execInfo.lpParameters = NULL; execInfo.lpParameters = NULL;
@@ -542,6 +554,7 @@ static HRESULT StartApplication(const UString &dir, const UString &path, HWND wi
result = (UINT32)(UINT_PTR)execInfo.hInstApp; result = (UINT32)(UINT_PTR)execInfo.hInstApp;
process.Attach(execInfo.hProcess); process.Attach(execInfo.hProcess);
} }
if (result <= 32) if (result <= 32)
{ {
switch (result) switch (result)
@@ -553,6 +566,7 @@ static HRESULT StartApplication(const UString &dir, const UString &path, HWND wi
L"7-Zip", MB_OK | MB_ICONSTOP); L"7-Zip", MB_OK | MB_ICONSTOP);
} }
} }
return S_OK; return S_OK;
} }
@@ -795,7 +809,7 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param)
for (;;) for (;;)
{ {
CRecordVector<HANDLE> handles; CRecordVector<HANDLE> handles;
CRecordVector<int> indices; CUIntVector indices;
FOR_VECTOR (i, processes.Handles) 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) void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode, bool useEditor, const wchar_t *type)
{ {
const UString name = GetItemName(index); 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)); bool tryAsArchive = tryInternal && (!tryExternal || !DoItemAlwaysStart(name));
UString fullVirtPath = _currentFolderPrefix + relPath; const UString fullVirtPath = _currentFolderPrefix + relPath;
CTempDir tempDirectory; CTempDir tempDirectory;
if (!tempDirectory.Create(kTempDirPrefix)) 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 // probably we must show some message here
// return; // return;
} }
if (!tryExternal)
return;
} }
} }
} }
@@ -1126,6 +1153,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
options.folder = fs2us(tempDirNorm); options.folder = fs2us(tempDirNorm);
options.showErrorMessages = true; options.showErrorMessages = true;
HRESULT result = CopyTo(options, indices, &messages, usePassword, password); HRESULT result = CopyTo(options, indices, &messages, usePassword, password);
if (_parentFolders.Size() > 0) if (_parentFolders.Size() > 0)

View File

@@ -8,13 +8,14 @@
#include "../../../Windows/Control/Static.h" #include "../../../Windows/Control/Static.h"
#include "../../../Windows/ErrorMsg.h" #include "../../../Windows/ErrorMsg.h"
#include "ProgressDialog2.h"
#include "DialogSize.h"
#include "ProgressDialog2Res.h"
#include "../GUI/ExtractRes.h" #include "../GUI/ExtractRes.h"
#include "LangUtils.h"
#include "DialogSize.h"
#include "ProgressDialog2.h"
#include "ProgressDialog2Res.h"
using namespace NWindows; using namespace NWindows;
extern HINSTANCE g_hInstance; extern HINSTANCE g_hInstance;
@@ -42,8 +43,6 @@ static const UINT kCreateDelay =
static const DWORD kPauseSleepTime = 100; static const DWORD kPauseSleepTime = 100;
#include "LangUtils.h"
#ifdef LANG #ifdef LANG
static const UInt32 kLangIDs[] = static const UInt32 kLangIDs[] =
@@ -705,10 +704,9 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
UInt32 curTime = ::GetTickCount(); 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)) if (IS_UNDEFINED_VAL(progressTotal))
{ {
// SetPos(0); // 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)) if (IS_DEFINED_VAL(_prevRemainingSec))
{ {
@@ -770,8 +768,8 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
else else
{ {
UInt64 remainingTime = 0; UInt64 remainingTime = 0;
if (completed < total) if (progressCompleted < progressTotal)
remainingTime = MyMultAndDiv(_elapsedTime, total - completed, completed); remainingTime = MyMultAndDiv(_elapsedTime, progressTotal - progressCompleted, progressCompleted);
UInt64 remainingSec = remainingTime / 1000; UInt64 remainingSec = remainingTime / 1000;
if (remainingSec != _prevRemainingSec) if (remainingSec != _prevRemainingSec)
{ {
@@ -783,7 +781,7 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
} }
{ {
UInt64 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime; UInt64 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime;
UInt64 v = (completed * 1000) / elapsedTime; UInt64 v = (progressCompleted * 1000) / elapsedTime;
Byte c = 0; Byte c = 0;
unsigned moveBits = 0; unsigned moveBits = 0;
if (v >= ((UInt64)10000 << 10)) { moveBits = 20; c = 'M'; } if (v >= ((UInt64)10000 << 10)) { moveBits = 20; c = 'M'; }
@@ -811,11 +809,11 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
{ {
UInt64 percent = 0; UInt64 percent = 0;
{ {
if (IS_DEFINED_VAL(total)) if (IS_DEFINED_VAL(progressTotal))
{ {
percent = completed * 100; percent = progressCompleted * 100;
if (total != 0) if (progressTotal != 0)
percent /= total; percent /= progressTotal;
} }
} }
if (percent != _prevPercentValue) if (percent != _prevPercentValue)

View File

@@ -40,7 +40,10 @@ HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw()
{ {
p->bstrVal = AllocBstrFromAscii(s); p->bstrVal = AllocBstrFromAscii(s);
if (p->bstrVal) if (p->bstrVal)
{
p->vt = VT_BSTR;
return S_OK; return S_OK;
}
p->vt = VT_ERROR; p->vt = VT_ERROR;
p->scode = E_OUTOFMEMORY; p->scode = E_OUTOFMEMORY;
return E_OUTOFMEMORY; return E_OUTOFMEMORY;

View File

@@ -10,8 +10,8 @@ AppName = "7-Zip"
InstallDir = %CE1%\%AppName% InstallDir = %CE1%\%AppName%
[Strings] [Strings]
AppVer = "15.08" AppVer = "15.09"
AppDate = "2015-10-01" AppDate = "2015-10-16"
[CEDevice] [CEDevice]
; ProcessorType = 2577 ; ARM ; ProcessorType = 2577 ; ARM

View File

@@ -2,7 +2,7 @@
;Defines ;Defines
!define VERSION_MAJOR 15 !define VERSION_MAJOR 15
!define VERSION_MINOR 08 !define VERSION_MINOR 09
!define VERSION_POSTFIX_FULL " beta" !define VERSION_POSTFIX_FULL " beta"
!ifdef WIN64 !ifdef WIN64
!ifdef IA64 !ifdef IA64

View File

@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<?define VerMajor = "15" ?> <?define VerMajor = "15" ?>
<?define VerMinor = "08" ?> <?define VerMinor = "09" ?>
<?define VerBuild = "00" ?> <?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?> <?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>

View File

@@ -1,4 +1,4 @@
7-Zip 15.08 Sources 7-Zip 15.09 Sources
------------------- -------------------
7-Zip is a file archiver for Windows. 7-Zip is a file archiver for Windows.

View File

@@ -1,6 +1,20 @@
HISTORY of the 7-Zip source code 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 9.38 beta 2015-01-03
------------------------- -------------------------
- The BUG in 9.31-9.37 was fixed: - The BUG in 9.31-9.37 was fixed: