This commit is contained in:
Igor Pavlov
2011-04-11 00:00:00 +00:00
committed by Kornel Lesiński
parent de4f8c22fe
commit 35596517f2
322 changed files with 9989 additions and 7759 deletions

View File

@@ -1,15 +1,24 @@
/* 7zCrc.c -- CRC32 calculation
2009-11-23 : Igor Pavlov : Public domain */
/* 7zCrc.c -- CRC32 init
2010-12-01 : Igor Pavlov : Public domain */
#include "7zCrc.h"
#include "CpuArch.h"
#define kCrcPoly 0xEDB88320
#ifdef MY_CPU_LE
#define CRC_NUM_TABLES 8
#ifdef MY_CPU_X86_OR_AMD64
#define CRC_NUM_TABLES 8
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
#elif defined(MY_CPU_LE)
#define CRC_NUM_TABLES 4
#else
#define CRC_NUM_TABLES 1
#define CRC_NUM_TABLES 5
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif
#ifndef MY_CPU_BE
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
@@ -17,25 +26,6 @@ typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size,
static CRC_FUNC g_CrcUpdate;
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
#if CRC_NUM_TABLES == 1
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
#else
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
{
return g_CrcUpdate(v, data, size, g_CrcTable);
@@ -57,18 +47,37 @@ void MY_FAST_CALL CrcGenerateTable()
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
g_CrcTable[i] = r;
}
#if CRC_NUM_TABLES == 1
g_CrcUpdate = CrcUpdateT1;
#else
for (; i < 256 * CRC_NUM_TABLES; i++)
{
UInt32 r = g_CrcTable[i - 256];
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
}
#ifdef MY_CPU_LE
g_CrcUpdate = CrcUpdateT4;
#ifdef MY_CPU_X86_OR_AMD64
#if CRC_NUM_TABLES == 8
if (!CPU_Is_InOrder())
g_CrcUpdate = CrcUpdateT8;
#endif
#else
{
#ifndef MY_CPU_BE
UInt32 k = 1;
if (*(const Byte *)&k == 1)
g_CrcUpdate = CrcUpdateT4;
else
#endif
{
for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)
{
UInt32 x = g_CrcTable[i - 256];
g_CrcTable[i] = CRC_UINT32_SWAP(x);
}
g_CrcUpdate = CrcUpdateT1_BeT4;
}
}
#endif
}

View File

@@ -1,12 +1,12 @@
/* 7zCrcOpt.c -- CRC32 calculation : optimized version
2009-11-23 : Igor Pavlov : Public domain */
/* 7zCrcOpt.c -- CRC32 calculation
2010-12-01 : Igor Pavlov : Public domain */
#include "CpuArch.h"
#ifdef MY_CPU_LE
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
#ifndef MY_CPU_BE
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
@@ -32,3 +32,33 @@ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const U
}
#endif
#ifndef MY_CPU_LE
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
v = CRC_UINT32_SWAP(v);
table += 0x100;
for (; size >= 4; size -= 4, p += 4)
{
v ^= *(const UInt32 *)p;
v =
table[0x000 + (v & 0xFF)] ^
table[0x100 + ((v >> 8) & 0xFF)] ^
table[0x200 + ((v >> 16) & 0xFF)] ^
table[0x300 + ((v >> 24))];
}
table -= 0x100;
v = CRC_UINT32_SWAP(v);
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
#endif

View File

@@ -1,7 +1,7 @@
#define MY_VER_MAJOR 9
#define MY_VER_MINOR 20
#define MY_VER_BUILD 0
#define MY_VERSION "9.20"
#define MY_DATE "2010-11-18"
#define MY_VER_MINOR 21
#define MY_VER_BUILD 00
#define MY_VERSION "9.21 beta"
#define MY_DATE "2011-04-11"
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

View File

@@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code
2010-10-26: Igor Pavlov : Public domain */
2010-12-01: Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H
#define __CPU_ARCH_H
@@ -52,7 +52,7 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
#define MY_CPU_LE
#endif
#if defined(__BIG_ENDIAN__)
#if defined(__BIG_ENDIAN__) || defined(__m68k__) || defined(__ARMEB__) || defined(__MIPSEB__)
#define MY_CPU_BE
#endif

View File

@@ -1,5 +1,5 @@
/* Lzma2Dec.c -- LZMA2 Decoder
2009-05-03 : Igor Pavlov : Public domain */
2010-12-15 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */
@@ -330,27 +330,21 @@ SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
{
CLzma2Dec decoder;
CLzma2Dec p;
SRes res;
SizeT outSize = *destLen, inSize = *srcLen;
Byte props[LZMA_PROPS_SIZE];
Lzma2Dec_Construct(&decoder);
*destLen = *srcLen = 0;
*status = LZMA_STATUS_NOT_SPECIFIED;
decoder.decoder.dic = dest;
decoder.decoder.dicBufSize = outSize;
RINOK(Lzma2Dec_GetOldProps(prop, props));
RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
Lzma2Dec_Construct(&p);
RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
p.decoder.dic = dest;
p.decoder.dicBufSize = outSize;
Lzma2Dec_Init(&p);
*srcLen = inSize;
res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
*destLen = decoder.decoder.dicPos;
res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
*destLen = p.decoder.dicPos;
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
res = SZ_ERROR_INPUT_EOF;
LzmaDec_FreeProbs(&decoder.decoder, alloc);
Lzma2Dec_FreeProbs(&p, alloc);
return res;
}

View File

@@ -1,5 +1,5 @@
/* LzmaDec.c -- LZMA Decoder
2009-09-20 : Igor Pavlov : Public domain */
2010-12-15 : Igor Pavlov : Public domain */
#include "LzmaDec.h"
@@ -442,8 +442,9 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
p->processedPos += len;
p->remainLen -= len;
while (len-- != 0)
while (len != 0)
{
len--;
dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
dicPos++;
}
@@ -972,28 +973,21 @@ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
{
CLzmaDec p;
SRes res;
SizeT inSize = *srcLen;
SizeT outSize = *destLen;
*srcLen = *destLen = 0;
SizeT outSize = *destLen, inSize = *srcLen;
*destLen = *srcLen = 0;
*status = LZMA_STATUS_NOT_SPECIFIED;
if (inSize < RC_INIT_SIZE)
return SZ_ERROR_INPUT_EOF;
LzmaDec_Construct(&p);
res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
if (res != 0)
return res;
RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc));
p.dic = dest;
p.dicBufSize = outSize;
LzmaDec_Init(&p);
*srcLen = inSize;
res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
*destLen = p.dicPos;
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
res = SZ_ERROR_INPUT_EOF;
(*destLen) = p.dicPos;
LzmaDec_FreeProbs(&p, alloc);
return res;
}

View File

@@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder
2010-04-16 : Igor Pavlov : Public domain */
2011-01-27 : Igor Pavlov : Public domain */
#include <string.h>
@@ -46,6 +46,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p)
{
p->level = 5;
p->dictSize = p->mc = 0;
p->reduceSize = (UInt32)(Int32)-1;
p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
p->writeEndMark = 0;
}
@@ -56,6 +57,15 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
if (level < 0) level = 5;
p->level = level;
if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
if (p->dictSize > p->reduceSize)
{
unsigned i;
for (i = 15; i <= 30; i++)
{
if (p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }
if (p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }
}
}
if (p->lc < 0) p->lc = 3;
if (p->lp < 0) p->lp = 0;
if (p->pb < 0) p->pb = 2;
@@ -329,7 +339,6 @@ typedef struct
SRes result;
UInt32 dictSize;
UInt32 matchFinderCycles;
int needInit;
@@ -398,7 +407,6 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30))
return SZ_ERROR_PARAM;
p->dictSize = props.dictSize;
p->matchFinderCycles = props.mc;
{
unsigned fb = props.fb;
if (fb < 5)

View File

@@ -1,14 +1,12 @@
/* LzmaEnc.h -- LZMA Encoder
2009-02-07 : Igor Pavlov : Public domain */
2011-01-27 : Igor Pavlov : Public domain */
#ifndef __LZMA_ENC_H
#define __LZMA_ENC_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
EXTERN_C_BEGIN
#define LZMA_PROPS_SIZE 5
@@ -18,6 +16,8 @@ typedef struct _CLzmaEncProps
UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
(1 << 12) <= dictSize <= (1 << 30) for 64-bit version
default = (1 << 24) */
UInt32 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF.
Encoder uses this value to reduce dictionary size */
int lc; /* 0 <= lc <= 8, default = 3 */
int lp; /* 0 <= lp <= 4, default = 0 */
int pb; /* 0 <= pb <= 4, default = 2 */
@@ -73,8 +73,6 @@ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
#ifdef __cplusplus
}
#endif
EXTERN_C_END
#endif

View File

@@ -1,5 +1,5 @@
/* Ppmd.h -- PPMD codec common code
2010-03-12 : Igor Pavlov : Public domain
2011-01-27 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#ifndef __PPMD_H
@@ -29,6 +29,9 @@ EXTERN_C_BEGIN
#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
#pragma pack(push, 1)
/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */
/* SEE-contexts for PPM-contexts with masked symbols */
typedef struct
{
@@ -48,6 +51,8 @@ typedef struct
UInt16 SuccessorHigh;
} CPpmd_State;
#pragma pack(pop)
typedef
#ifdef PPMD_32BIT
CPpmd_State *

View File

@@ -1,5 +1,5 @@
/* Ppmd8.h -- PPMdI codec
2010-03-24 : Igor Pavlov : Public domain
2011-01-27 : Igor Pavlov : Public domain
This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
@@ -24,6 +24,8 @@ typedef
#endif
CPpmd8_Context_Ref;
#pragma pack(push, 1)
typedef struct CPpmd8_Context_
{
Byte NumStats;
@@ -33,6 +35,8 @@ typedef struct CPpmd8_Context_
CPpmd8_Context_Ref Suffix;
} CPpmd8_Context;
#pragma pack(pop)
#define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
/* The BUG in Shkarin's code for FREEZE mode was fixed, but that fixed

View File

@@ -1,5 +1,5 @@
/* SfxSetup.c - 7z SFX Setup
2010-11-11 : Igor Pavlov : Public domain */
2010-12-13 : Igor Pavlov : Public domain */
#ifndef UNICODE
#define UNICODE
@@ -128,26 +128,21 @@ static Bool FindSignature(CSzFile *stream, UInt64 *resPos)
*resPos = 0;
for (;;)
{
size_t numTests, pos;
size_t processed, pos;
if (*resPos > kSignatureSearchLimit)
return False;
do
{
size_t processed = kBufferSize - numPrevBytes;
processed = kBufferSize - numPrevBytes;
if (File_Read(stream, buf + numPrevBytes, &processed) != 0)
return False;
if (processed == 0)
processed += numPrevBytes;
if (processed < k7zStartHeaderSize ||
(processed == k7zStartHeaderSize && numPrevBytes != 0))
return False;
numPrevBytes += processed;
}
while (numPrevBytes <= k7zStartHeaderSize);
numTests = numPrevBytes - k7zStartHeaderSize;
for (pos = 0; pos < numTests; pos++)
processed -= k7zStartHeaderSize;
for (pos = 0; pos <= processed; pos++)
{
for (; buf[pos] != '7' && pos < numTests; pos++);
if (pos == numTests)
for (; buf[pos] != '7' && pos <= processed; pos++);
if (pos > processed)
break;
if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0)
if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8))
@@ -156,9 +151,9 @@ static Bool FindSignature(CSzFile *stream, UInt64 *resPos)
return True;
}
}
*resPos += numTests;
numPrevBytes -= numTests;
memmove(buf, buf + numTests, numPrevBytes);
*resPos += processed;
numPrevBytes = k7zStartHeaderSize;
memmove(buf, buf + processed, k7zStartHeaderSize);
}
}

View File

@@ -1,6 +1,6 @@
PROG = 7zS2.sfx
LIBS = $(LIBS)
CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE
CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE -D_CRT_SECURE_NO_WARNINGS
C_OBJS = \
$O\7zAlloc.obj \

10
C/Xz.h
View File

@@ -1,5 +1,5 @@
/* Xz.h - Xz interface
2010-09-17 : Igor Pavlov : Public domain */
2011-01-09 : Igor Pavlov : Public domain */
#ifndef __XZ_H
#define __XZ_H
@@ -220,7 +220,8 @@ typedef struct
Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];
} CXzUnpacker;
SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc);
void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc);
void XzUnpacker_Init(CXzUnpacker *p);
void XzUnpacker_Free(CXzUnpacker *p);
/*
@@ -232,8 +233,9 @@ finishMode:
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
CODER_STATUS_NOT_FINISHED,
CODER_STATUS_NEEDS_MORE_INPUT - maybe there are more xz streams,
call XzUnpacker_IsStreamWasFinished to check that current stream was finished
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties

View File

@@ -1,5 +1,5 @@
/* XzDec.c -- Xz Decode
2010-04-16 : Igor Pavlov : Public domain */
2011-02-07 : Igor Pavlov : Public domain */
/* #define XZ_DUMP */
@@ -18,7 +18,8 @@
#include "Lzma2Dec.h"
#ifdef USE_SUBBLOCK
#include "SbDec.h"
#include "Bcj3Dec.c"
#include "SbDec.c"
#endif
#include "Xz.h"
@@ -72,7 +73,6 @@ SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *a
{
CBraState *p = ((CBraState *)pp);
alloc = alloc;
p->encodeMode = 0;
p->ip = 0;
if (p->methodId == XZ_ID_Delta)
{
@@ -195,7 +195,7 @@ static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src,
return SZ_OK;
}
SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc)
SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc)
{
CBraState *decoder;
if (id != XZ_ID_Delta &&
@@ -211,6 +211,7 @@ SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc)
if (decoder == 0)
return SZ_ERROR_MEM;
decoder->methodId = (UInt32)id;
decoder->encodeMode = encodeMode;
p->p = decoder;
p->Free = BraState_Free;
p->SetProps = BraState_SetProps;
@@ -225,8 +226,8 @@ SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc)
static void SbState_Free(void *pp, ISzAlloc *alloc)
{
CSubblockDec *p = (CSubblockDec *)pp;
SubblockDec_Free(p, alloc);
CSbDec *p = (CSbDec *)pp;
SbDec_Free(p);
alloc->Free(alloc, pp);
}
@@ -240,24 +241,32 @@ static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAl
static void SbState_Init(void *pp)
{
SubblockDec_Init((CSubblockDec *)pp);
SbDec_Init((CSbDec *)pp);
}
static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
{
ECoderStatus status;
SRes res = SubblockDec_Decode((CSubblockDec *)pp, dest, destLen, src, srcLen, finishMode, &status);
CSbDec *p = (CSbDec *)pp;
SRes res;
srcWasFinished = srcWasFinished;
*wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
p->dest = dest;
p->destLen = *destLen;
p->src = src;
p->srcLen = *srcLen;
p->finish = finishMode; /* change it */
res = SbDec_Decode((CSbDec *)pp);
*destLen -= p->destLen;
*srcLen -= p->srcLen;
*wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */
return res;
}
SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
{
CSubblockDec *decoder;
CSbDec *decoder;
p->p = 0;
decoder = alloc->Alloc(alloc, sizeof(CSubblockDec));
decoder = alloc->Alloc(alloc, sizeof(CSbDec));
if (decoder == 0)
return SZ_ERROR_MEM;
p->p = decoder;
@@ -265,7 +274,8 @@ SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
p->SetProps = SbState_SetProps;
p->Init = SbState_Init;
p->Code = SbState_Code;
SubblockDec_Construct(decoder);
SbDec_Construct(decoder);
SbDec_SetAlloc(decoder, alloc);
return SZ_OK;
}
#endif
@@ -369,7 +379,7 @@ SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId)
}
if (coderIndex == 0)
return SZ_ERROR_UNSUPPORTED;
return BraState_SetFromMethod(sc, methodId, p->alloc);
return BraState_SetFromMethod(sc, methodId, 0, p->alloc);
}
SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
@@ -587,13 +597,17 @@ SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
return SZ_OK;
}
SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc)
void XzUnpacker_Init(CXzUnpacker *p)
{
MixCoder_Construct(&p->decoder, alloc);
p->state = XZ_STATE_STREAM_HEADER;
p->pos = 0;
p->numStreams = 0;
return SZ_OK;
}
void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc)
{
MixCoder_Construct(&p->decoder, alloc);
XzUnpacker_Init(p);
}
void XzUnpacker_Free(CXzUnpacker *p)

311
C/XzEnc.c
View File

@@ -1,5 +1,5 @@
/* XzEnc.c -- Xz Encode
2009-06-04 : Igor Pavlov : Public domain */
2011-02-07 : Igor Pavlov : Public domain */
#include <stdlib.h>
#include <string.h>
@@ -9,7 +9,9 @@
#include "Bra.h"
#include "CpuArch.h"
#ifdef USE_SUBBLOCK
#include "SbEnc.h"
#include "Bcj3Enc.c"
#include "SbFind.c"
#include "SbEnc.c"
#endif
#include "XzEnc.h"
@@ -198,158 +200,147 @@ static size_t MyWrite(void *pp, const void *data, size_t size)
/* ---------- CSeqInFilter ---------- */
/*
typedef struct _IFilter
{
void *p;
void (*Free)(void *p, ISzAlloc *alloc);
SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);
void (*Init)(void *p);
size_t (*Filter)(void *p, Byte *data, SizeT destLen);
} IFilter;
#define FILT_BUF_SIZE (1 << 19)
#define FILTER_BUF_SIZE (1 << 20)
typedef struct
{
ISeqInStream p;
ISeqInStream *realStream;
UInt32 x86State;
UInt32 ip;
UInt64 processed;
CXzCheck check;
Byte buf[FILT_BUF_SIZE];
UInt32 bufferPos;
UInt32 convertedPosBegin;
UInt32 convertedPosEnd;
IFilter *filter;
IStateCoder StateCoder;
Byte *buf;
size_t curPos;
size_t endPos;
int srcWasFinished;
} CSeqInFilter;
static SRes SeqInFilter_Read(void *pp, void *data, size_t *size)
{
CSeqInFilter *p = (CSeqInFilter *)pp;
size_t remSize = *size;
size_t sizeOriginal = *size;
if (sizeOriginal == 0)
return S_OK;
*size = 0;
while (remSize > 0)
for (;;)
{
int i;
if (p->convertedPosBegin != p->convertedPosEnd)
if (!p->srcWasFinished && p->curPos == p->endPos)
{
UInt32 sizeTemp = p->convertedPosEnd - p->convertedPosBegin;
if (remSize < sizeTemp)
sizeTemp = (UInt32)remSize;
memmove(data, p->buf + p->convertedPosBegin, sizeTemp);
p->convertedPosBegin += sizeTemp;
data = (void *)((Byte *)data + sizeTemp);
remSize -= sizeTemp;
*size += sizeTemp;
break;
}
for (i = 0; p->convertedPosEnd + i < p->bufferPos; i++)
p->buf[i] = p->buf[i + p->convertedPosEnd];
p->bufferPos = i;
p->convertedPosBegin = p->convertedPosEnd = 0;
{
size_t processedSizeTemp = FILT_BUF_SIZE - p->bufferPos;
RINOK(p->realStream->Read(p->realStream, p->buf + p->bufferPos, &processedSizeTemp));
p->bufferPos = p->bufferPos + (UInt32)processedSizeTemp;
}
p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos);
if (p->convertedPosEnd == 0)
{
if (p->bufferPos == 0)
break;
else
{
p->convertedPosEnd = p->bufferPos;
continue;
}
}
if (p->convertedPosEnd > p->bufferPos)
{
for (; p->bufferPos < p->convertedPosEnd; p->bufferPos++)
p->buf[p->bufferPos] = 0;
p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos);
}
}
return SZ_OK;
}
*/
/*
typedef struct
{
ISeqInStream p;
ISeqInStream *realStream;
CMixCoder mixCoder;
Byte buf[FILT_BUF_SIZE];
UInt32 bufPos;
UInt32 bufSize;
} CMixCoderSeqInStream;
static SRes CMixCoderSeqInStream_Read(void *pp, void *data, size_t *size)
{
CMixCoderSeqInStream *p = (CMixCoderSeqInStream *)pp;
SRes res = SZ_OK;
size_t remSize = *size;
*size = 0;
while (remSize > 0)
{
if (p->bufPos == p->bufSize)
{
size_t curSize;
p->bufPos = p->bufSize = 0;
if (*size != 0)
break;
curSize = FILT_BUF_SIZE;
RINOK(p->realStream->Read(p->realStream, p->buf, &curSize));
p->bufSize = (UInt32)curSize;
p->curPos = 0;
p->endPos = FILTER_BUF_SIZE;
RINOK(p->realStream->Read(p->realStream, p->buf, &p->endPos));
if (p->endPos == 0)
p->srcWasFinished = 1;
}
{
SizeT destLen = remSize;
SizeT srcLen = p->bufSize - p->bufPos;
res = MixCoder_Code(&p->mixCoder, data, &destLen, p->buf + p->bufPos, &srcLen, 0);
data = (void *)((Byte *)data + destLen);
remSize -= destLen;
*size += destLen;
p->bufPos += srcLen;
}
}
SizeT srcLen = p->endPos - p->curPos;
int wasFinished;
SRes res;
*size = sizeOriginal;
res = p->StateCoder.Code(p->StateCoder.p, data, size, p->buf + p->curPos, &srcLen,
p->srcWasFinished, CODER_FINISH_ANY, &wasFinished);
p->curPos += srcLen;
if (*size != 0 || srcLen == 0 || res != 0)
return res;
}
}
}
*/
static void SeqInFilter_Construct(CSeqInFilter *p)
{
p->buf = NULL;
p->p.Read = SeqInFilter_Read;
}
static void SeqInFilter_Free(CSeqInFilter *p)
{
if (p->buf)
{
g_Alloc.Free(&g_Alloc, p->buf);
p->buf = NULL;
}
}
SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc);
static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props)
{
if (!p->buf)
{
p->buf = g_Alloc.Alloc(&g_Alloc, FILTER_BUF_SIZE);
if (!p->buf)
return SZ_ERROR_MEM;
}
p->curPos = p->endPos = 0;
p->srcWasFinished = 0;
RINOK(BraState_SetFromMethod(&p->StateCoder, props->id, 1, &g_Alloc));
RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, &g_Alloc));
p->StateCoder.Init(p->StateCoder.p);
return S_OK;
}
/* ---------- CSbEncInStream ---------- */
#ifdef USE_SUBBLOCK
typedef struct
{
ISeqInStream p;
CSubblockEnc sb;
UInt64 processed;
ISeqInStream *inStream;
CSbEnc enc;
} CSbEncInStream;
void SbEncInStream_Init(CSbEncInStream *p)
{
p->processed = 0;
SubblockEnc_Init(&p->sb);
}
static SRes SbEncInStream_Read(void *pp, void *data, size_t *size)
{
CSbEncInStream *p = (CSbEncInStream *)pp;
SRes res = SubblockEnc_Read(&p->sb, data, size);
p->processed += *size;
return res;
size_t sizeOriginal = *size;
if (sizeOriginal == 0)
return S_OK;
for (;;)
{
if (p->enc.needRead && !p->enc.readWasFinished)
{
size_t processed = p->enc.needReadSizeMax;
RINOK(p->inStream->Read(p->inStream, p->enc.buf + p->enc.readPos, &processed));
p->enc.readPos += processed;
if (processed == 0)
{
p->enc.readWasFinished = True;
p->enc.isFinalFinished = True;
}
p->enc.needRead = False;
}
*size = sizeOriginal;
RINOK(SbEnc_Read(&p->enc, data, size));
if (*size != 0 || !p->enc.needRead)
return S_OK;
}
}
void SbEncInStream_Construct(CSbEncInStream *p, ISzAlloc *alloc)
{
SbEnc_Construct(&p->enc, alloc);
p->p.Read = SbEncInStream_Read;
}
SRes SbEncInStream_Init(CSbEncInStream *p)
{
return SbEnc_Init(&p->enc);
}
void SbEncInStream_Free(CSbEncInStream *p)
{
SbEnc_Free(&p->enc);
}
#endif
typedef struct
{
/* CMixCoderSeqInStream inStream; */
CLzma2EncHandle lzma2;
#ifdef USE_SUBBLOCK
CSbEncInStream sb;
#endif
CSeqInFilter filter;
ISzAlloc *alloc;
ISzAlloc *bigAlloc;
} CLzma2WithFilters;
@@ -361,9 +352,9 @@ static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, IS
p->bigAlloc = bigAlloc;
p->lzma2 = NULL;
#ifdef USE_SUBBLOCK
p->sb.p.Read = SbEncInStream_Read;
SubblockEnc_Construct(&p->sb.sb, p->alloc);
SbEncInStream_Construct(&p->sb, alloc);
#endif
SeqInFilter_Construct(&p->filter);
}
static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p)
@@ -376,8 +367,9 @@ static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p)
static void Lzma2WithFilters_Free(CLzma2WithFilters *p)
{
SeqInFilter_Free(&p->filter);
#ifdef USE_SUBBLOCK
SubblockEnc_Free(&p->sb.sb);
SbEncInStream_Free(&p->sb);
#endif
if (p->lzma2)
{
@@ -386,17 +378,28 @@ static void Lzma2WithFilters_Free(CLzma2WithFilters *p)
}
}
static SRes Xz_Compress(CXzStream *xz,
CLzma2WithFilters *lzmaf,
ISeqOutStream *outStream,
ISeqInStream *inStream,
const CLzma2EncProps *lzma2Props,
Bool useSubblock,
ICompressProgress *progress)
void XzProps_Init(CXzProps *p)
{
xz->flags = XZ_CHECK_CRC32;
p->lzma2Props = 0;
p->filterProps = 0;
p->checkId = XZ_CHECK_CRC32;
}
RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, lzma2Props));
void XzFilterProps_Init(CXzFilterProps *p)
{
p->id = 0;
p->delta = 0;
p->ip= 0;
p->ipDefined = False;
}
static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
ISeqOutStream *outStream, ISeqInStream *inStream,
const CXzProps *props, ICompressProgress *progress)
{
xz->flags = (Byte)props->checkId;
RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, props->lzma2Props));
RINOK(Xz_WriteHeader(xz->flags, outStream));
{
@@ -404,15 +407,27 @@ static SRes Xz_Compress(CXzStream *xz,
CSeqSizeOutStream seqSizeOutStream;
CXzBlock block;
int filterIndex = 0;
CXzFilter *filter = NULL;
const CXzFilterProps *fp = props->filterProps;
XzBlock_ClearFlags(&block);
XzBlock_SetNumFilters(&block, 1 + (useSubblock ? 1 : 0));
XzBlock_SetNumFilters(&block, 1 + (fp ? 1 : 0));
if (useSubblock)
if (fp)
{
CXzFilter *f = &block.filters[filterIndex++];
f->id = XZ_ID_Subblock;
f->propsSize = 0;
filter = &block.filters[filterIndex++];
filter->id = fp->id;
filter->propsSize = 0;
if (fp->id == XZ_ID_Delta)
{
filter->props[0] = (Byte)(fp->delta - 1);
filter->propsSize = 1;
}
else if (fp->ipDefined)
{
SetUi32(filter->props, fp->ip);
filter->propsSize = 4;
}
}
{
@@ -432,20 +447,30 @@ static SRes Xz_Compress(CXzStream *xz,
checkInStream.realStream = inStream;
SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags));
#ifdef USE_SUBBLOCK
if (useSubblock)
if (fp)
{
lzmaf->sb.sb.inStream = &checkInStream.p;
SubblockEnc_Init(&lzmaf->sb.sb);
#ifdef USE_SUBBLOCK
if (fp->id == XZ_ID_Subblock)
{
lzmaf->sb.inStream = &checkInStream.p;
RINOK(SbEncInStream_Init(&lzmaf->sb));
}
else
#endif
{
lzmaf->filter.realStream = &checkInStream.p;
RINOK(SeqInFilter_Init(&lzmaf->filter, filter));
}
}
{
UInt64 packPos = seqSizeOutStream.processed;
SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p,
fp ?
#ifdef USE_SUBBLOCK
useSubblock ? &lzmaf->sb.p:
(fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p:
#endif
&lzmaf->filter.p:
&checkInStream.p,
progress);
RINOK(res);
@@ -467,8 +492,7 @@ static SRes Xz_Compress(CXzStream *xz,
}
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
const CLzma2EncProps *lzma2Props, Bool useSubblock,
ICompressProgress *progress)
const CXzProps *props, ICompressProgress *progress)
{
SRes res;
CXzStream xz;
@@ -477,8 +501,7 @@ SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
Lzma2WithFilters_Construct(&lzmaf, &g_Alloc, &g_BigAlloc);
res = Lzma2WithFilters_Create(&lzmaf);
if (res == SZ_OK)
res = Xz_Compress(&xz, &lzmaf, outStream, inStream,
lzma2Props, useSubblock, progress);
res = Xz_Compress(&xz, &lzmaf, outStream, inStream, props, progress);
Lzma2WithFilters_Free(&lzmaf);
Xz_Free(&xz, &g_Alloc);
return res;

View File

@@ -1,5 +1,5 @@
/* XzEnc.h -- Xz Encode
2009-04-15 : Igor Pavlov : Public domain */
2011-02-07 : Igor Pavlov : Public domain */
#ifndef __XZ_ENC_H
#define __XZ_ENC_H
@@ -8,18 +8,32 @@
#include "Xz.h"
#ifdef __cplusplus
extern "C" {
#endif
EXTERN_C_BEGIN
typedef struct
{
UInt32 id;
UInt32 delta;
UInt32 ip;
int ipDefined;
} CXzFilterProps;
void XzFilterProps_Init(CXzFilterProps *p);
typedef struct
{
const CLzma2EncProps *lzma2Props;
const CXzFilterProps *filterProps;
unsigned checkId;
} CXzProps;
void XzProps_Init(CXzProps *p);
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
const CLzma2EncProps *lzma2Props, Bool useSubblock,
ICompressProgress *progress);
const CXzProps *props, ICompressProgress *progress);
SRes Xz_EncodeEmpty(ISeqOutStream *outStream);
#ifdef __cplusplus
}
#endif
EXTERN_C_END
#endif

View File

@@ -1,5 +1,5 @@
/* XzIn.c - Xz input
2009-06-19 : Igor Pavlov : Public domain */
2011-02-01 : Igor Pavlov : Public domain */
#include <string.h>
@@ -152,29 +152,31 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOff
if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)
{
Int64 i = 0;
UInt32 total = 0;
*startOffset += XZ_STREAM_FOOTER_SIZE;
for (;;)
{
int j;
size_t processedSize;
size_t i;
#define TEMP_BUF_SIZE (1 << 10)
Byte tempBuf[TEMP_BUF_SIZE];
if (*startOffset < XZ_STREAM_FOOTER_SIZE || i > (1 << 16))
if (*startOffset < XZ_STREAM_FOOTER_SIZE || total > (1 << 16))
return SZ_ERROR_NO_ARCHIVE;
processedSize = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset;
i += processedSize;
*startOffset = -(Int64)processedSize;
i = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset;
total += (UInt32)i;
*startOffset = -(Int64)i;
RINOK(SeekFromCur(stream, startOffset));
RINOK(LookInStream_Read2(stream, tempBuf, processedSize, SZ_ERROR_NO_ARCHIVE));
for (j = (int)processedSize; j >= 0; j--)
if (tempBuf[j -1] != 0)
RINOK(LookInStream_Read2(stream, tempBuf, i, SZ_ERROR_NO_ARCHIVE));
for (; i != 0; i--)
if (tempBuf[i - 1] != 0)
break;
if (j != 0)
if (i != 0)
{
if ((j & 3) != 0)
if ((i & 3) != 0)
return SZ_ERROR_NO_ARCHIVE;
*startOffset += j;
*startOffset += i;
break;
}
}
if (*startOffset < XZ_STREAM_FOOTER_SIZE)
return SZ_ERROR_NO_ARCHIVE;
*startOffset -= XZ_STREAM_FOOTER_SIZE;
@@ -182,9 +184,6 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOff
RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE));
if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)
return SZ_ERROR_NO_ARCHIVE;
break;
}
}
}
p->flags = (CXzStreamFlags)GetBe16(buf + 8);

View File

@@ -3,19 +3,18 @@
#ifndef __7Z_COMPRESSION_MODE_H
#define __7Z_COMPRESSION_MODE_H
#include "../../../Common/MyString.h"
#include "../../../Windows/PropVariant.h"
#include "../../Common/MethodId.h"
#include "../../Common/MethodProps.h"
namespace NArchive {
namespace N7z {
struct CMethodFull: public CMethod
struct CMethodFull: public CProps
{
CMethodId Id;
UInt32 NumInStreams;
UInt32 NumOutStreams;
bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
};

View File

@@ -49,6 +49,15 @@ static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindIn
folder.PackStreams.Add(bindInfo.InStreams[i]);
}
static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)
{
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);
if (setCoderProperties)
return props.SetCoderProps(setCoderProperties, dataSizeReduce);
return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
}
HRESULT CEncoder::CreateMixerCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce)
@@ -86,8 +95,7 @@ HRESULT CEncoder::CreateMixerCoder(
}
#endif
RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon));
RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon));
/*
CMyComPtr<ICryptoResetSalt> resetSalt;

View File

@@ -24,25 +24,20 @@
using namespace NWindows;
extern UString ConvertMethodIdToString(UInt64 id);
namespace NArchive {
namespace N7z {
CHandler::CHandler()
{
_crcSize = 4;
#ifndef _NO_CRYPTO
_passwordIsDefined = false;
#endif
#ifdef EXTRACT_ONLY
_crcSize = 4;
#ifdef __7Z_SET_PROPERTIES
_numThreads = NSystem::GetNumberOfProcessors();
#endif
#else
Init();
#endif
}
@@ -70,7 +65,7 @@ STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
#else
STATPROPSTG kArcProps[] =
static const STATPROPSTG kArcProps[] =
{
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidSolid, VT_BOOL},
@@ -80,6 +75,25 @@ STATPROPSTG kArcProps[] =
{ NULL, kpidOffset, VT_UI8}
};
static inline wchar_t GetHex(Byte value)
{
return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
}
static UString ConvertMethodIdToString(UInt64 id)
{
wchar_t s[32];
int len = 32;
s[--len] = 0;
do
{
s[--len] = GetHex((Byte)id & 0xF); id >>= 4;
s[--len] = GetHex((Byte)id & 0xF); id >>= 4;
}
while (id != 0);
return s + len;
}
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
@@ -172,22 +186,18 @@ static UString GetStringForSizeValue(UInt32 value)
return result;
}
static const UInt64 k_Copy = 0x0;
static const UInt64 k_Delta = 3;
static const UInt64 k_LZMA2 = 0x21;
static const UInt64 k_LZMA = 0x030101;
static const UInt64 k_PPMD = 0x030401;
static wchar_t GetHex(Byte value)
{
return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
}
static inline void AddHexToString(UString &res, Byte value)
{
res += GetHex((Byte)(value >> 4));
res += GetHex((Byte)(value & 0xF));
}
static void AddProp32(UString &s, const wchar_t *name, UInt32 v)
{
s += name;
s += ConvertUInt32ToString(v);
}
#endif
bool CHandler::IsEncrypted(UInt32 index2) const
@@ -283,6 +293,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
{
UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
propsString = GetStringForSizeValue(dicSize);
UInt32 d = coder.Props[0];
UInt32 lc = d % 9;
d /= 9;
UInt32 pb = d / 5;
UInt32 lp = d % 5;
if (lc != 3) AddProp32(propsString, L":lc", lc);
if (lp != 0) AddProp32(propsString, L":lp", lp);
if (pb != 2) AddProp32(propsString, L":pb", pb);
}
else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1)
{

View File

@@ -18,6 +18,16 @@
namespace NArchive {
namespace N7z {
const UInt32 k_Copy = 0x0;
const UInt32 k_Delta = 3;
const UInt32 k_LZMA2 = 0x21;
const UInt32 k_LZMA = 0x030101;
const UInt32 k_PPMD = 0x030401;
const UInt32 k_BCJ = 0x03030103;
const UInt32 k_BCJ2 = 0x0303011B;
const UInt32 k_Deflate = 0x040108;
const UInt32 k_BZip2 = 0x040202;
#ifndef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
@@ -31,9 +41,52 @@ namespace N7z {
#endif
#ifndef EXTRACT_ONLY
class COutHandler: public CMultiMethodProps
{
HRESULT SetSolidFromString(const UString &s);
HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value);
public:
bool _removeSfxBlock;
UInt64 _numSolidFiles;
UInt64 _numSolidBytes;
bool _numSolidBytesDefined;
bool _solidExtension;
bool _compressHeaders;
bool _encryptHeadersSpecified;
bool _encryptHeaders;
bool WriteCTime;
bool WriteATime;
bool WriteMTime;
bool _volumeMode;
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
void InitSolid()
{
InitSolidFiles();
InitSolidSize();
_solidExtension = false;
_numSolidBytesDefined = false;
}
void InitProps();
COutHandler() { InitProps(); }
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
};
#endif
class CHandler:
#ifndef EXTRACT_ONLY
public NArchive::COutHandler,
public COutHandler,
#endif
public IInArchive,
#ifdef __7Z_SET_PROPERTIES
@@ -90,16 +143,16 @@ private:
CRecordVector<CBind> _binds;
HRESULT SetCompressionMethod(CCompressionMethodMode &method,
HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);
HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);
void AddDefaultMethod();
HRESULT SetMainMethod(CCompressionMethodMode &method,
CObjectVector<COneMethodInfo> &methodsInfo
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
);
HRESULT SetCompressionMethod(
CCompressionMethodMode &method,
CCompressionMethodMode &headerMethod);
#endif

View File

@@ -2,13 +2,9 @@
#include "StdAfx.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Common/ComTry.h"
#include "../../../Common/StringToInt.h"
#include "../../ICoder.h"
#include "../Common/ItemNameUtils.h"
#include "../Common/ParseProperties.h"
@@ -21,24 +17,19 @@ using namespace NWindows;
namespace NArchive {
namespace N7z {
static const wchar_t *kLZMAMethodName = L"LZMA";
static const wchar_t *kCopyMethod = L"Copy";
static const wchar_t *kDefaultMethodName = kLZMAMethodName;
static const wchar_t *k_LZMA_Name = L"LZMA";
static const wchar_t *kDefaultMethodName = k_LZMA_Name;
static const wchar_t *k_Copy_Name = L"Copy";
static const UInt32 kLzmaAlgorithmX5 = 1;
static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
static const UInt32 kDictionaryForHeaders =
static const wchar_t *k_MatchFinder_ForHeaders = L"BT2";
static const UInt32 k_NumFastBytes_ForHeaders = 273;
static const UInt32 k_Level_ForHeaders = 5;
static const UInt32 k_Dictionary_ForHeaders =
#ifdef UNDER_CE
1 << 18
1 << 18;
#else
1 << 20
1 << 20;
#endif
;
static const UInt32 kNumFastBytesForHeaders = 273;
static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5;
static inline bool IsCopyMethod(const UString &methodName)
{ return (methodName.CompareNoCase(kCopyMethod) == 0); }
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
{
@@ -46,123 +37,105 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
return S_OK;
}
HRESULT CHandler::SetCompressionMethod(
CCompressionMethodMode &methodMode,
CCompressionMethodMode &headerMethod)
HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m)
{
HRESULT res = SetCompressionMethod(methodMode, _methods
#ifndef _7ZIP_ST
, _numThreads
#endif
);
RINOK(res);
methodMode.Binds = _binds;
if (_compressHeaders)
{
// headerMethod.Methods.Add(methodMode.Methods.Back());
CObjectVector<COneMethodInfo> headerMethodInfoVector;
COneMethodInfo oneMethodInfo;
oneMethodInfo.MethodName = kLZMAMethodName;
{
CProp prop;
prop.Id = NCoderPropID::kMatchFinder;
prop.Value = kLzmaMatchFinderForHeaders;
oneMethodInfo.Props.Add(prop);
}
{
CProp prop;
prop.Id = NCoderPropID::kAlgorithm;
prop.Value = kAlgorithmForHeaders;
oneMethodInfo.Props.Add(prop);
}
{
CProp prop;
prop.Id = NCoderPropID::kNumFastBytes;
prop.Value = (UInt32)kNumFastBytesForHeaders;
oneMethodInfo.Props.Add(prop);
}
{
CProp prop;
prop.Id = NCoderPropID::kDictionarySize;
prop.Value = (UInt32)kDictionaryForHeaders;
oneMethodInfo.Props.Add(prop);
}
headerMethodInfoVector.Add(oneMethodInfo);
HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector
#ifndef _7ZIP_ST
, 1
#endif
);
RINOK(res);
}
if (!FindMethod(
EXTERNAL_CODECS_VARS
m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams))
return E_INVALIDARG;
(CProps &)dest = (CProps &)m;
return S_OK;
}
HRESULT CHandler::SetCompressionMethod(
HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
{
if (!_compressHeaders)
return S_OK;
COneMethodInfo m;
m.MethodName = k_LZMA_Name;
m.AddPropString(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);
m.AddProp32(NCoderPropID::kLevel, k_Level_ForHeaders);
m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders);
m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders);
m.AddNumThreadsProp(1);
CMethodFull methodFull;
RINOK(PropsMethod_To_FullMethod(methodFull, m));
headerMethod.Methods.Add(methodFull);
return S_OK;
}
void CHandler::AddDefaultMethod()
{
for (int i = 0; i < _methods.Size(); i++)
{
UString &methodName = _methods[0].MethodName;
if (methodName.IsEmpty())
methodName = kDefaultMethodName;
}
if (_methods.IsEmpty())
{
COneMethodInfo m;
m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
_methods.Add(m);
}
}
HRESULT CHandler::SetMainMethod(
CCompressionMethodMode &methodMode,
CObjectVector<COneMethodInfo> &methodsInfo
CObjectVector<COneMethodInfo> &methods
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
)
{
UInt32 level = _level;
AddDefaultMethod();
if (methodsInfo.IsEmpty())
{
COneMethodInfo oneMethodInfo;
oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName);
methodsInfo.Add(oneMethodInfo);
}
const UInt64 kSolidBytes_Min = (1 << 24);
const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1;
bool needSolid = false;
for(int i = 0; i < methodsInfo.Size(); i++)
for (int i = 0; i < methods.Size(); i++)
{
COneMethodInfo &oneMethodInfo = methodsInfo[i];
SetCompressionMethod2(oneMethodInfo
COneMethodInfo &oneMethodInfo = methods[i];
SetGlobalLevelAndThreads(oneMethodInfo
#ifndef _7ZIP_ST
, numThreads
#endif
);
if (!IsCopyMethod(oneMethodInfo.MethodName))
needSolid = true;
CMethodFull methodFull;
if (!FindMethod(
EXTERNAL_CODECS_VARS
oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams))
return E_INVALIDARG;
methodFull.Props = oneMethodInfo.Props;
RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
methodMode.Methods.Add(methodFull);
if (!_numSolidBytesDefined)
if (methodFull.Id != k_Copy)
needSolid = true;
if (_numSolidBytesDefined)
continue;
UInt32 dicSize;
switch (methodFull.Id)
{
for (int j = 0; j < methodFull.Props.Size(); j++)
{
const CProp &prop = methodFull.Props[j];
if ((prop.Id == NCoderPropID::kDictionarySize ||
prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4)
{
_numSolidBytes = ((UInt64)prop.Value.ulVal) << 7;
const UInt64 kMinSize = (1 << 24);
if (_numSolidBytes < kMinSize)
_numSolidBytes = kMinSize;
case k_LZMA:
case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break;
case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break;
case k_Deflate: dicSize = (UInt32)1 << 15; break;
case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;
default: continue;
}
_numSolidBytes = (UInt64)dicSize << 7;
if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min;
if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max;
_numSolidBytesDefined = true;
break;
}
}
}
}
if (!needSolid && !_numSolidBytesDefined)
{
_numSolidBytesDefined = true;
if (!_numSolidBytesDefined)
if (needSolid)
_numSolidBytes = kSolidBytes_Max;
else
_numSolidBytes = 0;
}
_numSolidBytesDefined = true;
return S_OK;
}
@@ -326,7 +299,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
CCompressionMethodMode methodMode, headerMethod;
RINOK(SetCompressionMethod(methodMode, headerMethod));
HRESULT res = SetMainMethod(methodMode, _methods
#ifndef _7ZIP_ST
, _numThreads
#endif
);
RINOK(res);
methodMode.Binds = _binds;
RINOK(SetHeaderMethod(headerMethod));
#ifndef _7ZIP_ST
methodMode.NumThreads = _numThreads;
headerMethod.NumThreads = 1;
@@ -373,8 +355,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CUpdateOptions options;
options.Method = &methodMode;
options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0;
options.UseFilters = _level != 0 && _autoFilter;
options.MaxFilter = _level >= 8;
int level = GetLevel();
options.UseFilters = level != 0 && _autoFilter;
options.MaxFilter = level >= 8;
options.HeaderOptions.CompressMainHeader = compressMainHeader;
options.HeaderOptions.WriteCTime = WriteCTime;
@@ -393,7 +376,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CMyComPtr<ICryptoGetTextPassword> getPassword;
updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword);
HRESULT res = Update(
res = Update(
EXTERNAL_CODECS_VARS
#ifdef _7Z_VOL
volume ? volume->Stream: 0,
@@ -437,25 +420,138 @@ static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream
return S_OK;
}
static HRESULT GetBindInfo(UString &srcString, CBind &bind)
void COutHandler::InitProps()
{
RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream));
if (srcString[0] != ':')
CMultiMethodProps::Init();
_removeSfxBlock = false;
_compressHeaders = true;
_encryptHeadersSpecified = false;
_encryptHeaders = false;
WriteCTime = false;
WriteATime = false;
WriteMTime = true;
_volumeMode = false;
InitSolid();
}
HRESULT COutHandler::SetSolidFromString(const UString &s)
{
UString s2 = s;
s2.MakeUpper();
for (int i = 0; i < s2.Length();)
{
const wchar_t *start = ((const wchar_t *)s2) + i;
const wchar_t *end;
UInt64 v = ConvertStringToUInt64(start, &end);
if (start == end)
{
if (s2[i++] != 'E')
return E_INVALIDARG;
srcString.Delete(0);
RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream));
if (!srcString.IsEmpty())
_solidExtension = true;
continue;
}
i += (int)(end - start);
if (i == s2.Length())
return E_INVALIDARG;
wchar_t c = s2[i++];
if (c == 'F')
{
if (v < 1)
v = 1;
_numSolidFiles = v;
}
else
{
unsigned numBits;
switch (c)
{
case 'B': numBits = 0; break;
case 'K': numBits = 10; break;
case 'M': numBits = 20; break;
case 'G': numBits = 30; break;
default: return E_INVALIDARG;
}
_numSolidBytes = (v << numBits);
_numSolidBytesDefined = true;
}
}
return S_OK;
}
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value)
{
bool isSolid;
switch (value.vt)
{
case VT_EMPTY: isSolid = true; break;
case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;
case VT_BSTR:
if (StringToBool(value.bstrVal, isSolid))
break;
return SetSolidFromString(value.bstrVal);
default: return E_INVALIDARG;
}
if (isSolid)
InitSolid();
else
_numSolidFiles = 1;
return S_OK;
}
HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
{
UString name = nameSpec;
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
if (name[0] == L'S')
{
name.Delete(0);
if (name.IsEmpty())
return SetSolidFromPROPVARIANT(value);
if (value.vt != VT_EMPTY)
return E_INVALIDARG;
return SetSolidFromString(name);
}
UInt32 number;
int index = ParseStringToUInt32(name, number);
UString realName = name.Mid(index);
if (index == 0)
{
if (name.CompareNoCase(L"RSFX") == 0) return PROPVARIANT_to_bool(value, _removeSfxBlock);
if (name.CompareNoCase(L"HC") == 0) return PROPVARIANT_to_bool(value, _compressHeaders);
if (name.CompareNoCase(L"HCF") == 0)
{
bool compressHeadersFull = true;
RINOK(PROPVARIANT_to_bool(value, compressHeadersFull));
return compressHeadersFull ? S_OK: E_INVALIDARG;
}
if (name.CompareNoCase(L"HE") == 0)
{
RINOK(PROPVARIANT_to_bool(value, _encryptHeaders));
_encryptHeadersSpecified = true;
return S_OK;
}
if (name.CompareNoCase(L"TC") == 0) return PROPVARIANT_to_bool(value, WriteCTime);
if (name.CompareNoCase(L"TA") == 0) return PROPVARIANT_to_bool(value, WriteATime);
if (name.CompareNoCase(L"TM") == 0) return PROPVARIANT_to_bool(value, WriteMTime);
if (name.CompareNoCase(L"V") == 0) return PROPVARIANT_to_bool(value, _volumeMode);
}
return CMultiMethodProps::SetProperty(name, value);
}
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
COM_TRY_BEGIN
_binds.Clear();
BeforeSetProperty();
InitProps();
for (int i = 0; i < numProperties; i++)
for (int i = 0; i < numProps; i++)
{
UString name = names[i];
name.MakeUpper();
@@ -466,9 +562,17 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (name[0] == 'B')
{
if (value.vt != VT_EMPTY)
return E_INVALIDARG;
name.Delete(0);
CBind bind;
RINOK(GetBindInfo(name, bind));
RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream));
if (name[0] != ':')
return E_INVALIDARG;
name.Delete(0);
RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream));
if (!name.IsEmpty())
return E_INVALIDARG;
_binds.Add(bind);
continue;
}
@@ -476,6 +580,47 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
RINOK(SetProperty(name, value));
}
int numEmptyMethods = GetNumEmptyMethods();
if (numEmptyMethods > 0)
{
int k;
for (k = 0; k < _binds.Size(); k++)
{
const CBind &bind = _binds[k];
if (bind.InCoder < (UInt32)numEmptyMethods ||
bind.OutCoder < (UInt32)numEmptyMethods)
return E_INVALIDARG;
}
for (k = 0; k < _binds.Size(); k++)
{
CBind &bind = _binds[k];
bind.InCoder -= (UInt32)numEmptyMethods;
bind.OutCoder -= (UInt32)numEmptyMethods;
}
_methods.Delete(0, numEmptyMethods);
}
AddDefaultMethod();
if (!_filterMethod.MethodName.IsEmpty())
{
for (int k = 0; k < _binds.Size(); k++)
{
CBind &bind = _binds[k];
bind.InCoder++;
bind.OutCoder++;
}
_methods.Insert(0, _filterMethod);
}
for (int k = 0; k < _binds.Size(); k++)
{
const CBind &bind = _binds[k];
if (bind.InCoder >= (UInt32)_methods.Size() ||
bind.OutCoder >= (UInt32)_methods.Size())
return E_INVALIDARG;
}
return S_OK;
COM_TRY_END
}

View File

@@ -317,7 +317,6 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
const UInt32 kBufferSize = (1 << 16);
byteBuffer.SetCapacity(kBufferSize);
Byte *buffer = byteBuffer;
UInt32 numPrevBytes = kHeaderSize;
memcpy(buffer, _header, kHeaderSize);
UInt64 curTestPos = _arhiveBeginStreamPosition;
for (;;)
@@ -325,21 +324,14 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
if (searchHeaderSizeLimit != NULL)
if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit)
break;
do
{
UInt32 numReadBytes = kBufferSize - numPrevBytes;
UInt32 processedSize;
RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize));
numPrevBytes += processedSize;
RINOK(stream->Read(buffer + kHeaderSize, kBufferSize - kHeaderSize, &processedSize));
if (processedSize == 0)
return S_FALSE;
}
while (numPrevBytes <= kHeaderSize);
UInt32 numTests = numPrevBytes - kHeaderSize;
for (UInt32 pos = 0; pos < numTests; pos++)
for (UInt32 pos = 1; pos <= processedSize; pos++)
{
for (; buffer[pos] != '7' && pos < numTests; pos++);
if (pos == numTests)
for (; buffer[pos] != '7' && pos <= processedSize; pos++);
if (pos > processedSize)
break;
if (TestSignature(buffer + pos))
{
@@ -349,9 +341,8 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL);
}
}
curTestPos += numTests;
numPrevBytes -= numTests;
memmove(buffer, buffer + numTests, numPrevBytes);
curTestPos += processedSize;
memmove(buffer, buffer + processedSize, kHeaderSize);
}
return S_FALSE;
}
@@ -362,6 +353,8 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
HeadersSize = 0;
Close();
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition))
RINOK(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition))
RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL))
RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit));
_stream = stream;
return S_OK;
@@ -1194,12 +1187,14 @@ HRESULT CInArchive::ReadDatabase2(
if (nextHeaderSize == 0)
return S_OK;
if (nextHeaderSize > (UInt64)0xFFFFFFFF)
if (nextHeaderSize > (UInt64)(UInt32)0xFFFFFFFF)
return S_FALSE;
if ((Int64)nextHeaderOffset < 0)
return S_FALSE;
if (db.ArchiveInfo.StartPositionAfterHeader + nextHeaderOffset > _fileEndPosition)
return S_FALSE;
RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));
CByteBuffer buffer2;

View File

@@ -133,6 +133,7 @@ class CInArchive
CInByte2 *_inByteBack;
UInt64 _arhiveBeginStreamPosition;
UInt64 _fileEndPosition;
Byte _header[kHeaderSize];

View File

@@ -24,15 +24,6 @@
namespace NArchive {
namespace N7z {
static const UInt64 k_LZMA = 0x030101;
static const UInt64 k_BCJ = 0x03030103;
static const UInt64 k_BCJ2 = 0x0303011B;
static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2";
static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20;
static const UInt32 kAlgorithmForBCJ2_LZMA = 1;
static const UInt32 kNumFastBytesForBCJ2_LZMA = 64;
#ifdef MY_CPU_X86_OR_AMD64
#define USE_86_FILTER
#endif
@@ -339,90 +330,74 @@ static bool IsExeExt(const UString &ext)
return false;
}
#ifdef USE_86_FILTER
static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult)
static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &m)
{
methodResult.Id = methodID;
methodResult.NumInStreams = numInStreams;
methodResult.NumOutStreams = 1;
m.Id = methodID;
m.NumInStreams = numInStreams;
m.NumOutStreams = 1;
}
static void MakeExeMethod(const CCompressionMethodMode &method,
bool bcj2Filter, CCompressionMethodMode &exeMethod)
static void AddBcj2Methods(CCompressionMethodMode &mode)
{
exeMethod = method;
if (bcj2Filter)
{
CMethodFull methodFull;
GetMethodFull(k_BCJ2, 4, methodFull);
exeMethod.Methods.Insert(0, methodFull);
GetMethodFull(k_LZMA, 1, methodFull);
{
CProp prop;
prop.Id = NCoderPropID::kAlgorithm;
prop.Value = kAlgorithmForBCJ2_LZMA;
methodFull.Props.Add(prop);
}
{
CProp prop;
prop.Id = NCoderPropID::kMatchFinder;
prop.Value = kMatchFinderForBCJ2_LZMA;
methodFull.Props.Add(prop);
}
{
CProp prop;
prop.Id = NCoderPropID::kDictionarySize;
prop.Value = kDictionaryForBCJ2_LZMA;
methodFull.Props.Add(prop);
}
{
CProp prop;
prop.Id = NCoderPropID::kNumFastBytes;
prop.Value = kNumFastBytesForBCJ2_LZMA;
methodFull.Props.Add(prop);
}
{
CProp prop;
prop.Id = NCoderPropID::kNumThreads;
prop.Value = (UInt32)1;
methodFull.Props.Add(prop);
}
CMethodFull m;
GetMethodFull(k_LZMA, 1, m);
m.AddProp32(NCoderPropID::kDictionarySize, 1 << 20);
m.AddProp32(NCoderPropID::kNumFastBytes, 128);
m.AddProp32(NCoderPropID::kNumThreads, 1);
m.AddProp32(NCoderPropID::kLitPosBits, 2);
m.AddProp32(NCoderPropID::kLitContextBits, 0);
// m.AddPropString(NCoderPropID::kMatchFinder, L"BT2");
mode.Methods.Add(m);
mode.Methods.Add(m);
exeMethod.Methods.Add(methodFull);
exeMethod.Methods.Add(methodFull);
CBind bind;
bind.OutCoder = 0;
bind.InStream = 0;
bind.InCoder = 1; bind.OutStream = 0; mode.Binds.Add(bind);
bind.InCoder = 2; bind.OutStream = 1; mode.Binds.Add(bind);
bind.InCoder = 3; bind.OutStream = 2; mode.Binds.Add(bind);
}
bind.InCoder = 1;
bind.OutStream = 0;
exeMethod.Binds.Add(bind);
bind.InCoder = 2;
bind.OutStream = 1;
exeMethod.Binds.Add(bind);
bind.InCoder = 3;
bind.OutStream = 2;
exeMethod.Binds.Add(bind);
static void MakeExeMethod(CCompressionMethodMode &mode,
bool useFilters, bool addFilter, bool bcj2Filter)
{
if (!mode.Binds.IsEmpty() || !useFilters || mode.Methods.Size() > 2)
return;
if (mode.Methods.Size() == 2)
{
if (mode.Methods[0].Id == k_BCJ2)
AddBcj2Methods(mode);
return;
}
if (!addFilter)
return;
bcj2Filter = bcj2Filter;
#ifdef USE_86_FILTER
if (bcj2Filter)
{
CMethodFull m;
GetMethodFull(k_BCJ2, 4, m);
mode.Methods.Insert(0, m);
AddBcj2Methods(mode);
}
else
{
CMethodFull methodFull;
GetMethodFull(k_BCJ, 1, methodFull);
exeMethod.Methods.Insert(0, methodFull);
CMethodFull m;
GetMethodFull(k_BCJ, 1, m);
mode.Methods.Insert(0, m);
CBind bind;
bind.OutCoder = 0;
bind.InStream = 0;
bind.InCoder = 1;
bind.OutStream = 0;
exeMethod.Binds.Add(bind);
mode.Binds.Add(bind);
}
#endif
}
#endif
static void FromUpdateItemToFileItem(const CUpdateItem &ui,
CFileItem &file, CFileItem2 &file2)
@@ -601,6 +576,7 @@ public:
Fos = FosSpec;
Result = E_FAIL;
}
~CThreadDecoder() { CVirtThread::WaitThreadFinish(); }
virtual void Execute();
};
@@ -669,9 +645,7 @@ STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password)
static const int kNumGroupsMax = 4;
#ifdef USE_86_FILTER
static bool Is86Group(int group) { return (group & 1) != 0; }
#endif
static bool IsEncryptedGroup(int group) { return (group & 2) != 0; }
static int GetGroupIndex(bool encrypted, int bcjFiltered)
{ return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); }
@@ -789,16 +763,15 @@ HRESULT Update(
if (inSizeForReduce2 > inSizeForReduce)
inSizeForReduce = inSizeForReduce2;
const UInt32 kMinReduceSize = (1 << 16);
if (inSizeForReduce < kMinReduceSize)
inSizeForReduce = kMinReduceSize;
RINOK(updateCallback->SetTotal(complexity));
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(updateCallback, true);
CStreamBinder sb;
RINOK(sb.CreateEvents());
CThreadDecoder threadDecoder;
if (!folderRefs.IsEmpty())
{
@@ -870,13 +843,8 @@ HRESULT Update(
{
const CSolidGroup &group = groups[groupIndex];
CCompressionMethodMode method;
#ifdef USE_86_FILTER
if (Is86Group(groupIndex))
MakeExeMethod(*options.Method, options.MaxFilter, method);
else
#endif
method = *options.Method;
CCompressionMethodMode method = *options.Method;
MakeExeMethod(method, options.UseFilters, Is86Group(groupIndex), options.MaxFilter);
if (IsEncryptedGroup(groupIndex))
{
@@ -923,11 +891,6 @@ HRESULT Update(
}
else
{
CStreamBinder sb;
RINOK(sb.CreateEvents());
CMyComPtr<ISequentialOutStream> sbOutStream;
CMyComPtr<ISequentialInStream> sbInStream;
sb.CreateStreams(&sbInStream, &sbOutStream);
CBoolVector extractStatuses;
CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
@@ -946,8 +909,16 @@ HRESULT Update(
extractStatuses.Add(needExtract);
}
int startPackIndex = newDatabase.PackSizes.Size();
CFolder newFolder;
{
CMyComPtr<ISequentialInStream> sbInStream;
{
CMyComPtr<ISequentialOutStream> sbOutStream;
sb.CreateStreams(&sbInStream, &sbOutStream);
sb.ReInit();
RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream));
sbOutStream.Release();
}
threadDecoder.InStream = inStream;
threadDecoder.Folder = &db->Folders[folderIndex];
@@ -956,14 +927,13 @@ HRESULT Update(
threadDecoder.Start();
int startPackIndex = newDatabase.PackSizes.Size();
CFolder newFolder;
RINOK(encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
sbInStream, NULL, &inSizeForReduce, newFolder,
archive.SeqStream, newDatabase.PackSizes, progress));
threadDecoder.WaitFinish();
threadDecoder.WaitExecuteFinish();
}
RINOK(threadDecoder.Result);
@@ -1134,6 +1104,8 @@ HRESULT Update(
if (folderRefIndex != folderRefs.Size())
return E_FAIL;
RINOK(lps->SetCur());
/*
folderRefs.ClearAndFree();
fileIndexToUpdateIndexMap.ClearAndFree();

View File

@@ -4,13 +4,6 @@
#include "Common/ComTry.h"
#include "Windows/PropVariant.h"
#ifndef _7ZIP_ST
#include "../../Windows/System.h"
#endif
#include "../Common/CreateCoder.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
@@ -20,21 +13,13 @@
#include "../Compress/CopyCoder.h"
#include "Common/DummyOutStream.h"
#include "Common/ParseProperties.h"
#include "Common/HandlerOut.h"
using namespace NWindows;
namespace NArchive {
namespace NBz2 {
static const UInt32 kNumPassesX1 = 1;
static const UInt32 kNumPassesX7 = 2;
static const UInt32 kNumPassesX9 = 7;
static const UInt32 kDicSizeX1 = 100000;
static const UInt32 kDicSizeX3 = 500000;
static const UInt32 kDicSizeX5 = 900000;
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
@@ -48,22 +33,7 @@ class CHandler:
UInt64 _startPosition;
bool _packSizeDefined;
UInt32 _level;
UInt32 _dicSize;
UInt32 _numPasses;
#ifndef _7ZIP_ST
UInt32 _numThreads;
#endif
void InitMethodProperties()
{
_level = 5;
_dicSize =
_numPasses = 0xFFFFFFFF;
#ifndef _7ZIP_ST
_numThreads = NWindows::NSystem::GetNumberOfProcessors();;
#endif
}
CSingleMethodProps _props;
public:
MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
@@ -73,10 +43,10 @@ public:
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
CHandler() { InitMethodProperties(); }
CHandler() { }
};
STATPROPSTG kProps[] =
static const STATPROPSTG kProps[] =
{
{ NULL, kpidPackSize, VT_UI8}
};
@@ -87,7 +57,7 @@ IMP_IInArchive_ArcProps_NO_Table
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch(propID)
switch (propID)
{
case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
}
@@ -104,7 +74,7 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant prop;
switch(propID)
switch (propID)
{
case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
}
@@ -188,7 +158,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
decoderSpec->SetInStream(_seqStream);
#ifndef _7ZIP_ST
RINOK(decoderSpec->SetNumberOfThreads(_numThreads));
RINOK(decoderSpec->SetNumberOfThreads(_props._numThreads));
#endif
CDummyOutStream *outStreamSpec = new CDummyOutStream;
@@ -246,50 +216,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
static HRESULT UpdateArchive(
UInt64 unpackSize,
ISequentialOutStream *outStream,
int indexInClient,
UInt32 dictionary,
UInt32 numPasses,
#ifndef _7ZIP_ST
UInt32 numThreads,
#endif
const CProps &props,
IArchiveUpdateCallback *updateCallback)
{
RINOK(updateCallback->SetTotal(unpackSize));
UInt64 complexity = 0;
RINOK(updateCallback->SetCompleted(&complexity));
CMyComPtr<ISequentialInStream> fileInStream;
RINOK(updateCallback->GetStream(indexInClient, &fileInStream));
RINOK(updateCallback->GetStream(0, &fileInStream));
CLocalProgress *localProgressSpec = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
localProgressSpec->Init(updateCallback, true);
NCompress::NBZip2::CEncoder *encoderSpec = new NCompress::NBZip2::CEncoder;
CMyComPtr<ICompressCoder> encoder = encoderSpec;
{
NWindows::NCOM::CPropVariant properties[] =
{
dictionary,
numPasses
#ifndef _7ZIP_ST
, numThreads
#endif
};
PROPID propIDs[] =
{
NCoderPropID::kDictionarySize,
NCoderPropID::kNumPasses
#ifndef _7ZIP_ST
, NCoderPropID::kNumThreads
#endif
};
RINOK(encoderSpec->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0])));
}
RINOK(props.SetCoderProps(encoderSpec, NULL));
RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
}
@@ -336,25 +275,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
}
UInt32 dicSize = _dicSize;
if (dicSize == 0xFFFFFFFF)
dicSize = (_level >= 5 ? kDicSizeX5 :
(_level >= 3 ? kDicSizeX3 :
kDicSizeX1));
UInt32 numPasses = _numPasses;
if (numPasses == 0xFFFFFFFF)
numPasses = (_level >= 9 ? kNumPassesX9 :
(_level >= 7 ? kNumPassesX7 :
kNumPassesX1));
return UpdateArchive(
size, outStream, 0, dicSize, numPasses,
#ifndef _7ZIP_ST
_numThreads,
#endif
updateCallback);
return UpdateArchive(size, outStream, _props, updateCallback);
}
if (indexInArchive != 0)
return E_INVALIDARG;
@@ -365,47 +286,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
InitMethodProperties();
#ifndef _7ZIP_ST
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
_numThreads = numProcessors;
#endif
for (int i = 0; i < numProps; i++)
{
UString name = names[i];
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
const PROPVARIANT &prop = values[i];
if (name[0] == L'X')
{
UInt32 level = 9;
RINOK(ParsePropValue(name.Mid(1), prop, level));
_level = level;
}
else if (name[0] == L'D')
{
UInt32 dicSize = kDicSizeX5;
RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));
_dicSize = dicSize;
}
else if (name.Left(4) == L"PASS")
{
UInt32 num = kNumPassesX9;
RINOK(ParsePropValue(name.Mid(4), prop, num));
_numPasses = num;
}
else if (name.Left(2) == L"MT")
{
#ifndef _7ZIP_ST
RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads));
#endif
}
else
return E_INVALIDARG;
}
return S_OK;
return _props.SetProperties(names, values, numProps);
}
static IInArchive *CreateArc() { return new CHandler; }

View File

@@ -4,9 +4,7 @@
#include "../../../../C/Alloc.h"
#include "Common/Buffer.h"
#include "Common/ComTry.h"
#include "Common/Defs.h"
#include "Common/IntToString.h"
#include "Common/StringConvert.h"
#include "Common/UTFConvert.h"
@@ -654,7 +652,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode)
numItems = m_Database.Items.Size();
if(numItems == 0)
if (numItems == 0)
return S_OK;
bool testMode = (testModeSpec != 0);
UInt64 totalUnPacked = 0;
@@ -780,12 +778,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
curUnpack, extractCallback, testMode);
cabBlockInStreamSpec->MsZip = false;
HRESULT res = S_OK;
switch(folder.GetCompressionMethod())
{
case NHeader::NCompressionMethodMajor::kNone:
break;
case NHeader::NCompressionMethodMajor::kMSZip:
if(deflateDecoderSpec == NULL)
if (!deflateDecoder)
{
deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder;
deflateDecoder = deflateDecoderSpec;
@@ -793,33 +792,35 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
cabBlockInStreamSpec->MsZip = true;
break;
case NHeader::NCompressionMethodMajor::kLZX:
if(lzxDecoderSpec == NULL)
if (!lzxDecoder)
{
lzxDecoderSpec = new NCompress::NLzx::CDecoder;
lzxDecoder = lzxDecoderSpec;
}
RINOK(lzxDecoderSpec->SetParams(folder.CompressionTypeMinor));
res = lzxDecoderSpec->SetParams(folder.CompressionTypeMinor);
break;
case NHeader::NCompressionMethodMajor::kQuantum:
if(quantumDecoderSpec == NULL)
if (!quantumDecoder)
{
quantumDecoderSpec = new NCompress::NQuantum::CDecoder;
quantumDecoder = quantumDecoderSpec;
}
quantumDecoderSpec->SetParams(folder.CompressionTypeMinor);
res = quantumDecoderSpec->SetParams(folder.CompressionTypeMinor);
break;
default:
res = E_INVALIDARG;
break;
}
if (res == E_INVALIDARG)
{
RINOK(cabFolderOutStream->Unsupported());
totalUnPacked += curUnpack;
continue;
}
}
RINOK(res);
cabBlockInStreamSpec->InitForNewFolder();
HRESULT res = S_OK;
{
int volIndex = mvItem.VolumeIndex;
int locFolderIndex = item.GetFolderIndex(db.Folders.Size());

View File

@@ -39,7 +39,7 @@ struct CItem
{
if (Name.Length() == 0)
return false;
return (Name[Name.Length() - 1] == '/');
return (Name.Back() == '/');
}
};

View File

@@ -214,7 +214,7 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
for (i = 0; i < _coders.Size(); i++)
if (i != _progressCoderIndex)
_coders[i].WaitFinish();
_coders[i].WaitExecuteFinish();
RINOK(ReturnIfError(E_ABORT));
RINOK(ReturnIfError(E_OUTOFMEMORY));

View File

@@ -19,6 +19,7 @@ struct CCoder2: public CCoderInfo2, public CVirtThread
CRecordVector<ISequentialOutStream*> OutStreamPointers;
CCoder2(UInt32 numInStreams, UInt32 numOutStreams);
~CCoder2() { CVirtThread::WaitThreadFinish(); }
void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
virtual void Execute();
void Code(ICompressProgressInfo *progress);

View File

@@ -4,7 +4,7 @@
#include "CoderMixer2ST.h"
namespace NCoderMixer2 {
namespace NCoderMixer {
CCoderMixer2ST::CCoderMixer2ST() {}
@@ -42,7 +42,7 @@ HRESULT CCoderMixer2ST::GetInStream(
{
CMyComPtr<ISequentialInStream> seqInStream;
int i;
for(i = 0; i < _bindInfo.InStreams.Size(); i++)
for (i = 0; i < _bindInfo.InStreams.Size(); i++)
if (_bindInfo.InStreams[i] == streamIndex)
{
seqInStream = inStreams[i];
@@ -57,7 +57,7 @@ HRESULT CCoderMixer2ST::GetInStream(
_bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex,
coderIndex, coderStreamIndex);
CCoderInfo &coder = _coders[coderIndex];
CCoderInfo2 &coder = _coders[coderIndex];
if (!coder.Coder)
return E_NOTIMPL;
coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream);
@@ -91,7 +91,7 @@ HRESULT CCoderMixer2ST::GetOutStream(
{
CMyComPtr<ISequentialOutStream> seqOutStream;
int i;
for(i = 0; i < _bindInfo.OutStreams.Size(); i++)
for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
if (_bindInfo.OutStreams[i] == streamIndex)
{
seqOutStream = outStreams[i];
@@ -106,7 +106,7 @@ HRESULT CCoderMixer2ST::GetOutStream(
_bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex,
coderIndex, coderStreamIndex);
CCoderInfo &coder = _coders[coderIndex];
CCoderInfo2 &coder = _coders[coderIndex];
if (!coder.Coder)
return E_NOTIMPL;
coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream);
@@ -169,7 +169,7 @@ STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams,
// _mainCoderIndex = 0;
// _mainCoderIndex = _coders.Size() - 1;
CCoderInfo &mainCoder = _coders[_mainCoderIndex];
CCoderInfo2 &mainCoder = _coders[_mainCoderIndex];
CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
@@ -198,7 +198,7 @@ STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams,
{
if (i == _mainCoderIndex)
continue;
CCoderInfo &coder = _coders[i];
CCoderInfo2 &coder = _coders[i];
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
if (setOutStreamSize)

View File

@@ -7,7 +7,7 @@
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
namespace NCoderMixer2 {
namespace NCoderMixer {
// SetBindInfo()
// for each coder
@@ -26,11 +26,11 @@ namespace NCoderMixer2 {
// Code
// }
struct CSTCoderInfo: public CCoderInfo
struct CSTCoderInfo: public CCoderInfo2
{
bool IsMain;
CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain):
CCoderInfo(numInStreams, numOutStreams),IsMain(isMain) {}
CCoderInfo2(numInStreams, numOutStreams), IsMain(isMain) {}
};
class CCoderMixer2ST:
@@ -84,5 +84,5 @@ public:
};
}
#endif
#endif

View File

@@ -73,7 +73,7 @@ STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream,
for (i = 0; i < _coders.Size(); i++)
if (i != _progressCoderIndex)
_coders[i].WaitFinish();
_coders[i].WaitExecuteFinish();
RINOK(ReturnIfError(E_ABORT));
RINOK(ReturnIfError(E_OUTOFMEMORY));

View File

@@ -18,6 +18,7 @@ struct CCoder: public CCoderInfo, public CVirtThread
virtual void Execute();
void Code(ICompressProgressInfo *progress);
~CCoder() { CVirtThread::WaitThreadFinish(); }
};
/*

View File

@@ -2,16 +2,10 @@
#include "StdAfx.h"
#include "../../../Common/StringToInt.h"
#include "../../../Windows/PropVariant.h"
#ifndef _7ZIP_ST
#include "../../../Windows/System.h"
#endif
#include "../../ICoder.h"
#include "../Common/ParseProperties.h"
#include "HandlerOut.h"
@@ -20,487 +14,40 @@ using namespace NWindows;
namespace NArchive {
static const wchar_t *kCopyMethod = L"Copy";
static const wchar_t *kLZMAMethodName = L"LZMA";
static const wchar_t *kLZMA2MethodName = L"LZMA2";
static const wchar_t *kBZip2MethodName = L"BZip2";
static const wchar_t *kPpmdMethodName = L"PPMd";
static const wchar_t *kDeflateMethodName = L"Deflate";
static const wchar_t *kDeflate64MethodName = L"Deflate64";
static const wchar_t *kLzmaMatchFinderX1 = L"HC4";
static const wchar_t *kLzmaMatchFinderX5 = L"BT4";
static const UInt32 kLzmaAlgoX1 = 0;
static const UInt32 kLzmaAlgoX5 = 1;
static const UInt32 kLzmaDicSizeX1 = 1 << 16;
static const UInt32 kLzmaDicSizeX3 = 1 << 20;
static const UInt32 kLzmaDicSizeX5 = 1 << 24;
static const UInt32 kLzmaDicSizeX7 = 1 << 25;
static const UInt32 kLzmaDicSizeX9 = 1 << 26;
static const UInt32 kLzmaFastBytesX1 = 32;
static const UInt32 kLzmaFastBytesX7 = 64;
static const UInt32 kPpmdMemSizeX1 = (1 << 22);
static const UInt32 kPpmdMemSizeX5 = (1 << 24);
static const UInt32 kPpmdMemSizeX7 = (1 << 26);
static const UInt32 kPpmdMemSizeX9 = (192 << 20);
static const UInt32 kPpmdOrderX1 = 4;
static const UInt32 kPpmdOrderX5 = 6;
static const UInt32 kPpmdOrderX7 = 16;
static const UInt32 kPpmdOrderX9 = 32;
static const UInt32 kDeflateAlgoX1 = 0;
static const UInt32 kDeflateAlgoX5 = 1;
static const UInt32 kDeflateFastBytesX1 = 32;
static const UInt32 kDeflateFastBytesX7 = 64;
static const UInt32 kDeflateFastBytesX9 = 128;
static const UInt32 kDeflatePassesX1 = 1;
static const UInt32 kDeflatePassesX7 = 3;
static const UInt32 kDeflatePassesX9 = 10;
static const UInt32 kBZip2NumPassesX1 = 1;
static const UInt32 kBZip2NumPassesX7 = 2;
static const UInt32 kBZip2NumPassesX9 = 7;
static const UInt32 kBZip2DicSizeX1 = 100000;
static const UInt32 kBZip2DicSizeX3 = 500000;
static const UInt32 kBZip2DicSizeX5 = 900000;
static const wchar_t *kDefaultMethodName = kLZMAMethodName;
static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
static const UInt32 kDictionaryForHeaders = 1 << 20;
static const UInt32 kNumFastBytesForHeaders = 273;
static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5;
static bool AreEqual(const UString &methodName, const wchar_t *s)
{ return (methodName.CompareNoCase(s) == 0); }
bool COneMethodInfo::IsLzma() const
static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value)
{
return
AreEqual(MethodName, kLZMAMethodName) ||
AreEqual(MethodName, kLZMA2MethodName);
if (m.FindProp(propID) < 0)
m.AddProp32(propID, value);
}
static inline bool IsBZip2Method(const UString &methodName)
{ return AreEqual(methodName, kBZip2MethodName); }
static inline bool IsPpmdMethod(const UString &methodName)
{ return AreEqual(methodName, kPpmdMethodName); }
static inline bool IsDeflateMethod(const UString &methodName)
{
return
AreEqual(methodName, kDeflateMethodName) ||
AreEqual(methodName, kDeflate64MethodName);
}
struct CNameToPropID
{
PROPID PropID;
VARTYPE VarType;
const wchar_t *Name;
};
static CNameToPropID g_NameToPropID[] =
{
{ NCoderPropID::kBlockSize, VT_UI4, L"C" },
{ NCoderPropID::kDictionarySize, VT_UI4, L"D" },
{ NCoderPropID::kUsedMemorySize, VT_UI4, L"MEM" },
{ NCoderPropID::kOrder, VT_UI4, L"O" },
{ NCoderPropID::kPosStateBits, VT_UI4, L"PB" },
{ NCoderPropID::kLitContextBits, VT_UI4, L"LC" },
{ NCoderPropID::kLitPosBits, VT_UI4, L"LP" },
{ NCoderPropID::kEndMarker, VT_BOOL, L"eos" },
{ NCoderPropID::kNumPasses, VT_UI4, L"Pass" },
{ NCoderPropID::kNumFastBytes, VT_UI4, L"fb" },
{ NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },
{ NCoderPropID::kAlgorithm, VT_UI4, L"a" },
{ NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },
{ NCoderPropID::kNumThreads, VT_UI4, L"mt" },
{ NCoderPropID::kDefaultProp, VT_UI4, L"" }
};
static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
{
if (varType == srcProp.vt)
{
destProp = srcProp;
return true;
}
if (varType == VT_UI1)
{
if (srcProp.vt == VT_UI4)
{
UInt32 value = srcProp.ulVal;
if (value > 0xFF)
return false;
destProp = (Byte)value;
return true;
}
}
else if (varType == VT_BOOL)
{
bool res;
if (SetBoolProperty(res, srcProp) != S_OK)
return false;
destProp = res;
return true;
}
return false;
}
static int FindPropIdExact(const UString &name)
{
for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
return i;
return -1;
}
static int FindPropIdStart(const UString &name)
{
for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
{
UString t = g_NameToPropID[i].Name;
if (t.CompareNoCase(name.Left(t.Length())) == 0)
return i;
}
return -1;
}
static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value)
{
for (int j = 0; j < m.Props.Size(); j++)
if (m.Props[j].Id == propID)
return;
CProp prop;
prop.Id = propID;
prop.Value = value;
m.Props.Add(prop);
}
void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
)
{
UInt32 level = _level;
if (oneMethodInfo.MethodName.IsEmpty())
oneMethodInfo.MethodName = kDefaultMethodName;
if (oneMethodInfo.IsLzma())
{
UInt32 dicSize =
(level >= 9 ? kLzmaDicSizeX9 :
(level >= 7 ? kLzmaDicSizeX7 :
(level >= 5 ? kLzmaDicSizeX5 :
(level >= 3 ? kLzmaDicSizeX3 :
kLzmaDicSizeX1))));
UInt32 algo =
(level >= 5 ? kLzmaAlgoX5 :
kLzmaAlgoX1);
UInt32 fastBytes =
(level >= 7 ? kLzmaFastBytesX7 :
kLzmaFastBytesX1);
const wchar_t *matchFinder =
(level >= 5 ? kLzmaMatchFinderX5 :
kLzmaMatchFinderX1);
SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);
if (level != (UInt32)(UInt32)-1)
SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
#ifndef _7ZIP_ST
SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
#endif
}
else if (IsDeflateMethod(oneMethodInfo.MethodName))
{
UInt32 fastBytes =
(level >= 9 ? kDeflateFastBytesX9 :
(level >= 7 ? kDeflateFastBytesX7 :
kDeflateFastBytesX1));
}
UInt32 numPasses =
(level >= 9 ? kDeflatePassesX9 :
(level >= 7 ? kDeflatePassesX7 :
kDeflatePassesX1));
UInt32 algo =
(level >= 5 ? kDeflateAlgoX5 :
kDeflateAlgoX1);
SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
}
else if (IsBZip2Method(oneMethodInfo.MethodName))
{
UInt32 numPasses =
(level >= 9 ? kBZip2NumPassesX9 :
(level >= 7 ? kBZip2NumPassesX7 :
kBZip2NumPassesX1));
UInt32 dicSize =
(level >= 5 ? kBZip2DicSizeX5 :
(level >= 3 ? kBZip2DicSizeX3 :
kBZip2DicSizeX1));
SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
void CMultiMethodProps::Init()
{
#ifndef _7ZIP_ST
SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
#endif
}
else if (IsPpmdMethod(oneMethodInfo.MethodName))
{
UInt32 useMemSize =
(level >= 9 ? kPpmdMemSizeX9 :
(level >= 7 ? kPpmdMemSizeX7 :
(level >= 5 ? kPpmdMemSizeX5 :
kPpmdMemSizeX1)));
UInt32 order =
(level >= 9 ? kPpmdOrderX9 :
(level >= 7 ? kPpmdOrderX7 :
(level >= 5 ? kPpmdOrderX5 :
kPpmdOrderX1)));
SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);
SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);
}
}
static void SplitParams(const UString &srcString, UStringVector &subStrings)
{
subStrings.Clear();
UString name;
int len = srcString.Length();
if (len == 0)
return;
for (int i = 0; i < len; i++)
{
wchar_t c = srcString[i];
if (c == L':')
{
subStrings.Add(name);
name.Empty();
}
else
name += c;
}
subStrings.Add(name);
}
static void SplitParam(const UString &param, UString &name, UString &value)
{
int eqPos = param.Find(L'=');
if (eqPos >= 0)
{
name = param.Left(eqPos);
value = param.Mid(eqPos + 1);
return;
}
for(int i = 0; i < param.Length(); i++)
{
wchar_t c = param[i];
if (c >= L'0' && c <= L'9')
{
name = param.Left(i);
value = param.Mid(i);
return;
}
}
name = param;
}
HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)
{
CProp prop;
int index = FindPropIdExact(name);
if (index < 0)
return E_INVALIDARG;
const CNameToPropID &nameToPropID = g_NameToPropID[index];
prop.Id = nameToPropID.PropID;
if (prop.Id == NCoderPropID::kBlockSize ||
prop.Id == NCoderPropID::kDictionarySize ||
prop.Id == NCoderPropID::kUsedMemorySize)
{
UInt32 dicSize;
RINOK(ParsePropDictionaryValue(value, dicSize));
prop.Value = dicSize;
}
else
{
NCOM::CPropVariant propValue;
if (nameToPropID.VarType == VT_BSTR)
propValue = value;
else if (nameToPropID.VarType == VT_BOOL)
{
bool res;
if (!StringToBool(value, res))
return E_INVALIDARG;
propValue = res;
}
else
{
UInt32 number;
if (ParseStringToUInt32(value, number) == value.Length())
propValue = number;
else
propValue = value;
}
if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))
return E_INVALIDARG;
}
oneMethodInfo.Props.Add(prop);
return S_OK;
}
HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)
{
UStringVector params;
SplitParams(srcString, params);
if (params.Size() > 0)
oneMethodInfo.MethodName = params[0];
for (int i = 1; i < params.Size(); i++)
{
const UString &param = params[i];
UString name, value;
SplitParam(param, name, value);
RINOK(SetParam(oneMethodInfo, name, value));
}
return S_OK;
}
HRESULT COutHandler::SetSolidSettings(const UString &s)
{
UString s2 = s;
s2.MakeUpper();
for (int i = 0; i < s2.Length();)
{
const wchar_t *start = ((const wchar_t *)s2) + i;
const wchar_t *end;
UInt64 v = ConvertStringToUInt64(start, &end);
if (start == end)
{
if (s2[i++] != 'E')
return E_INVALIDARG;
_solidExtension = true;
continue;
}
i += (int)(end - start);
if (i == s2.Length())
return E_INVALIDARG;
wchar_t c = s2[i++];
switch(c)
{
case 'F':
if (v < 1)
v = 1;
_numSolidFiles = v;
break;
case 'B':
_numSolidBytes = v;
_numSolidBytesDefined = true;
break;
case 'K':
_numSolidBytes = (v << 10);
_numSolidBytesDefined = true;
break;
case 'M':
_numSolidBytes = (v << 20);
_numSolidBytesDefined = true;
break;
case 'G':
_numSolidBytes = (v << 30);
_numSolidBytesDefined = true;
break;
default:
return E_INVALIDARG;
}
}
return S_OK;
}
HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value)
{
bool isSolid;
switch(value.vt)
{
case VT_EMPTY:
isSolid = true;
break;
case VT_BOOL:
isSolid = (value.boolVal != VARIANT_FALSE);
break;
case VT_BSTR:
if (StringToBool(value.bstrVal, isSolid))
break;
return SetSolidSettings(value.bstrVal);
default:
return E_INVALIDARG;
}
if (isSolid)
InitSolid();
else
_numSolidFiles = 1;
return S_OK;
}
void COutHandler::Init()
{
_removeSfxBlock = false;
_compressHeaders = true;
_encryptHeadersSpecified = false;
_encryptHeaders = false;
WriteCTime = false;
WriteATime = false;
WriteMTime = true;
#ifndef _7ZIP_ST
_numThreads = NSystem::GetNumberOfProcessors();
_numProcessors = _numThreads = NSystem::GetNumberOfProcessors();
#endif
_level = 5;
_level = (UInt32)(UInt32)-1;
_autoFilter = true;
_volumeMode = false;
_crcSize = 4;
InitSolid();
_filterMethod.Clear();
_methods.Clear();
}
void COutHandler::BeforeSetProperty()
{
Init();
#ifndef _7ZIP_ST
numProcessors = NSystem::GetNumberOfProcessors();
#endif
mainDicSize = 0xFFFFFFFF;
mainDicMethodIndex = 0xFFFFFFFF;
minNumber = 0;
_crcSize = 4;
}
HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
{
UString name = nameSpec;
name.MakeUpper();
@@ -511,24 +58,14 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
{
name.Delete(0);
_level = 9;
return ParsePropValue(name, value, _level);
}
if (name[0] == L'S')
{
name.Delete(0);
if (name.IsEmpty())
return SetSolidSettings(value);
if (value.vt != VT_EMPTY)
return E_INVALIDARG;
return SetSolidSettings(name);
return ParsePropToUInt32(name, value, _level);
}
if (name == L"CRC")
{
_crcSize = 4;
name.Delete(0, 3);
return ParsePropValue(name, value, _crcSize);
_crcSize = 4;
return ParsePropToUInt32(name, value, _crcSize);
}
UInt32 number;
@@ -536,86 +73,67 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
UString realName = name.Mid(index);
if (index == 0)
{
if(name.Left(2).CompareNoCase(L"MT") == 0)
if (name.Left(2).CompareNoCase(L"MT") == 0)
{
#ifndef _7ZIP_ST
RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
RINOK(ParseMtProp(name.Mid(2), value, _numProcessors, _numThreads));
#endif
return S_OK;
}
if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value);
if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value);
if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value);
if (name.CompareNoCase(L"HCF") == 0)
{
bool compressHeadersFull = true;
RINOK(SetBoolProperty(compressHeadersFull, value));
if (!compressHeadersFull)
return E_INVALIDARG;
return S_OK;
}
if (name.CompareNoCase(L"HE") == 0)
{
RINOK(SetBoolProperty(_encryptHeaders, value));
_encryptHeadersSpecified = true;
return S_OK;
}
if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value);
if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value);
if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value);
if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value);
number = 0;
}
if (number > 10000)
return E_FAIL;
if (number < minNumber)
return E_INVALIDARG;
number -= minNumber;
for(int j = _methods.Size(); j <= (int)number; j++)
{
COneMethodInfo oneMethodInfo;
_methods.Add(oneMethodInfo);
}
COneMethodInfo &oneMethodInfo = _methods[number];
if (realName.Length() == 0)
if (name.CompareNoCase(L"F") == 0)
{
HRESULT res = PROPVARIANT_to_bool(value, _autoFilter);
if (res == S_OK)
return res;
if (value.vt != VT_BSTR)
return E_INVALIDARG;
return _filterMethod.ParseMethodFromPROPVARIANT(L"", value);
}
number = 0;
}
if (number > 64)
return E_FAIL;
for (int j = _methods.Size(); j <= (int)number; j++)
_methods.Add(COneMethodInfo());
return _methods[number].ParseMethodFromPROPVARIANT(realName, value);
}
RINOK(SetParams(oneMethodInfo, value.bstrVal));
void CSingleMethodProps::Init()
{
Clear();
#ifndef _7ZIP_ST
_numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
AddNumThreadsProp(_numThreads);
#endif
_level = (UInt32)(UInt32)-1;
}
HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
Init();
for (int i = 0; i < numProps; i++)
{
UString name = names[i];
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
const PROPVARIANT &value = values[i];
if (name[0] == L'X')
{
UInt32 a = 9;
RINOK(ParsePropToUInt32(name.Mid(1), value, a));
_level = a;
AddLevelProp(a);
}
else if (name.Left(2).CompareNoCase(L"MT") == 0)
{
#ifndef _7ZIP_ST
RINOK(ParseMtProp(name.Mid(2), value, _numProcessors, _numThreads));
AddNumThreadsProp(_numThreads);
#endif
}
else
{
int index = FindPropIdStart(realName);
if (index < 0)
return E_INVALIDARG;
const CNameToPropID &nameToPropID = g_NameToPropID[index];
CProp prop;
prop.Id = nameToPropID.PropID;
if (prop.Id == NCoderPropID::kBlockSize ||
prop.Id == NCoderPropID::kDictionarySize ||
prop.Id == NCoderPropID::kUsedMemorySize)
{
UInt32 dicSize;
RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize));
prop.Value = dicSize;
if (number <= mainDicMethodIndex)
mainDicSize = dicSize;
}
else
{
int index = FindPropIdExact(realName);
if (index < 0)
return E_INVALIDARG;
const CNameToPropID &nameToPropID = g_NameToPropID[index];
prop.Id = nameToPropID.PropID;
if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))
return E_INVALIDARG;
}
oneMethodInfo.Props.Add(prop);
return ParseParamsFromPROPVARIANT(name, value);
}
return S_OK;
}

View File

@@ -3,83 +3,61 @@
#ifndef __HANDLER_OUT_H
#define __HANDLER_OUT_H
#include "../../../Common/MyString.h"
#include "../../Common/MethodProps.h"
namespace NArchive {
struct COneMethodInfo
{
CObjectVector<CProp> Props;
UString MethodName;
bool IsLzma() const;
};
class COutHandler
class CMultiMethodProps
{
UInt32 _level;
public:
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
HRESULT SetSolidSettings(const UString &s);
HRESULT SetSolidSettings(const PROPVARIANT &value);
#ifndef _7ZIP_ST
UInt32 _numThreads;
UInt32 _numProcessors;
#endif
UInt32 _crcSize;
CObjectVector<COneMethodInfo> _methods;
bool _removeSfxBlock;
UInt64 _numSolidFiles;
UInt64 _numSolidBytes;
bool _numSolidBytesDefined;
bool _solidExtension;
bool _compressHeaders;
bool _encryptHeadersSpecified;
bool _encryptHeaders;
bool WriteCTime;
bool WriteATime;
bool WriteMTime;
COneMethodInfo _filterMethod;
bool _autoFilter;
UInt32 _level;
bool _volumeMode;
HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value);
HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString);
void SetCompressionMethod2(COneMethodInfo &oneMethodInfo
void SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
);
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
void InitSolid()
int GetNumEmptyMethods() const
{
InitSolidFiles();
InitSolidSize();
_solidExtension = false;
_numSolidBytesDefined = false;
int i;
for (i = 0; i < _methods.Size(); i++)
if (!_methods[i].IsEmpty())
break;
return i;
}
int GetLevel() const { return _level == (UInt32)(UInt32)-1 ? 5 : (int)_level; }
void Init();
COutHandler() { Init(); }
CMultiMethodProps() { Init(); }
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
};
void BeforeSetProperty();
class CSingleMethodProps: public CMethodProps
{
UInt32 _level;
UInt32 minNumber;
UInt32 numProcessors;
UInt32 mainDicSize;
UInt32 mainDicMethodIndex;
void Init();
public:
#ifndef _7ZIP_ST
UInt32 _numThreads;
UInt32 _numProcessors;
#endif
CSingleMethodProps() { Init(); }
int GetLevel() const { return _level == (UInt32)(UInt32)-1 ? 5 : (int)_level; }
HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
};
}

View File

@@ -31,8 +31,8 @@ UString GetOSName2(const UString &name)
if (name.IsEmpty())
return UString();
UString newName = GetOSName(name);
if (newName[newName.Length() - 1] == kOSDirDelimiter)
newName.Delete(newName.Length() - 1);
if (newName.Back() == kOSDirDelimiter)
newName.DeleteBack();
return newName;
}

View File

@@ -1,177 +1,3 @@
// ParseProperties.cpp
#include "StdAfx.h"
#include "ParseProperties.h"
#include "Common/StringToInt.h"
#include "Common/MyCom.h"
HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
{
if (prop.vt == VT_UI4)
{
if (!name.IsEmpty())
return E_INVALIDARG;
resValue = prop.ulVal;
}
else if (prop.vt == VT_EMPTY)
{
if(!name.IsEmpty())
{
const wchar_t *start = name;
const wchar_t *end;
UInt64 v = ConvertStringToUInt64(start, &end);
if (end - start != name.Length())
return E_INVALIDARG;
resValue = (UInt32)v;
}
}
else
return E_INVALIDARG;
return S_OK;
}
static const int kLogarithmicSizeLimit = 32;
static const wchar_t kByteSymbol = L'B';
static const wchar_t kKiloByteSymbol = L'K';
static const wchar_t kMegaByteSymbol = L'M';
HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize)
{
UString srcString = srcStringSpec;
srcString.MakeUpper();
const wchar_t *start = srcString;
const wchar_t *end;
UInt64 number = ConvertStringToUInt64(start, &end);
int numDigits = (int)(end - start);
if (numDigits == 0 || srcString.Length() > numDigits + 1)
return E_INVALIDARG;
if (srcString.Length() == numDigits)
{
if (number >= kLogarithmicSizeLimit)
return E_INVALIDARG;
dicSize = (UInt32)1 << (int)number;
return S_OK;
}
switch (srcString[numDigits])
{
case kByteSymbol:
if (number >= ((UInt64)1 << kLogarithmicSizeLimit))
return E_INVALIDARG;
dicSize = (UInt32)number;
break;
case kKiloByteSymbol:
if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10)))
return E_INVALIDARG;
dicSize = (UInt32)(number << 10);
break;
case kMegaByteSymbol:
if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20)))
return E_INVALIDARG;
dicSize = (UInt32)(number << 20);
break;
default:
return E_INVALIDARG;
}
return S_OK;
}
HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
{
if (name.IsEmpty())
{
if (prop.vt == VT_UI4)
{
UInt32 logDicSize = prop.ulVal;
if (logDicSize >= 32)
return E_INVALIDARG;
resValue = (UInt32)1 << logDicSize;
return S_OK;
}
if (prop.vt == VT_BSTR)
return ParsePropDictionaryValue(prop.bstrVal, resValue);
return E_INVALIDARG;
}
return ParsePropDictionaryValue(name, resValue);
}
bool StringToBool(const UString &s, bool &res)
{
if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0)
{
res = true;
return true;
}
if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0)
{
res = false;
return true;
}
return false;
}
HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)
{
switch(value.vt)
{
case VT_EMPTY:
dest = true;
return S_OK;
case VT_BOOL:
dest = (value.boolVal != VARIANT_FALSE);
return S_OK;
/*
case VT_UI4:
dest = (value.ulVal != 0);
break;
*/
case VT_BSTR:
return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG;
}
return E_INVALIDARG;
}
int ParseStringToUInt32(const UString &srcString, UInt32 &number)
{
const wchar_t *start = srcString;
const wchar_t *end;
UInt64 number64 = ConvertStringToUInt64(start, &end);
if (number64 > 0xFFFFFFFF)
{
number = 0;
return 0;
}
number = (UInt32)number64;
return (int)(end - start);
}
HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)
{
if (name.IsEmpty())
{
switch(prop.vt)
{
case VT_UI4:
numThreads = prop.ulVal;
break;
default:
{
bool val;
RINOK(SetBoolProperty(val, prop));
numThreads = (val ? defaultNumThreads : 1);
break;
}
}
}
else
{
UInt32 number;
int index = ParseStringToUInt32(name, number);
if (index != name.Length())
return E_INVALIDARG;
numThreads = number;
}
return S_OK;
}

View File

@@ -1,18 +1,6 @@
// ParseProperties.h
#ifndef __PARSEPROPERTIES_H
#define __PARSEPROPERTIES_H
#include "Common/MyString.h"
#include "Common/Types.h"
HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize);
HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
bool StringToBool(const UString &s, bool &res);
HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value);
int ParseStringToUInt32(const UString &srcString, UInt32 &number);
HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);
#ifndef __PARSE_PROPERTIES_H
#define __PARSE_PROPERTIES_H
#endif

View File

@@ -1,118 +1,3 @@
// DeflateProps.cpp
#include "StdAfx.h"
#include "Windows/PropVariant.h"
#include "Common/ParseProperties.h"
#include "DeflateProps.h"
namespace NArchive {
static const UInt32 kAlgo1 = 0;
static const UInt32 kAlgo5 = 1;
static const UInt32 kPasses1 = 1;
static const UInt32 kPasses7 = 3;
static const UInt32 kPasses9 = 10;
static const UInt32 kFb1 = 32;
static const UInt32 kFb7 = 64;
static const UInt32 kFb9 = 128;
void CDeflateProps::Normalize()
{
UInt32 level = Level;
if (level == 0xFFFFFFFF)
level = 5;
if (Algo == 0xFFFFFFFF)
Algo = (level >= 5 ?
kAlgo5 :
kAlgo1);
if (NumPasses == 0xFFFFFFFF)
NumPasses =
(level >= 9 ? kPasses9 :
(level >= 7 ? kPasses7 :
kPasses1));
if (Fb == 0xFFFFFFFF)
Fb =
(level >= 9 ? kFb9 :
(level >= 7 ? kFb7 :
kFb1));
}
HRESULT CDeflateProps::SetCoderProperties(ICompressSetCoderProperties *setCoderProperties)
{
Normalize();
NWindows::NCOM::CPropVariant props[] =
{
Algo,
NumPasses,
Fb,
Mc
};
PROPID propIDs[] =
{
NCoderPropID::kAlgorithm,
NCoderPropID::kNumPasses,
NCoderPropID::kNumFastBytes,
NCoderPropID::kMatchFinderCycles
};
int numProps = sizeof(propIDs) / sizeof(propIDs[0]);
if (!McDefined)
numProps--;
return setCoderProperties->SetCoderProperties(propIDs, props, numProps);
}
HRESULT CDeflateProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
Init();
for (int i = 0; i < numProps; i++)
{
UString name = names[i];
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
const PROPVARIANT &prop = values[i];
if (name[0] == L'X')
{
UInt32 a = 9;
RINOK(ParsePropValue(name.Mid(1), prop, a));
Level = a;
}
else if (name.Left(1) == L"A")
{
UInt32 a = kAlgo5;
RINOK(ParsePropValue(name.Mid(1), prop, a));
Algo = a;
}
else if (name.Left(4) == L"PASS")
{
UInt32 a = kPasses9;
RINOK(ParsePropValue(name.Mid(4), prop, a));
NumPasses = a;
}
else if (name.Left(2) == L"FB")
{
UInt32 a = kFb9;
RINOK(ParsePropValue(name.Mid(2), prop, a));
Fb = a;
}
else if (name.Left(2) == L"MC")
{
UInt32 a = 0xFFFFFFFF;
RINOK(ParsePropValue(name.Mid(2), prop, a));
Mc = a;
McDefined = true;
}
else
return E_INVALIDARG;
}
return S_OK;
}
}

View File

@@ -3,33 +3,4 @@
#ifndef __DEFLATE_PROPS_H
#define __DEFLATE_PROPS_H
#include "../ICoder.h"
namespace NArchive {
class CDeflateProps
{
UInt32 Level;
UInt32 NumPasses;
UInt32 Fb;
UInt32 Algo;
UInt32 Mc;
bool McDefined;
void Init()
{
Level = NumPasses = Fb = Algo = Mc = 0xFFFFFFFF;
McDefined = false;
}
void Normalize();
public:
CDeflateProps() { Init(); }
bool IsMaximum() const { return Algo > 0; }
HRESULT SetCoderProperties(ICompressSetCoderProperties *setCoderProperties);
HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
};
}
#endif

View File

@@ -18,11 +18,10 @@
#include "../Compress/DeflateDecoder.h"
#include "../Compress/DeflateEncoder.h"
#include "Common/HandlerOut.h"
#include "Common/InStreamWithCRC.h"
#include "Common/OutStreamWithCRC.h"
#include "DeflateProps.h"
#define Get32(p) GetUi32(p)
using namespace NWindows;
@@ -305,7 +304,7 @@ class CHandler:
CMyComPtr<ICompressCoder> _decoder;
NCompress::NDeflate::NDecoder::CCOMCoder *_decoderSpec;
CDeflateProps _method;
CSingleMethodProps _props;
public:
MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
@@ -321,7 +320,7 @@ public:
}
};
STATPROPSTG kProps[] =
static STATPROPSTG const kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8},
@@ -545,7 +544,7 @@ static HRESULT UpdateArchive(
ISequentialOutStream *outStream,
UInt64 unpackSize,
const CItem &newItem,
CDeflateProps &deflateProps,
const CSingleMethodProps &props,
IArchiveUpdateCallback *updateCallback)
{
UInt64 complexity = 0;
@@ -567,7 +566,7 @@ static HRESULT UpdateArchive(
CItem item = newItem;
item.Method = NHeader::NCompressionMethod::kDeflate;
item.ExtraFlags = deflateProps.IsMaximum() ?
item.ExtraFlags = props.GetLevel() >= 7 ?
NHeader::NExtraFlags::kMaximum :
NHeader::NExtraFlags::kFastest;
@@ -577,7 +576,7 @@ static HRESULT UpdateArchive(
NCompress::NDeflate::NEncoder::CCOMCoder *deflateEncoderSpec = new NCompress::NDeflate::NEncoder::CCOMCoder;
CMyComPtr<ICompressCoder> deflateEncoder = deflateEncoderSpec;
RINOK(deflateProps.SetCoderProperties(deflateEncoderSpec));
RINOK(props.SetCoderProps(deflateEncoderSpec, NULL));
RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress));
item.Crc = inStreamSpec->GetCRC();
@@ -616,8 +615,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (prop.vt != VT_FILETIME)
return E_INVALIDARG;
utcTime = prop.filetime;
if (!NTime::FileTimeToUnixTime(utcTime, newItem.Time))
return E_INVALIDARG;
NTime::FileTimeToUnixTime(utcTime, newItem.Time);
}
{
NCOM::CPropVariant prop;
@@ -658,8 +656,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
}
return UpdateArchive(outStream, size, newItem, _method, updateCallback);
return UpdateArchive(outStream, size, newItem, _props, updateCallback);
}
if (indexInArchive != 0)
@@ -680,7 +677,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
return _method.SetProperties(names, values, numProps);
return _props.SetProperties(names, values, numProps);
}
static IInArchive *CreateArc() { return new CHandler; }

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -172,11 +172,11 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
int pos = s.ReverseFind(L';');
if (pos >= 0 && pos == s.Length() - 2)
if (s[s.Length() - 1] == L'1')
if (s.Back() == L'1')
s = s.Left(pos);
if (!s.IsEmpty())
if (s[s.Length() - 1] == L'.')
s = s.Left(s.Length() - 1);
if (s.Back() == L'.')
s.DeleteBack();
prop = (const wchar_t *)NItemName::GetOSName2(s);
}
break;
@@ -211,20 +211,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return S_OK;
UInt64 totalSize = 0;
UInt32 i;
for(i = 0; i < numItems; i++)
for (i = 0; i < numItems; i++)
{
UInt32 index = (allFilesMode ? i : indices[i]);
if (index < (UInt32)_archive.Refs.Size())
{
const CRef &ref = _archive.Refs[index];
const CDir &item = ref.Dir->_subItems[ref.Index];
if (!item.IsDir())
totalSize += item.DataLength;
}
else
{
totalSize += _archive.GetBootItemSize(index - _archive.Refs.Size());
}
}
extractCallback->SetTotal(totalSize);
UInt64 currentTotalSize = 0;

View File

@@ -177,47 +177,6 @@ struct CItem
}
};
struct CItemEx: public CItem
{
UInt64 DataPosition;
};
class CInArchive
{
CMyComPtr<IInStream> m_Stream;
UInt64 m_Position;
HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize);
HRESULT CheckReadBytes(void *data, UInt32 size);
public:
HRESULT Open(IInStream *inStream);
HRESULT GetNextItem(bool &filled, CItemEx &itemInfo);
HRESULT Skip(UInt64 numBytes);
};
HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
{
size_t realProcessedSize = size;
RINOK(ReadStream(m_Stream, data, &realProcessedSize));
processedSize = (UInt32)realProcessedSize;
m_Position += processedSize;
return S_OK;
}
HRESULT CInArchive::CheckReadBytes(void *data, UInt32 size)
{
UInt32 processedSize;
RINOK(ReadBytes(data, size, processedSize));
return (processedSize == size) ? S_OK: S_FALSE;
}
HRESULT CInArchive::Open(IInStream *inStream)
{
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
m_Stream = inStream;
return S_OK;
}
static const Byte *ReadUInt16(const Byte *p, UInt16 &v)
{
v = Get16(p);
@@ -245,13 +204,13 @@ static Byte CalcSum(const Byte *data, size_t size)
return sum;
}
HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
static HRESULT GetNextItem(ISequentialInStream *stream, bool &filled, CItem &item)
{
filled = false;
UInt32 processedSize;
size_t processedSize = 2;
Byte startHeader[2];
RINOK(ReadBytes(startHeader, 2, processedSize))
RINOK(ReadStream(stream, startHeader, &processedSize))
if (processedSize == 0)
return S_OK;
if (processedSize == 1)
@@ -261,7 +220,8 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
Byte header[256];
const UInt32 kBasicPartSize = 22;
RINOK(ReadBytes(header, kBasicPartSize, processedSize));
processedSize = kBasicPartSize;
RINOK(ReadStream(stream, header, &processedSize));
if (processedSize != kBasicPartSize)
return (startHeader[0] == 0) ? S_OK: S_FALSE;
@@ -284,8 +244,7 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
headerSize = startHeader[0];
if (headerSize < kBasicPartSize)
return S_FALSE;
UInt32 remain = headerSize - kBasicPartSize;
RINOK(CheckReadBytes(header + kBasicPartSize, remain));
RINOK(ReadStream_FALSE(stream, header + kBasicPartSize, headerSize - kBasicPartSize));
if (startHeader[1] != CalcSum(header, headerSize))
return S_FALSE;
size_t nameLength = *p++;
@@ -300,7 +259,7 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
{
if (item.Level == 2)
{
RINOK(CheckReadBytes(header + kBasicPartSize, 2));
RINOK(ReadStream_FALSE(stream, header + kBasicPartSize, 2));
}
if ((size_t)(p - header) + 3 > headerSize)
return S_FALSE;
@@ -317,39 +276,30 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
return S_FALSE;
item.PackSize -= nextSize;
}
if (item.Extensions.Size() >= (1 << 8))
return S_FALSE;
CExtension ext;
RINOK(CheckReadBytes(&ext.Type, 1))
RINOK(ReadStream_FALSE(stream, &ext.Type, 1))
nextSize -= 3;
ext.Data.SetCapacity(nextSize);
RINOK(CheckReadBytes((Byte *)ext.Data, nextSize))
RINOK(ReadStream_FALSE(stream, (Byte *)ext.Data, nextSize))
item.Extensions.Add(ext);
Byte hdr2[2];
RINOK(CheckReadBytes(hdr2, 2));
RINOK(ReadStream_FALSE(stream, hdr2, 2));
ReadUInt16(hdr2, nextSize);
}
}
item.DataPosition = m_Position;
filled = true;
return S_OK;
}
HRESULT CInArchive::Skip(UInt64 numBytes)
{
UInt64 newPostion;
RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));
m_Position += numBytes;
if (m_Position != newPostion)
return E_FAIL;
return S_OK;
}
struct COsPair
{
Byte Id;
const char *Name;
};
static COsPair g_OsPairs[] =
static const COsPair g_OsPairs[] =
{
{ 0, "MS-DOS" },
{ 'M', "MS-DOS" },
@@ -380,7 +330,7 @@ static const char *GetOS(Byte osId)
return kUnknownOS;
}
static STATPROPSTG kProps[] =
static const STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
@@ -393,6 +343,11 @@ static STATPROPSTG kProps[] =
{ NULL, kpidHostOS, VT_BSTR}
};
static const STATPROPSTG kArcProps[] =
{
{ NULL, kpidPhySize, VT_UI8}
};
class CCRC
{
UInt16 _value;
@@ -479,12 +434,19 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *pro
return result;
}
struct CItemEx: public CItem
{
UInt64 DataPosition;
};
class CHandler:
public IInArchive,
public CMyUnknownImp
{
CObjectVector<CItemEx> _items;
CMyComPtr<IInStream> _stream;
UInt64 _phySize;
AString _errorMessage;
public:
MY_UNKNOWN_IMP1(IInArchive)
INTERFACE_IInArchive(;)
@@ -492,7 +454,7 @@ public:
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO
IMP_IInArchive_ArcProps
CHandler::CHandler() {}
@@ -502,6 +464,18 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK;
}
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch(propID)
{
case kpidPhySize: prop = _phySize; break;
case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
@@ -514,8 +488,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP));
if (!s.IsEmpty())
{
if (s[s.Length() - 1] == WCHAR_PATH_SEPARATOR)
s.Delete(s.Length() - 1);
if (s.Back() == WCHAR_PATH_SEPARATOR)
s.DeleteBack();
prop = s;
}
break;
@@ -567,32 +541,43 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
try
{
_items.Clear();
CInArchive archive;
UInt64 endPos = 0;
bool needSetTotal = true;
if (callback != NULL)
{
RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
}
RINOK(archive.Open(stream));
_phySize = 0;
for (;;)
{
CItemEx item;
bool filled;
HRESULT result = archive.GetNextItem(filled, item);
HRESULT result = GetNextItem(stream, filled, item);
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &item.DataPosition));
if (result == S_FALSE)
return S_FALSE;
{
_errorMessage = "Incorrect header";
break;
}
if (result != S_OK)
return S_FALSE;
_phySize = item.DataPosition;
if (!filled)
break;
_items.Add(item);
archive.Skip(item.PackSize);
if (callback != NULL)
UInt64 newPostion;
RINOK(stream->Seek(item.PackSize, STREAM_SEEK_CUR, &newPostion));
if (newPostion > endPos)
{
_phySize = endPos;
_errorMessage = "Unexpected end of archive";
break;
}
_phySize = newPostion;
if (callback)
{
if (needSetTotal)
{
@@ -622,6 +607,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
STDMETHODIMP CHandler::Close()
{
_errorMessage.Empty();
_items.Clear();
_stream.Release();
return S_OK;

View File

@@ -296,7 +296,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal
RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));
_packSize = endPos - _startPosition;
_packSizeDefined = true;
if (_packSize >= 24 && _header.Size == 0 && _header.FilterID == 0 && _header.LzmaProps[0] == 0)
return S_FALSE;
_stream = inStream;
_seqStream = inStream;
return S_OK;

View File

@@ -15,7 +15,7 @@
#include "../Compress/CopyCoder.h"
#define Get32(p) GetBe32(p)
static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); }
namespace NArchive {
namespace NMub {
@@ -116,8 +116,16 @@ HRESULT CHandler::Open2(IInStream *stream)
RINOK(ReadStream(stream, buf, &processed));
if (processed < kHeaderSize)
return S_FALSE;
UInt32 num = Get32(buf + 4);
if (Get32(buf) != 0xCAFEBABE || num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize)
bool be;
switch (GetBe32(buf))
{
case 0xCAFEBABE: be = true; break;
case 0xB9FAF10E: be = false; break;
default: return S_FALSE;
}
UInt32 num = Get32(buf + 4, be);
if (num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize)
return S_FALSE;
UInt64 endPosMax = kHeaderSize;
for (UInt32 i = 0; i < num; i++)
@@ -125,11 +133,11 @@ HRESULT CHandler::Open2(IInStream *stream)
const Byte *p = buf + kHeaderSize + i * kRecordSize;
CItem &sb = _items[i];
sb.IsTail = false;
sb.Type = Get32(p);
sb.SubType = Get32(p + 4);
sb.Offset = Get32(p + 8);
sb.Size = Get32(p + 12);
sb.Align = Get32(p + 16);
sb.Type = Get32(p, be);
sb.SubType = Get32(p + 4, be);
sb.Offset = Get32(p + 8, be);
sb.Size = Get32(p + 12, be);
sb.Align = Get32(p + 16, be);
if ((sb.Type & ~MACH_TYPE_ABI64) >= 0x100 ||
(sb.SubType & ~MACH_SUBTYPE_ABI64) >= 0x100 ||

View File

@@ -87,7 +87,7 @@ struct CItem
else
s = MultiByteToUnicodeString(PrefixA);
if (s.Length() > 0)
if (s[s.Length() - 1] != L'\\')
if (s.Back() != L'\\')
s += L'\\';
if (unicode)
s += NameU;

View File

@@ -631,7 +631,7 @@ enum
// kpidBaseOfData32,
};
STATPROPSTG kArcProps[] =
static const STATPROPSTG kArcProps[] =
{
{ NULL, kpidCpu, VT_BSTR},
{ NULL, kpidBit64, VT_BOOL},
@@ -662,7 +662,7 @@ STATPROPSTG kArcProps[] =
// { L"Base Of Data", kpidBaseOfData32, VT_UI8},
};
STATPROPSTG kProps[] =
static const STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8},
@@ -1749,4 +1749,335 @@ static CArcInfo g_ArcInfo =
REGISTER_ARC(Pe)
}}
}
namespace NTe {
// Terse Executable (TE) image
/*
struct CDataDir
{
UInt32 Va;
UInt32 Size;
};
*/
static const UInt32 kHeaderSize = 40;
static bool FindValue(const CUInt32PCharPair *pairs, unsigned num, UInt32 value)
{
for (unsigned i = 0; i < num; i++)
if (pairs[i].Value == value)
return true;
return false;
}
#define MY_FIND_VALUE(pairs, value) FindValue(pairs, sizeof(pairs) / sizeof(pairs[0]), value)
struct CHeader
{
UInt16 Machine;
Byte NumSections;
Byte SubSystem;
UInt16 StrippedSize;
/*
UInt32 AddressOfEntryPoint;
UInt32 BaseOfCode;
UInt64 ImageBase;
CDataDir DataDir[2]; // base relocation and debug directory
*/
UInt32 ConvertPa(UInt32 pa) const { return pa - StrippedSize + kHeaderSize; }
bool Parse(const Byte *p)
{
if (p[0] != 'V' || p[1] != 'Z')
return false;
Machine = Get16(p + 2);
NumSections = p[4];
SubSystem = p[5];
StrippedSize = Get16(p + 6);
/*
AddressOfEntryPoint = Get32(p + 8);
BaseOfCode = Get32(p + 12);
ImageBase = Get64(p + 16);
for (int i = 0; i < 2; i++)
{
const Byte *p2 = p + 24 + i * 8;
DataDir[i].Va = Get32(p2);
DataDir[i].Size = Get32(p2 + 4);
}
*/
return NumSections <= 64 &&
MY_FIND_VALUE(NPe::g_MachinePairs, Machine) &&
MY_FIND_VALUE(NPe::g_SubSystems, SubSystem);
}
};
struct CSection
{
Byte Name[8];
// UInt32 VSize;
UInt32 Va;
UInt32 PSize;
UInt32 Pa;
UInt32 Flags;
// UInt16 NumRelocs;
void Parse(const Byte *p)
{
memcpy(Name, p, 8);
// VSize = Get32(p + 8);
Va = Get32(p + 12);
PSize = Get32(p + 16);
Pa = Get32(p + 20);
// NumRelocs = Get16(p + 32);
Flags = Get32(p + 36);
}
bool Check() const { return (PSize + Pa > Pa); }
void UpdateTotalSize(UInt32 &totalSize)
{
UInt32 t = Pa + PSize;
if (t > totalSize)
totalSize = t;
}
};
class CHandler:
public IInArchive,
public IInArchiveGetStream,
public CMyUnknownImp
{
UInt32 _totalSize;
CMyComPtr<IInStream> _stream;
CObjectVector<CSection> _items;
CHeader _h;
UInt64 _fileSize;
HRESULT Open2(IInStream *stream);
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
};
static const STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI4},
{ NULL, kpidPackSize, VT_UI4},
{ NULL, kpidCharacts, VT_BSTR},
{ NULL, kpidOffset, VT_UI4},
{ NULL, kpidVa, VT_UI8}
};
enum
{
kpidSubSystem
// , kpidImageBase
};
static const STATPROPSTG kArcProps[] =
{
{ NULL, kpidPhySize, VT_UI4},
// { NULL, kpidHeadersSize, VT_UI4},
{ NULL, kpidCpu, VT_BSTR},
{ L"Subsystem", kpidSubSystem, VT_BSTR},
// { L"Image Base", kpidImageBase, VT_UI8}
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps_WITH_NAME
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
switch(propID)
{
case kpidPhySize: prop = _totalSize; break;
case kpidCpu: PAIR_TO_PROP(NPe::g_MachinePairs, _h.Machine, prop); break;
case kpidSubSystem: PAIR_TO_PROP(NPe::g_SubSystems, _h.SubSystem, prop); break;
/*
case kpidImageBase: prop = _h.ImageBase; break;
case kpidAddressOfEntryPoint: prop = _h.AddressOfEntryPoint; break;
case kpidBaseOfCode: prop = _h.BaseOfCode; break;
*/
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
{
const CSection &item = _items[index];
switch(propID)
{
case kpidPath: StringToProp(NPe::GetName(item.Name), prop); break;
case kpidSize:
case kpidPackSize: prop = (UInt64)item.PSize; break;
case kpidOffset: prop = item.Pa; break;
case kpidVa: prop = item.Va; break;
case kpidCharacts: FLAGS_TO_PROP(NPe::g_SectFlags, item.Flags, prop); break;
}
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
HRESULT CHandler::Open2(IInStream *stream)
{
Byte h[kHeaderSize];
RINOK(ReadStream_FALSE(stream, h, kHeaderSize));
if (!_h.Parse(h))
return S_FALSE;
CByteBuffer buf;
UInt32 headerSize = NPe::kSectionSize * _h.NumSections;
buf.SetCapacity(headerSize);
RINOK(ReadStream_FALSE(stream, buf, headerSize));
_totalSize = kHeaderSize + headerSize;
for (UInt32 i = 0; i < headerSize; i += NPe::kSectionSize)
{
CSection sect;
sect.Parse(buf + i);
sect.Pa = _h.ConvertPa(sect.Pa);
_items.Add(sect);
sect.UpdateTotalSize(_totalSize);
if (!sect.Check())
return S_FALSE;
}
return stream->Seek(0, STREAM_SEEK_END, &_fileSize);
}
STDMETHODIMP CHandler::Open(IInStream *inStream,
const UInt64 * /* maxCheckStartPosition */,
IArchiveOpenCallback * /* openArchiveCallback */)
{
COM_TRY_BEGIN
Close();
try
{
if (Open2(inStream) != S_OK)
return S_FALSE;
_stream = inStream;
}
catch(...) { return S_FALSE; }
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
_stream.Release();
_items.Clear();
_totalSize = 0;
return S_OK;
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = _items.Size();
return S_OK;
}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode)
numItems = _items.Size();
if (numItems == 0)
return S_OK;
UInt64 totalSize = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
totalSize += _items[allFilesMode ? i : indices[i]].PSize;
extractCallback->SetTotal(totalSize);
UInt64 currentTotalSize = 0;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_stream);
for (i = 0; i < numItems; i++)
{
lps->InSize = lps->OutSize = currentTotalSize;
RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
UInt32 index = allFilesMode ? i : indices[i];
const CSection &item = _items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
currentTotalSize += item.PSize;
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
int res = NExtract::NOperationResult::kDataError;
if (item.Pa <= _fileSize)
{
if (testMode)
{
if (item.Pa + item.PSize <= _fileSize)
res = NExtract::NOperationResult::kOK;
}
else
{
RINOK(_stream->Seek(item.Pa, STREAM_SEEK_SET, NULL));
streamSpec->Init(item.PSize);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize == item.PSize)
res = NExtract::NOperationResult::kOK;
}
}
realOutStream.Release();
RINOK(extractCallback->SetOperationResult(res));
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
const CSection &item = _items[index];
return CreateLimitedInStream(_stream, item.Pa, item.PSize, stream);
COM_TRY_END
}
static IInArchive *CreateArc() { return new CHandler; }
static CArcInfo g_ArcInfo =
{ L"TE", L"te", 0, 0xCF, { 'V', 'Z' }, 2, false, CreateArc, 0 };
REGISTER_ARC(TE)
}
}

View File

@@ -5,6 +5,7 @@
#include "../../../C/7zCrc.h"
#include "../../../C/Alloc.h"
#include "../../../C/CpuArch.h"
#include "../../../C/Xz.h"
#include "Common/ComTry.h"
#include "Common/IntToString.h"
@@ -13,6 +14,7 @@
#include "Windows/PropVariantUtils.h"
#include "Windows/Time.h"
#include "../Common/CWrappers.h"
#include "../Common/LimitedStreams.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
@@ -26,6 +28,10 @@
namespace NArchive {
namespace NSquashfs {
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
static const UInt32 kNumFilesMax = (1 << 28);
static const unsigned kNumDirLevelsMax = (1 << 10);
@@ -62,13 +68,15 @@ static const UInt32 kSignature32_LZ = 0x71736873;
#define kMethod_ZLIB 1
#define kMethod_LZMA 2
#define kMethod_LZO 3
#define kMethod_XZ 4
static const char *k_Methods[] =
{
"Unknown",
"ZLIB",
"LZMA",
"LZO"
"LZO",
"XZ"
};
static const UInt32 kMetadataBlockSizeLog = 13;
@@ -860,6 +868,8 @@ class CHandler:
NCompress::NZlib::CDecoder *_zlibDecoderSpec;
CMyComPtr<ICompressCoder> _zlibDecoder;
CXzUnpacker _xz;
CByteBuffer _inputBuffer;
CDynBufSeqOutStream *_dynOutStreamSpec;
@@ -886,6 +896,11 @@ class CHandler:
public:
CHandler();
~CHandler()
{
XzUnpacker_Free(&_xz);
}
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
@@ -895,6 +910,8 @@ public:
CHandler::CHandler()
{
XzUnpacker_Construct(&_xz, &g_Alloc);
_limitedInStreamSpec = new CLimitedSequentialInStream;
_limitedInStream = _limitedInStreamSpec;
@@ -1104,33 +1121,16 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL));
}
if (method == kMethod_LZO)
if (method == kMethod_ZLIB)
{
if (_inputBuffer.GetCapacity() < inSize)
if (!_zlibDecoder)
{
_inputBuffer.Free();
_inputBuffer.SetCapacity(inSize);
_zlibDecoderSpec = new NCompress::NZlib::CDecoder();
_zlibDecoder = _zlibDecoderSpec;
}
RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize));
Byte *dest = outBuf;
if (!outBuf)
{
dest = _dynOutStreamSpec->GetBufPtrForWriting(outSizeMax);
if (!dest)
return E_OUTOFMEMORY;
}
SizeT destLen = outSizeMax, srcLen = inSize;
RINOK(LzoDecode(dest, &destLen, _inputBuffer, &srcLen));
if (inSize != srcLen)
RINOK(_zlibDecoder->Code(_limitedInStream, outStream, NULL, NULL, NULL));
if (inSize != _zlibDecoderSpec->GetInputProcessedSize())
return S_FALSE;
if (outBuf)
{
*outBufWasWritten = true;
*outBufWasWrittenSize = (UInt32)destLen;
}
else
_dynOutStreamSpec->UpdateSize(destLen);
}
else if (method == kMethod_LZMA)
{
@@ -1153,15 +1153,45 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
}
else
{
if (!_zlibDecoder)
if (_inputBuffer.GetCapacity() < inSize)
{
_zlibDecoderSpec = new NCompress::NZlib::CDecoder();
_zlibDecoder = _zlibDecoderSpec;
_inputBuffer.Free();
_inputBuffer.SetCapacity(inSize);
}
RINOK(_zlibDecoder->Code(_limitedInStream, outStream, NULL, NULL, NULL));
if (inSize != _zlibDecoderSpec->GetInputProcessedSize())
RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize));
Byte *dest = outBuf;
if (!outBuf)
{
dest = _dynOutStreamSpec->GetBufPtrForWriting(outSizeMax);
if (!dest)
return E_OUTOFMEMORY;
}
SizeT destLen = outSizeMax, srcLen = inSize;
if (method == kMethod_LZO)
{
RINOK(LzoDecode(dest, &destLen, _inputBuffer, &srcLen));
}
else
{
ECoderStatus status;
XzUnpacker_Init(&_xz);
SRes res = XzUnpacker_Code(&_xz, dest, &destLen, _inputBuffer, &srcLen, LZMA_FINISH_END, &status);
if (res != 0)
return SResToHRESULT(res);
if (status != CODER_STATUS_NEEDS_MORE_INPUT || !XzUnpacker_IsStreamWasFinished(&_xz))
return S_FALSE;
}
if (inSize != srcLen)
return S_FALSE;
if (outBuf)
{
*outBufWasWritten = true;
*outBufWasWrittenSize = (UInt32)destLen;
}
else
_dynOutStreamSpec->UpdateSize(destLen);
}
return S_OK;
}
@@ -1418,6 +1448,7 @@ HRESULT CHandler::Open2(IInStream *inStream)
case kMethod_ZLIB:
case kMethod_LZMA:
case kMethod_LZO:
case kMethod_XZ:
break;
default:
return E_NOTIMPL;
@@ -2072,16 +2103,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (inStream)
{
HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
if (hres != S_OK && hres != S_FALSE)
if (hres == S_OK)
{
if (copyCoderSpec->TotalSize == unpackSize)
res = NExtract::NOperationResult::kOK;
}
else if (hres == E_NOTIMPL)
{
res = NExtract::NOperationResult::kUnSupportedMethod;
}
else if(hres != S_FALSE)
{
RINOK(hres);
}
if (copyCoderSpec->TotalSize == unpackSize && hres == S_OK)
res = NExtract::NOperationResult::kOK;
else
{
res = res;
}
}
}
}

View File

@@ -21,8 +21,7 @@
#include "../Compress/ZlibEncoder.h"
#include "Common/DummyOutStream.h"
#include "DeflateProps.h"
#include "Common/HandlerOut.h"
using namespace NWindows;
@@ -69,7 +68,7 @@ class CHandler:
CMyComPtr<ISequentialInStream> _seqStream;
CMyComPtr<IInStream> _stream;
CDeflateProps _method;
CSingleMethodProps _props;
public:
MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
@@ -206,7 +205,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
static HRESULT UpdateArchive(ISequentialOutStream *outStream,
UInt64 size, CDeflateProps &deflateProps,
UInt64 size, const CSingleMethodProps &props,
IArchiveUpdateCallback *updateCallback)
{
UInt64 complexity = 0;
@@ -234,7 +233,7 @@ static HRESULT UpdateArchive(ISequentialOutStream *outStream,
NCompress::NZlib::CEncoder *encoderSpec = new NCompress::NZlib::CEncoder;
CMyComPtr<ICompressCoder> encoder = encoderSpec;
encoderSpec->Create();
RINOK(deflateProps.SetCoderProperties(encoderSpec->DeflateEncoderSpec));
RINOK(props.SetCoderProps(encoderSpec->DeflateEncoderSpec, NULL));
RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, progress));
if (encoderSpec->GetInputProcessedSize() + kHeaderSize != size)
return E_INVALIDARG;
@@ -284,7 +283,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
}
return UpdateArchive(outStream, size, _method, updateCallback);
return UpdateArchive(outStream, size, _props, updateCallback);
}
if (indexInArchive != 0)
@@ -304,7 +303,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
return _method.SetProperties(names, values, numProps);
return _props.SetProperties(names, values, numProps);
}
static IInArchive *CreateArc() { return new CHandler; }

View File

@@ -64,6 +64,8 @@ HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &
{
item.HeaderPos = _phySize;
RINOK(ReadItem(stream, filled, item, _errorMessage));
if (filled && item.IsSparse())
_isSparse = true;
_phySize += item.HeaderSize;
_headersSize += item.HeaderSize;
return S_OK;
@@ -87,7 +89,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
break;
_items.Add(item);
RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &_phySize));
RINOK(stream->Seek(item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize));
if (_phySize > endPos)
{
_errorMessage = kUnexpectedEnd;
@@ -162,6 +164,7 @@ STDMETHODIMP CHandler::Close()
_headersSize = 0;
_curIndex = 0;
_latestIsRead = false;
_isSparse = false;
_items.Clear();
_seqStream.Release();
_stream.Release();
@@ -186,7 +189,7 @@ HRESULT CHandler::SkipTo(UInt32 index)
{
if (_latestIsRead)
{
UInt64 packSize = _latestItem.GetPackSize();
UInt64 packSize = _latestItem.GetPackSizeAligned();
RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL));
_phySize += copyCoderSpec->TotalSize;
if (copyCoderSpec->TotalSize != packSize)
@@ -241,12 +244,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break;
case kpidIsDir: prop = item->IsDir(); break;
case kpidSize: prop = item->GetUnpackSize(); break;
case kpidPackSize: prop = item->GetPackSize(); break;
case kpidPackSize: prop = item->GetPackSizeAligned(); break;
case kpidMTime:
if (item->MTime != 0)
{
FILETIME ft;
NTime::UnixTimeToFileTime(item->MTime, ft);
if (NTime::UnixTime64ToFileTime(item->MTime, ft))
prop = ft;
}
break;
@@ -319,7 +322,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
UInt64 unpackSize = item->GetUnpackSize();
totalSize += unpackSize;
totalPackSize += item->GetPackSize();
totalPackSize += item->GetPackSizeAligned();
if (item->IsDir())
{
RINOK(extractCallback->PrepareOperation(askMode));
@@ -340,6 +343,11 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
realOutStream.Release();
outStreamSpec->Init(skipMode ? 0 : unpackSize, true);
Int32 opRes = NExtract::NOperationResult::kOK;
if (item->IsSparse())
opRes = NExtract::NOperationResult::kUnSupportedMethod;
else
{
if (item->IsLink())
{
RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length()));
@@ -350,18 +358,19 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL));
}
streamSpec->Init(item->GetPackSize());
streamSpec->Init(item->GetPackSizeAligned());
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
}
if (outStreamSpec->GetRem() != 0)
opRes = NExtract::NOperationResult::kDataError;
}
if (seqMode)
{
_latestIsRead = false;
_curIndex++;
}
outStreamSpec->ReleaseStream();
RINOK(extractCallback->SetOperationResult(outStreamSpec->GetRem() == 0 ?
NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kDataError));
RINOK(extractCallback->SetOperationResult(opRes));
}
return S_OK;
COM_TRY_END
@@ -371,6 +380,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
const CItemEx &item = _items[index];
if (item.IsSparse())
return E_NOTIMPL;
if (item.IsLink())
{
CBufInStream *streamSpec = new CBufInStream;
@@ -379,7 +390,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
*stream = streamTemp.Detach();
return S_OK;
}
return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream);
return CreateLimitedInStream(_stream, item.GetDataPosition(), item.PackSize, stream);
COM_TRY_END
}

View File

@@ -32,6 +32,7 @@ class CHandler:
UInt64 _headersSize;
bool _phySizeDefined;
AString _errorMessage;
bool _isSparse;
NCompress::CCopyCoder *copyCoderSpec;
CMyComPtr<ICompressCoder> copyCoder;

View File

@@ -37,7 +37,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
IArchiveUpdateCallback *callback)
{
COM_TRY_BEGIN
if ((_stream && !_errorMessage.IsEmpty()) || _seqStream)
if ((_stream && (!_errorMessage.IsEmpty() || _isSparse)) || _seqStream)
return E_NOTIMPL;
CObjectVector<CUpdateItem> updateItems;
for (UInt32 i = 0; i < numItems; i++)
@@ -81,11 +81,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidMTime, &prop));
if (prop.vt == VT_EMPTY)
ui.Time = 0;
ui.MTime = 0;
else if (prop.vt != VT_FILETIME)
return E_INVALIDARG;
else if (!NTime::FileTimeToUnixTime(prop.filetime, ui.Time))
ui.Time = 0;
else
ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime);
}
{
NCOM::CPropVariant prop;

View File

@@ -84,6 +84,7 @@ namespace NFileHeader
Each file name is terminated by a null + an additional null after
the last file name. */
const char kSparse = 'S';
}
// Further link types may be defined later.

View File

@@ -63,6 +63,31 @@ static void ReadString(const char *s, int size, AString &result)
result = temp;
}
static bool ParseInt64(const char *p, Int64 &val)
{
UInt32 h = GetBe32(p);
val = GetBe64(p + 4);
if (h == (UInt32)1 << 31)
return ((val >> 63) & 1) == 0;
if (h == (UInt32)(Int32)-1)
return ((val >> 63) & 1) != 0;
UInt64 uv;
bool res = OctalToNumber(p, 12, uv);
val = uv;
return res;
}
static bool ParseSize(const char *p, UInt64 &val)
{
if (GetBe32(p) == (UInt32)1 << 31)
{
// GNU extension
val = GetBe64(p + 4);
return ((val >> 63) & 1) == 0;
}
return OctalToNumber(p, 12, val);
}
static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error)
{
char buf[NFileHeader::kRecordSize];
@@ -105,17 +130,10 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8;
if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8;
if (GetBe32(p) == (UInt32)1 << 31)
{
// GNU extension
item.Size = GetBe64(p + 4);
}
else
{
RIF(OctalToNumber(p, 12, item.Size));
}
RIF(ParseSize(p, item.PackSize));
item.Size = item.PackSize;
p += 12;
RIF(OctalToNumber32(p, 12, item.MTime)); p += 12;
RIF(ParseInt64(p, item.MTime)); p += 12;
UInt32 checkSum;
RIF(OctalToNumber32(p, 8, checkSum));
@@ -141,7 +159,36 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
item.Name = prefix + AString('/') + item.Name;
if (item.LinkFlag == NFileHeader::NLinkFlag::kLink)
{
item.PackSize = 0;
item.Size = 0;
}
else if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse)
{
if (buf[482] != 0)
return S_FALSE;
RIF(ParseSize(buf + 483, item.Size));
p = buf + 386;
UInt64 min = 0;
for (int i = 0; i < 4; i++, p += 24)
{
if (GetBe32(p) == 0)
break;
CSparseBlock sb;
RIF(ParseSize(p, sb.Offset));
RIF(ParseSize(p + 12, sb.Size));
item.SparseBlocks.Add(sb);
if (sb.Offset < min || sb.Offset > item.Size)
return S_FALSE;
if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0)
return S_FALSE;
min = sb.Offset + sb.Size;
if (min < sb.Offset)
return S_FALSE;
}
if (min > item.Size)
return S_FALSE;
}
UInt32 checkSumReal = 0;
for (int i = 0; i < NFileHeader::kRecordSize; i++)
@@ -178,26 +225,39 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, AStri
if (item.Name.Compare(NFileHeader::kLongLink) != 0 &&
item.Name.Compare(NFileHeader::kLongLink2) != 0)
return S_FALSE;
if (item.Size > (1 << 14))
if (item.PackSize > (1 << 14))
return S_FALSE;
int packSize = (int)item.GetPackSize();
int packSize = (int)item.GetPackSizeAligned();
char *buf = name->GetBuffer(packSize);
RINOK(ReadStream_FALSE(stream, buf, packSize));
item.HeaderSize += packSize;
buf[(size_t)item.Size] = '\0';
buf[(size_t)item.PackSize] = '\0';
name->ReleaseBuffer();
continue;
}
if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X')
switch (item.LinkFlag)
{
case 'g':
case 'x':
case 'X':
{
// pax Extended Header
break;
}
else if (item.LinkFlag == NFileHeader::NLinkFlag::kDumpDir)
case NFileHeader::NLinkFlag::kDumpDir:
{
break;
// GNU Extensions to the Archive Format
}
else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))
case NFileHeader::NLinkFlag::kSparse:
{
break;
// GNU Extensions to the Archive Format
}
default:
if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))
return S_FALSE;
}
if (flagL) item.Name = nameL;
if (flagK) item.LinkName = nameK;
return S_OK;

View File

@@ -10,15 +10,22 @@
namespace NArchive {
namespace NTar {
struct CSparseBlock
{
UInt64 Offset;
UInt64 Size;
};
struct CItem
{
AString Name;
UInt64 PackSize;
UInt64 Size;
Int64 MTime;
UInt32 Mode;
UInt32 UID;
UInt32 GID;
UInt32 MTime;
UInt32 DeviceMajor;
UInt32 DeviceMinor;
@@ -31,7 +38,10 @@ struct CItem
bool DeviceMajorDefined;
bool DeviceMinorDefined;
CRecordVector<CSparseBlock> SparseBlocks;
bool IsLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymbolicLink && (Size == 0); }
bool IsSparse() const { return LinkFlag == NFileHeader::NLinkFlag::kSparse; }
UInt64 GetUnpackSize() const { return IsLink() ? LinkName.Length() : Size; }
bool IsDir() const
@@ -56,15 +66,16 @@ struct CItem
return true;
}
UInt64 GetPackSize() const { return (Size + 0x1FF) & (~((UInt64)0x1FF)); }
UInt64 GetPackSizeAligned() const { return (PackSize + 0x1FF) & (~((UInt64)0x1FF)); }
};
struct CItemEx: public CItem
{
UInt64 HeaderPos;
unsigned HeaderSize;
UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }
UInt64 GetFullSize() const { return HeaderSize + Size; }
UInt64 GetFullSize() const { return HeaderSize + PackSize; }
};
}}

View File

@@ -47,7 +47,7 @@ static bool MakeOctalString8(char *s, UInt32 value)
if (tempString.Length() >= kMaxSize)
return false;
int numSpaces = kMaxSize - (tempString.Length() + 1);
for(int i = 0; i < numSpaces; i++)
for (int i = 0; i < numSpaces; i++)
s[i] = ' ';
MyStringCopy(s + numSpaces, (const char *)tempString);
return true;
@@ -67,11 +67,23 @@ static void MakeOctalString12(char *s, UInt64 value)
return;
}
int numSpaces = kMaxSize - tempString.Length();
for(int i = 0; i < numSpaces; i++)
for (int i = 0; i < numSpaces; i++)
s[i] = ' ';
memmove(s + numSpaces, (const char *)tempString, tempString.Length());
}
static void MakeOctalString12_From_Int64(char *s, Int64 value)
{
if (value >= 0)
{
MakeOctalString12(s, value);
return;
}
s[0] = s[1] = s[2] = s[3] = (char)(Byte)0xFF;
for (int i = 0; i < 8; i++, value <<= 8)
s[4 + i] = (char)(value >> 56);
}
static bool CopyString(char *dest, const AString &src, int maxSize)
{
if (src.Length() >= maxSize)
@@ -100,8 +112,8 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item)
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); cur += 8;
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID)); cur += 8;
MakeOctalString12(cur, item.Size); cur += 12;
MakeOctalString12(cur, item.MTime); cur += 12;
MakeOctalString12(cur, item.PackSize); cur += 12;
MakeOctalString12_From_Int64(cur, item.MTime); cur += 12;
memmove(cur, NFileHeader::kCheckSumBlanks, 8);
cur += 8;
@@ -130,7 +142,7 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item)
UInt32 checkSumReal = 0;
for(i = 0; i < NFileHeader::kRecordSize; i++)
for (i = 0; i < NFileHeader::kRecordSize; i++)
checkSumReal += Byte(record[i]);
RETURN_IF_NOT_TRUE(MakeOctalString8(record + 148, checkSumReal));
@@ -146,7 +158,7 @@ HRESULT COutArchive::WriteHeader(const CItem &item)
CItem modifiedItem = item;
int nameStreamSize = nameSize + 1;
modifiedItem.Size = nameStreamSize;
modifiedItem.PackSize = nameStreamSize;
modifiedItem.LinkFlag = 'L';
modifiedItem.Name = NFileHeader::kLongLink;
modifiedItem.LinkName.Empty();

View File

@@ -48,7 +48,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
complexity = 0;
for(i = 0; i < updateItems.Size(); i++)
for (i = 0; i < updateItems.Size(); i++)
{
lps->InSize = lps->OutSize = complexity;
RINOK(lps->SetCur());
@@ -64,14 +64,14 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
if (ui.IsDir)
{
item.LinkFlag = NFileHeader::NLinkFlag::kDirectory;
item.Size = 0;
item.PackSize = 0;
}
else
{
item.LinkFlag = NFileHeader::NLinkFlag::kNormal;
item.Size = ui.Size;
item.PackSize = ui.Size;
}
item.MTime = ui.Time;
item.MTime = ui.MTime;
item.DeviceMajorDefined = false;
item.DeviceMinorDefined = false;
item.UID = 0;
@@ -83,12 +83,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
if (ui.NewData)
{
item.Size = ui.Size;
if (item.Size == (UInt64)(Int64)-1)
item.PackSize = ui.Size;
if (ui.Size == (UInt64)(Int64)-1)
return E_INVALIDARG;
}
else
item.Size = inputItems[ui.IndexInArchive].Size;
item.PackSize = inputItems[ui.IndexInArchive].PackSize;
if (ui.NewData)
{
@@ -101,9 +101,9 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
if (!ui.IsDir)
{
RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != item.Size)
if (copyCoderSpec->TotalSize != item.PackSize)
return E_FAIL;
RINOK(outArchive.FillDataResidual(item.Size));
RINOK(outArchive.FillDataResidual(item.PackSize));
}
}
complexity += ui.Size;
@@ -117,7 +117,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
{
RINOK(outArchive.WriteHeader(item));
RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL));
size = existItem.Size;
size = existItem.PackSize;
}
else
{
@@ -129,10 +129,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != size)
return E_FAIL;
RINOK(outArchive.FillDataResidual(existItem.Size));
RINOK(outArchive.FillDataResidual(existItem.PackSize));
complexity += size;
}
}
lps->InSize = lps->OutSize = complexity;
RINOK(lps->SetCur());
return outArchive.WriteFinishHeader();
}

View File

@@ -13,15 +13,15 @@ struct CUpdateItem
{
int IndexInArchive;
int IndexInClient;
UInt32 Time;
UInt32 Mode;
Int64 MTime;
UInt64 Size;
AString Name;
AString User;
AString Group;
UInt32 Mode;
bool NewData;
bool NewProps;
bool IsDir;
AString Name;
AString User;
AString Group;
};
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,

View File

@@ -574,34 +574,33 @@ HRESULT CInArchive::Open2()
{
Clear();
// Some UDFs contain additional pad zeros (2 KB).
// Seek to STREAM_SEEK_END for direct DVD reading can return 8 KB more, so we check last 16 KB.
// And when we read last block, result read size can be smaller than required size.
UInt64 fileSize;
RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize));
// Some UDFs contain additional 2 KB of zeros, so we also check 12, corrected to 11.
const int kSecLogSizeMax = 12;
Byte buf[1 << kSecLogSizeMax];
Byte kSizesLog[] = { 11, 8, 12 };
for (int i = 0;; i++)
const size_t kBufSize = 1 << 14;
Byte buf[kBufSize];
size_t readSize = (fileSize < kBufSize) ? (size_t)fileSize : kBufSize;
RINOK(_stream->Seek(fileSize - readSize, STREAM_SEEK_SET, NULL));
RINOK(ReadStream(_stream, buf, &readSize));
size_t i = readSize;
for (;;)
{
if (i == sizeof(kSizesLog) / sizeof(kSizesLog[0]))
const size_t kSecSizeMin = 1 << 8;
if (i < kSecSizeMin)
return S_FALSE;
SecLogSize = kSizesLog[i];
Int32 bufSize = 1 << SecLogSize;
if (bufSize > fileSize)
return S_FALSE;
RINOK(_stream->Seek(-bufSize, STREAM_SEEK_END, NULL));
RINOK(ReadStream_FALSE(_stream, buf, bufSize));
i -= kSecSizeMin;
SecLogSize = (readSize - i < ((size_t)1 << 11)) ? 8 : 11;
CTag tag;
if (tag.Parse(buf, bufSize) == S_OK)
if (tag.Parse(buf + i, (1 << SecLogSize)) == S_OK)
if (tag.Id == DESC_TYPE_AnchorVolPtr)
break;
}
if (SecLogSize == 12)
SecLogSize = 11;
CExtent extentVDS;
extentVDS.Parse(buf + 16);
extentVDS.Parse(buf + i + 16);
for (UInt32 location = extentVDS.Pos; ; location++)
{

1935
CPP/7zip/Archive/UefiHandler.cpp Executable file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -465,7 +465,8 @@ static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream,
RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
}
lps->InSize = lps->OutSize = complexity;
RINOK(lps->SetCur());
CUpdateItem ri;
FILETIME ft;

View File

@@ -8,6 +8,7 @@
#include "../../Common/ComTry.h"
#include "../../Common/IntToString.h"
#include "../../Common/StringConvert.h"
#include "../ICoder.h"
@@ -40,13 +41,15 @@ namespace NXz {
struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;
static const wchar_t *k_LZMA2_Name = L"LZMA2";
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
#ifndef EXTRACT_ONLY
public IOutArchive,
public ISetProperties,
public COutHandler,
public CMultiMethodProps,
#endif
public CMyUnknownImp
{
@@ -62,12 +65,12 @@ class CHandler:
CMyComPtr<IInStream> _stream;
CMyComPtr<ISequentialInStream> _seqStream;
UInt32 _crcSize;
UInt32 _filterId;
void Init()
{
_crcSize = 4;
COutHandler::Init();
_filterId = 0;
CMultiMethodProps::Init();
}
HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback);
@@ -98,14 +101,14 @@ CHandler::CHandler()
Init();
}
STATPROPSTG kProps[] =
static STATPROPSTG const kProps[] =
{
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidPackSize, VT_UI8},
{ NULL, kpidMethod, VT_BSTR}
};
STATPROPSTG kArcProps[] =
static STATPROPSTG const kArcProps[] =
{
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidNumBlocks, VT_UI4}
@@ -160,11 +163,11 @@ struct CMethodNamePair
const char *Name;
};
static CMethodNamePair g_NamePairs[] =
static const CMethodNamePair g_NamePairs[] =
{
{ XZ_ID_Subblock, "SB" },
{ XZ_ID_Delta, "Delta" },
{ XZ_ID_X86, "x86" },
{ XZ_ID_X86, "BCJ" },
{ XZ_ID_PPC, "PPC" },
{ XZ_ID_IA64, "IA64" },
{ XZ_ID_ARM, "ARM" },
@@ -439,7 +442,10 @@ struct CXzUnpackerCPP
Byte *InBuf;
Byte *OutBuf;
CXzUnpacker p;
CXzUnpackerCPP(): InBuf(0), OutBuf(0) {}
CXzUnpackerCPP(): InBuf(0), OutBuf(0)
{
XzUnpacker_Construct(&p, &g_Alloc);
}
~CXzUnpackerCPP()
{
XzUnpacker_Free(&p);
@@ -483,7 +489,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CCompressProgressWrap progressWrap(progress);
SRes res;
SRes res = S_OK;
const UInt32 kInBufSize = 1 << 15;
const UInt32 kOutBufSize = 1 << 21;
@@ -492,8 +498,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt32 inSize = 0;
UInt32 outPos = 0;
CXzUnpackerCPP xzu;
res = XzUnpacker_Create(&xzu.p, &g_Alloc);
if (res == SZ_OK)
XzUnpacker_Init(&xzu.p);
{
xzu.InBuf = (Byte *)MyAlloc(kInBufSize);
xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);
@@ -534,6 +539,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
outPos = 0;
}
RINOK(lps->SetCur());
if (finished)
{
_packSize = lps->InSize;
@@ -553,7 +559,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
break;
}
RINOK(lps->SetCur());
}
Int32 opRes;
@@ -573,8 +578,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return SResToHRESULT(res);
}
realOutStream.Release();
RINOK(extractCallback->SetOperationResult(opRes));
return S_OK;
return extractCallback->SetOperationResult(opRes);
COM_TRY_END
}
@@ -618,9 +622,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
if (IntToBool(newData))
{
{
UInt64 size;
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
if (prop.vt != VT_UI8)
@@ -632,22 +636,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CLzma2EncProps lzma2Props;
Lzma2EncProps_Init(&lzma2Props);
lzma2Props.lzmaProps.level = _level;
lzma2Props.lzmaProps.level = GetLevel();
CMyComPtr<ISequentialInStream> fileInStream;
RINOK(updateCallback->GetStream(0, &fileInStream));
CSeqInStreamWrap seqInStream(fileInStream);
{
NCOM::CPropVariant prop = (UInt64)size;
RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props));
}
for (int i = 0; i < _methods.Size(); i++)
{
COneMethodInfo &m = _methods[i];
SetCompressionMethod2(m
SetGlobalLevelAndThreads(m
#ifndef _7ZIP_ST
, _numThreads
#endif
);
if (m.IsLzma())
{
for (int j = 0; j < m.Props.Size(); j++)
{
@@ -666,7 +674,40 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
lps->Init(updateCallback, true);
CCompressProgressWrap progressWrap(progress);
SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &lzma2Props, False, &progressWrap.p);
CXzProps xzProps;
CXzFilterProps filter;
XzProps_Init(&xzProps);
XzFilterProps_Init(&filter);
xzProps.lzma2Props = &lzma2Props;
xzProps.filterProps = (_filterId != 0 ? &filter : NULL);
switch (_crcSize)
{
case 0: xzProps.checkId = XZ_CHECK_NO; break;
case 4: xzProps.checkId = XZ_CHECK_CRC32; break;
case 8: xzProps.checkId = XZ_CHECK_CRC64; break;
case 32: xzProps.checkId = XZ_CHECK_SHA256; break;
default: return E_INVALIDARG;
}
filter.id = _filterId;
if (_filterId == XZ_ID_Delta)
{
bool deltaDefined = false;
for (int j = 0; j < _filterMethod.Props.Size(); j++)
{
const CProp &prop = _filterMethod.Props[j];
if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)
{
UInt32 delta = (UInt32)prop.Value.ulVal;
if (delta < 1 || delta > 256)
return E_INVALIDARG;
filter.delta = delta;
deltaDefined = true;
}
}
if (!deltaDefined)
return E_INVALIDARG;
}
SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &xzProps, &progressWrap.p);
if (res == SZ_OK)
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
return SResToHRESULT(res);
@@ -678,14 +719,46 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return NCompress::CopyStream(_stream, outStream, 0);
}
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
COM_TRY_BEGIN
BeforeSetProperty();
Init();
for (int i = 0; i < numProps; i++)
{
RINOK(SetProperty(names[i], values[i]));
}
if (!_filterMethod.MethodName.IsEmpty())
{
int k;
for (k = 0; k < ARRAY_SIZE(g_NamePairs); k++)
{
const CMethodNamePair &pair = g_NamePairs[k];
UString m = GetUnicodeString(pair.Name);
if (_filterMethod.MethodName.CompareNoCase(m) == 0)
{
_filterId = pair.Id;
break;
}
}
if (k == ARRAY_SIZE(g_NamePairs))
return E_INVALIDARG;
}
int numEmptyMethods = GetNumEmptyMethods();
_methods.Delete(0, numEmptyMethods);
if (_methods.Size() > 1)
return E_INVALIDARG;
if (_methods.Size() == 1)
{
UString &methodName = _methods[0].MethodName;
if (methodName.IsEmpty())
methodName = k_LZMA2_Name;
else if (methodName.CompareNoCase(k_LZMA2_Name) != 0)
return E_INVALIDARG;
}
return S_OK;
COM_TRY_END
}

View File

@@ -33,6 +33,7 @@ static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize;
class CLzmaEncoder:
public ICompressCoder,
public ICompressSetCoderProperties,
public CMyUnknownImp
{
NCompress::NLzma::CEncoder *EncoderSpec;
@@ -41,12 +42,12 @@ class CLzmaEncoder:
public:
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
MY_UNKNOWN_IMP
MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
};
HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
STDMETHODIMP CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
{
if (!Encoder)
{
@@ -67,7 +68,7 @@ HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIAN
return S_OK;
}
HRESULT CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
{
RINOK(WriteStream(outStream, Header, kLzmaHeaderSize));
@@ -210,52 +211,12 @@ HRESULT CAddCommon::Compress(
_compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_LZMA;
CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder();
_compressEncoder = _lzmaEncoder;
NWindows::NCOM::CPropVariant props[] =
{
#ifndef _7ZIP_ST
_options.NumThreads,
#endif
_options.Algo,
_options.DicSize,
_options.NumFastBytes,
const_cast<BSTR>((const wchar_t *)_options.MatchFinder),
_options.NumMatchFinderCycles
};
PROPID propIDs[] =
{
#ifndef _7ZIP_ST
NCoderPropID::kNumThreads,
#endif
NCoderPropID::kAlgorithm,
NCoderPropID::kDictionarySize,
NCoderPropID::kNumFastBytes,
NCoderPropID::kMatchFinder,
NCoderPropID::kMatchFinderCycles
};
int numProps = sizeof(propIDs) / sizeof(propIDs[0]);
if (!_options.NumMatchFinderCyclesDefined)
numProps--;
RINOK(_lzmaEncoder->SetCoderProperties(propIDs, props, numProps));
}
else if (method == NFileHeader::NCompressionMethod::kPPMd)
{
_compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd;
NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();
_compressEncoder = encoder;
NWindows::NCOM::CPropVariant props[] =
{
_options.Algo,
_options.MemSize,
_options.Order
};
PROPID propIDs[] =
{
NCoderPropID::kAlgorithm,
NCoderPropID::kUsedMemorySize,
NCoderPropID::kOrder
};
RINOK(encoder->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));
}
else
{
@@ -282,55 +243,19 @@ HRESULT CAddCommon::Compress(
if (method == NFileHeader::NCompressionMethod::kDeflated ||
method == NFileHeader::NCompressionMethod::kDeflated64)
{
NWindows::NCOM::CPropVariant props[] =
{
_options.Algo,
_options.NumPasses,
_options.NumFastBytes,
_options.NumMatchFinderCycles
};
PROPID propIDs[] =
{
NCoderPropID::kAlgorithm,
NCoderPropID::kNumPasses,
NCoderPropID::kNumFastBytes,
NCoderPropID::kMatchFinderCycles
};
int numProps = sizeof(propIDs) / sizeof(propIDs[0]);
if (!_options.NumMatchFinderCyclesDefined)
numProps--;
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
_compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);
if (setCoderProperties)
{
RINOK(setCoderProperties->SetCoderProperties(propIDs, props, numProps));
}
}
else if (method == NFileHeader::NCompressionMethod::kBZip2)
{
NWindows::NCOM::CPropVariant props[] =
{
_options.DicSize,
_options.NumPasses
#ifndef _7ZIP_ST
, _options.NumThreads
#endif
};
PROPID propIDs[] =
{
NCoderPropID::kDictionarySize,
NCoderPropID::kNumPasses
#ifndef _7ZIP_ST
, NCoderPropID::kNumThreads
#endif
};
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
_compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);
if (setCoderProperties)
{
RINOK(setCoderProperties->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));
}
}
{
CMyComPtr<ICompressSetCoderProperties> setCoderProps;
_compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps);
if (setCoderProps)
{
RINOK(_options.MethodInfo.SetCoderProps(setCoderProps,
_options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL));
}
}
}
CMyComPtr<ISequentialOutStream> outStreamNew;

View File

@@ -5,36 +5,54 @@
#include "Common/MyString.h"
#ifndef _7ZIP_ST
#include "../../../Windows/System.h"
#endif
#include "../Common/HandlerOut.h"
namespace NArchive {
namespace NZip {
struct CCompressionMethodMode
struct CBaseProps
{
CRecordVector<Byte> MethodSequence;
UString MatchFinder;
UInt32 Algo;
UInt32 NumPasses;
UInt32 NumFastBytes;
bool NumMatchFinderCyclesDefined;
UInt32 NumMatchFinderCycles;
UInt32 DicSize;
UInt32 MemSize;
UInt32 Order;
CMethodProps MethodInfo;
Int32 Level;
#ifndef _7ZIP_ST
UInt32 NumThreads;
bool NumThreadsWasChanged;
#endif
bool PasswordIsDefined;
AString Password;
bool IsAesMode;
Byte AesKeyMode;
CCompressionMethodMode():
NumMatchFinderCyclesDefined(false),
PasswordIsDefined(false),
IsAesMode(false),
AesKeyMode(3)
{}
void Init()
{
MethodInfo.Clear();
Level = -1;
#ifndef _7ZIP_ST
NumThreads = NWindows::NSystem::GetNumberOfProcessors();;
NumThreadsWasChanged = false;
#endif
IsAesMode = false;
AesKeyMode = 3;
}
};
struct CCompressionMethodMode: public CBaseProps
{
CRecordVector<Byte> MethodSequence;
bool PasswordIsDefined;
AString Password;
UInt64 _dataSizeReduce;
bool _dataSizeReduceDefined;
CCompressionMethodMode(): PasswordIsDefined(false)
{
_dataSizeReduceDefined = false;
_dataSizeReduce = 0;
}
};
}}

View File

@@ -107,7 +107,7 @@ static struct CStrongCryptoPair
{ NStrongCryptoFlags::kRC4, "RC4" }
};
static STATPROPSTG kProps[] =
static const STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
@@ -117,6 +117,7 @@ static STATPROPSTG kProps[] =
{ NULL, kpidCTime, VT_FILETIME},
{ NULL, kpidATime, VT_FILETIME},
{ NULL, kpidAttrib, VT_UI4},
// { NULL, kpidPosixAttrib, VT_UI4},
{ NULL, kpidEncrypted, VT_BOOL},
{ NULL, kpidComment, VT_BSTR},
{ NULL, kpidCRC, VT_UI4},
@@ -125,7 +126,7 @@ static STATPROPSTG kProps[] =
{ NULL, kpidUnpackVer, VT_UI4}
};
static STATPROPSTG kArcProps[] =
static const STATPROPSTG kArcProps[] =
{
{ NULL, kpidBit64, VT_BOOL},
{ NULL, kpidComment, VT_BSTR},
@@ -135,7 +136,7 @@ static STATPROPSTG kArcProps[] =
CHandler::CHandler()
{
InitMethodProperties();
InitMethodProps();
}
static AString BytesToString(const CByteBuffer &data)
@@ -165,6 +166,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidComment: prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break;
case kpidPhySize: prop = m_Archive.ArcInfo.GetPhySize(); break;
case kpidOffset: if (m_Archive.ArcInfo.StartPosition != 0) prop = m_Archive.ArcInfo.StartPosition; break;
case kpidError: if (!m_Archive.IsOkHeaders) prop = "Incorrect headers"; break;
}
prop.Detach(value);
COM_TRY_END
@@ -194,7 +196,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
UInt32 unixTime;
if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft))
prop = (UInt32)NFileTimeType::kWindows;
else if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime))
else if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime))
prop = (UInt32)NFileTimeType::kUnix;
else
prop = (UInt32)NFileTimeType::kDOS;
@@ -220,7 +222,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc))
{
UInt32 unixTime;
if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime))
if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime))
NTime::UnixTimeToFileTime(unixTime, utc);
else
{
@@ -233,7 +235,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = utc;
break;
}
case kpidAttrib: prop = item.GetWinAttributes(); break;
case kpidAttrib: prop = item.GetWinAttrib(); break;
case kpidPosixAttrib:
{
UInt32 attrib;
if (item.GetPosixAttrib(attrib))
prop = attrib;
break;
}
case kpidEncrypted: prop = item.IsEncrypted(); break;
case kpidComment: prop = item.GetUnicodeString(BytesToString(item.Comment)); break;
case kpidCRC: if (item.IsThereCrc()) prop = item.FileCRC; break;
@@ -435,7 +444,10 @@ public:
ISequentialOutStream *realOutStream,
IArchiveExtractCallback *extractCallback,
ICompressProgressInfo *compressProgress,
UInt32 numThreads, Int32 &res);
#ifndef _7ZIP_ST
UInt32 numThreads,
#endif
Int32 &res);
};
HRESULT CZipDecoder::Decode(
@@ -444,7 +456,10 @@ HRESULT CZipDecoder::Decode(
ISequentialOutStream *realOutStream,
IArchiveExtractCallback *extractCallback,
ICompressProgressInfo *compressProgress,
UInt32 numThreads, Int32 &res)
#ifndef _7ZIP_ST
UInt32 numThreads,
#endif
Int32 &res)
{
res = NExtract::NOperationResult::kDataError;
CInStreamReleaser inStreamReleaser;
@@ -805,15 +820,22 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->PrepareOperation(askMode));
Int32 res;
RINOK(myDecoder.Decode(
HRESULT hres = myDecoder.Decode(
EXTERNAL_CODECS_VARS
m_Archive, item, realOutStream, extractCallback,
progress, _numThreads, res));
progress,
#ifndef _7ZIP_ST
_props.NumThreads,
#endif
res);
RINOK(hres);
realOutStream.Release();
RINOK(extractCallback->SetOperationResult(res))
}
return S_OK;
lps->InSize = currentTotalPacked;
lps->OutSize = currentTotalUnPacked;
return lps->SetCur();
COM_TRY_END
}

View File

@@ -12,10 +12,6 @@
#include "ZipIn.h"
#include "ZipCompressionMode.h"
#ifndef _7ZIP_ST
#include "../../../Windows/System.h"
#endif
namespace NArchive {
namespace NZip {
@@ -46,53 +42,24 @@ private:
CObjectVector<CItemEx> m_Items;
CInArchive m_Archive;
int m_Level;
CBaseProps _props;
int m_MainMethod;
UInt32 m_DicSize;
UInt32 m_Algo;
UInt32 m_NumPasses;
UInt32 m_NumFastBytes;
UInt32 m_NumMatchFinderCycles;
UInt32 m_MemSize;
UInt32 m_Order;
bool m_NumMatchFinderCyclesDefined;
bool m_ForceAesMode;
bool m_IsAesMode;
Byte m_AesKeyMode;
bool m_WriteNtfsTimeExtra;
bool m_ForceLocal;
bool m_ForceUtf8;
#ifndef _7ZIP_ST
UInt32 _numThreads;
#endif
DECL_EXTERNAL_CODECS_VARS
void InitMethodProperties()
void InitMethodProps()
{
m_Level = -1;
_props.Init();
m_MainMethod = -1;
m_Algo =
m_DicSize =
m_NumPasses =
m_NumFastBytes =
m_Order =
m_MemSize =
m_NumMatchFinderCycles = 0xFFFFFFFF;
m_NumMatchFinderCyclesDefined = false;
m_ForceAesMode = false;
m_IsAesMode = false;
m_AesKeyMode = 3; // aes-256
m_WriteNtfsTimeExtra = true;
m_ForceLocal = false;
m_ForceUtf8 = false;
#ifndef _7ZIP_ST
_numThreads = NWindows::NSystem::GetNumberOfProcessors();;
#endif
}
};

View File

@@ -28,37 +28,6 @@ using namespace NTime;
namespace NArchive {
namespace NZip {
static const UInt32 kLzAlgoX1 = 0;
static const UInt32 kLzAlgoX5 = 1;
static const UInt32 kDeflateNumPassesX1 = 1;
static const UInt32 kDeflateNumPassesX7 = 3;
static const UInt32 kDeflateNumPassesX9 = 10;
static const UInt32 kDeflateNumFastBytesX1 = 32;
static const UInt32 kDeflateNumFastBytesX7 = 64;
static const UInt32 kDeflateNumFastBytesX9 = 128;
static const wchar_t *kLzmaMatchFinderX1 = L"HC4";
static const wchar_t *kLzmaMatchFinderX5 = L"BT4";
static const UInt32 kLzmaNumFastBytesX1 = 32;
static const UInt32 kLzmaNumFastBytesX7 = 64;
static const UInt32 kLzmaDicSizeX1 = 1 << 16;
static const UInt32 kLzmaDicSizeX3 = 1 << 20;
static const UInt32 kLzmaDicSizeX5 = 1 << 24;
static const UInt32 kLzmaDicSizeX7 = 1 << 25;
static const UInt32 kLzmaDicSizeX9 = 1 << 26;
static const UInt32 kBZip2NumPassesX1 = 1;
static const UInt32 kBZip2NumPassesX7 = 2;
static const UInt32 kBZip2NumPassesX9 = 7;
static const UInt32 kBZip2DicSizeX1 = 100000;
static const UInt32 kBZip2DicSizeX3 = 500000;
static const UInt32 kBZip2DicSizeX5 = 900000;
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
{
*timeType = NFileTimeType::kDOS;
@@ -99,6 +68,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COM_TRY_BEGIN2
CObjectVector<CUpdateItem> updateItems;
bool thereAreAesUpdates = false;
UInt64 largestSize = 0;
bool largestSizeDefined = false;
for (UInt32 i = 0; i < numItems; i++)
{
CUpdateItem ui;
@@ -178,7 +149,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
const wchar_t kSlash = L'/';
if (!name.IsEmpty())
{
if (name[name.Length() - 1] == kSlash)
if (name.Back() == kSlash)
{
if (!ui.IsDir)
return E_INVALIDARG;
@@ -235,6 +206,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (prop.vt != VT_UI8)
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
if (largestSize < size)
largestSize = size;
largestSizeDefined = true;
}
ui.Size = size;
}
@@ -247,6 +221,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
}
CCompressionMethodMode options;
(CBaseProps &)options = _props;
options._dataSizeReduce = largestSize;
options._dataSizeReduceDefined = largestSizeDefined;
if (getTextPassword)
{
@@ -256,8 +233,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.PasswordIsDefined = IntToBool(passwordIsDefined);
if (options.PasswordIsDefined)
{
options.IsAesMode = (m_ForceAesMode ? m_IsAesMode : thereAreAesUpdates);
options.AesKeyMode = m_AesKeyMode;
if (!m_ForceAesMode)
options.IsAesMode = thereAreAesUpdates;
if (!IsAsciiString((const wchar_t *)password))
return E_INVALIDARG;
@@ -272,13 +249,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
else
options.PasswordIsDefined = false;
int level = m_Level;
if (level < 0)
level = 5;
Byte mainMethod;
if (m_MainMethod < 0)
mainMethod = (Byte)(((level == 0) ?
mainMethod = (Byte)(((_props.Level == 0) ?
NFileHeader::NCompressionMethod::kStored :
NFileHeader::NCompressionMethod::kDeflated));
else
@@ -286,83 +259,6 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.MethodSequence.Add(mainMethod);
if (mainMethod != NFileHeader::NCompressionMethod::kStored)
options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored);
bool isDeflate = (mainMethod == NFileHeader::NCompressionMethod::kDeflated) ||
(mainMethod == NFileHeader::NCompressionMethod::kDeflated64);
bool isLZMA = (mainMethod == NFileHeader::NCompressionMethod::kLZMA);
bool isLz = (isLZMA || isDeflate);
options.NumPasses = m_NumPasses;
options.DicSize = m_DicSize;
options.NumFastBytes = m_NumFastBytes;
options.NumMatchFinderCycles = m_NumMatchFinderCycles;
options.NumMatchFinderCyclesDefined = m_NumMatchFinderCyclesDefined;
options.Algo = m_Algo;
options.MemSize = m_MemSize;
options.Order = m_Order;
#ifndef _7ZIP_ST
options.NumThreads = _numThreads;
#endif
if (isLz)
{
if (isDeflate)
{
if (options.NumPasses == 0xFFFFFFFF)
options.NumPasses = (level >= 9 ? kDeflateNumPassesX9 :
(level >= 7 ? kDeflateNumPassesX7 :
kDeflateNumPassesX1));
if (options.NumFastBytes == 0xFFFFFFFF)
options.NumFastBytes = (level >= 9 ? kDeflateNumFastBytesX9 :
(level >= 7 ? kDeflateNumFastBytesX7 :
kDeflateNumFastBytesX1));
}
else if (isLZMA)
{
if (options.DicSize == 0xFFFFFFFF)
options.DicSize =
(level >= 9 ? kLzmaDicSizeX9 :
(level >= 7 ? kLzmaDicSizeX7 :
(level >= 5 ? kLzmaDicSizeX5 :
(level >= 3 ? kLzmaDicSizeX3 :
kLzmaDicSizeX1))));
if (options.NumFastBytes == 0xFFFFFFFF)
options.NumFastBytes = (level >= 7 ? kLzmaNumFastBytesX7 :
kLzmaNumFastBytesX1);
options.MatchFinder =
(level >= 5 ? kLzmaMatchFinderX5 :
kLzmaMatchFinderX1);
}
if (options.Algo == 0xFFFFFFFF)
options.Algo = (level >= 5 ? kLzAlgoX5 :
kLzAlgoX1);
}
if (mainMethod == NFileHeader::NCompressionMethod::kBZip2)
{
if (options.NumPasses == 0xFFFFFFFF)
options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 :
(level >= 7 ? kBZip2NumPassesX7 :
kBZip2NumPassesX1));
if (options.DicSize == 0xFFFFFFFF)
options.DicSize = (level >= 5 ? kBZip2DicSizeX5 :
(level >= 3 ? kBZip2DicSizeX3 :
kBZip2DicSizeX1));
}
if (mainMethod == NFileHeader::NCompressionMethod::kPPMd)
{
int level2 = level;
if (level2 < 1) level2 = 1;
if (level2 > 9) level2 = 9;
if (options.MemSize == 0xFFFFFFFF)
options.MemSize = (1 << (19 + (level2 > 8 ? 8 : level2)));
if (options.Order == 0xFFFFFFFF)
options.Order = 3 + level2;
if (options.Algo == 0xFFFFFFFF)
options.Algo = (level2 >= 7 ? 1 : 0);
}
return Update(
EXTERNAL_CODECS_VARS
@@ -371,16 +267,34 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COM_TRY_END2
}
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
struct CMethodIndexToName
{
unsigned Method;
const wchar_t *Name;
};
static const CMethodIndexToName k_SupportedMethods[] =
{
{ NFileHeader::NCompressionMethod::kStored, L"COPY" },
{ NFileHeader::NCompressionMethod::kDeflated, L"DEFLATE" },
{ NFileHeader::NCompressionMethod::kDeflated64, L"DEFLATE64" },
{ NFileHeader::NCompressionMethod::kBZip2, L"BZIP2" },
{ NFileHeader::NCompressionMethod::kLZMA, L"LZMA" },
{ NFileHeader::NCompressionMethod::kPPMd, L"PPMD" }
};
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
InitMethodProps();
#ifndef _7ZIP_ST
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
_numThreads = numProcessors;
const UInt32 numProcessors = _props.NumThreads;
#endif
InitMethodProperties();
for (int i = 0; i < numProperties; i++)
for (int i = 0; i < numProps; i++)
{
UString name = UString(names[i]);
UString name = names[i];
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
@@ -390,140 +304,112 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (name[0] == L'X')
{
UInt32 level = 9;
RINOK(ParsePropValue(name.Mid(1), prop, level));
m_Level = level;
continue;
RINOK(ParsePropToUInt32(name.Mid(1), prop, level));
_props.Level = level;
_props.MethodInfo.AddLevelProp(level);
}
else if (name == L"M")
{
if (prop.vt == VT_BSTR)
{
UString m = prop.bstrVal;
UString m = prop.bstrVal, m2;
m.MakeUpper();
if (m == L"COPY") m_MainMethod = NFileHeader::NCompressionMethod::kStored;
else if (m == L"DEFLATE") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated;
else if (m == L"DEFLATE64") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated64;
else if (m == L"BZIP2") m_MainMethod = NFileHeader::NCompressionMethod::kBZip2;
else if (m == L"LZMA") m_MainMethod = NFileHeader::NCompressionMethod::kLZMA;
else if (m == L"PPMD") m_MainMethod = NFileHeader::NCompressionMethod::kPPMd;
else return E_INVALIDARG;
int colonPos = m.Find(L':');
if (colonPos >= 0)
{
m2 = m.Mid(colonPos + 1);
m = m.Left(colonPos);
}
int k;
for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
{
const CMethodIndexToName &pair = k_SupportedMethods[k];
if (m == pair.Name)
{
if (!m2.IsEmpty())
{
RINOK(_props.MethodInfo.ParseParamsFromString(m2));
}
m_MainMethod = pair.Method;
break;
}
}
if (k == ARRAY_SIZE(k_SupportedMethods))
return E_INVALIDARG;
}
else if (prop.vt == VT_UI4)
{
switch(prop.ulVal)
int k;
for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
{
case NFileHeader::NCompressionMethod::kStored:
case NFileHeader::NCompressionMethod::kDeflated:
case NFileHeader::NCompressionMethod::kDeflated64:
case NFileHeader::NCompressionMethod::kBZip2:
case NFileHeader::NCompressionMethod::kLZMA:
m_MainMethod = (Byte)prop.ulVal;
unsigned method = k_SupportedMethods[k].Method;
if (prop.ulVal == method)
{
m_MainMethod = method;
break;
default:
return E_INVALIDARG;
}
}
if (k == ARRAY_SIZE(k_SupportedMethods))
return E_INVALIDARG;
}
else
return E_INVALIDARG;
}
else if (name.Left(2) == L"EM")
{
if (prop.vt == VT_BSTR)
if (prop.vt != VT_BSTR)
return E_INVALIDARG;
{
UString valueString = prop.bstrVal;
valueString.MakeUpper();
if (valueString.Left(3) == L"AES")
UString m = prop.bstrVal;
m.MakeUpper();
if (m.Left(3) == L"AES")
{
valueString = valueString.Mid(3);
if (valueString == L"128")
m_AesKeyMode = 1;
else if (valueString == L"192")
m_AesKeyMode = 2;
else if (valueString == L"256" || valueString.IsEmpty())
m_AesKeyMode = 3;
m = m.Mid(3);
if (m == L"128")
_props.AesKeyMode = 1;
else if (m == L"192")
_props.AesKeyMode = 2;
else if (m == L"256" || m.IsEmpty())
_props.AesKeyMode = 3;
else
return E_INVALIDARG;
m_IsAesMode = true;
_props.IsAesMode = true;
m_ForceAesMode = true;
}
else if (valueString == L"ZIPCRYPTO")
else if (m == L"ZIPCRYPTO")
{
m_IsAesMode = false;
_props.IsAesMode = false;
m_ForceAesMode = true;
}
else
return E_INVALIDARG;
}
else
return E_INVALIDARG;
}
else if (name[0] == L'D')
{
UInt32 dicSize = kBZip2DicSizeX5;
RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));
m_DicSize = dicSize;
}
else if (name.Left(3) == L"MEM")
{
UInt32 memSize = 1 << 24;
RINOK(ParsePropDictionaryValue(name.Mid(3), prop, memSize));
m_MemSize = memSize;
}
else if (name[0] == L'O')
{
UInt32 order = 8;
RINOK(ParsePropValue(name.Mid(1), prop, order));
m_Order = order;
}
else if (name.Left(4) == L"PASS")
{
UInt32 num = kDeflateNumPassesX9;
RINOK(ParsePropValue(name.Mid(4), prop, num));
m_NumPasses = num;
}
else if (name.Left(2) == L"FB")
{
UInt32 num = kDeflateNumFastBytesX9;
RINOK(ParsePropValue(name.Mid(2), prop, num));
m_NumFastBytes = num;
}
else if (name.Left(2) == L"MC")
{
UInt32 num = 0xFFFFFFFF;
RINOK(ParsePropValue(name.Mid(2), prop, num));
m_NumMatchFinderCycles = num;
m_NumMatchFinderCyclesDefined = true;
}
else if (name.Left(2) == L"MT")
{
#ifndef _7ZIP_ST
RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads));
RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _props.NumThreads));
_props.NumThreadsWasChanged = true;
#endif
}
else if (name.Left(1) == L"A")
{
UInt32 num = kLzAlgoX5;
RINOK(ParsePropValue(name.Mid(1), prop, num));
m_Algo = num;
}
else if (name.CompareNoCase(L"TC") == 0)
{
RINOK(SetBoolProperty(m_WriteNtfsTimeExtra, prop));
RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra));
}
else if (name.CompareNoCase(L"CL") == 0)
{
RINOK(SetBoolProperty(m_ForceLocal, prop));
RINOK(PROPVARIANT_to_bool(prop, m_ForceLocal));
if (m_ForceLocal)
m_ForceUtf8 = false;
}
else if (name.CompareNoCase(L"CU") == 0)
{
RINOK(SetBoolProperty(m_ForceUtf8, prop));
RINOK(PROPVARIANT_to_bool(prop, m_ForceUtf8));
if (m_ForceUtf8)
m_ForceLocal = false;
}
else
return E_INVALIDARG;
return _props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop);
}
return S_OK;
}

View File

@@ -756,6 +756,7 @@ void CEcd64::Parse(const Byte *p)
HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress)
{
IsOkHeaders = true;
// m_Signature must be kLocalFileHeaderSignature or
// kEndOfCentralDirSignature
// m_Position points to next byte after signature
@@ -852,6 +853,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
if (numCdItems != items.Size())
IsOkHeaders = false;
if ((UInt16)ecd64.numEntriesInCDOnThisDisk != ((UInt16)numCdItems) ||
(UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) ||
(UInt32)ecd64.cdSize != (UInt32)cdSize ||
@@ -861,7 +864,6 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
_inBufMode = false;
_inBuffer.Free();
IsOkHeaders = (numCdItems == items.Size());
ArcInfo.FinishPosition = m_Position;
return S_OK;
}

View File

@@ -51,7 +51,7 @@ bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const
return false;
}
bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const
bool CExtraSubBlock::ExtractUnixTime(bool isCentral, int index, UInt32 &res) const
{
res = 0;
UInt32 size = (UInt32)Data.GetCapacity();
@@ -60,6 +60,15 @@ bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const
const Byte *p = (const Byte *)Data;
Byte flags = *p++;
size--;
if (isCentral)
{
if (index != NFileHeader::NUnixTime::kMTime ||
(flags & (1 << NFileHeader::NUnixTime::kMTime)) == 0 ||
size < 4)
return false;
res = GetUi32(p);
return true;
}
for (int i = 0; i < 3; i++)
if ((flags & (1 << i)) != 0)
{
@@ -88,7 +97,7 @@ bool CItem::IsDir() const
if (!FromCentral)
return false;
WORD highAttributes = WORD((ExternalAttributes >> 16 ) & 0xFFFF);
switch(MadeByVersion.HostOS)
switch (MadeByVersion.HostOS)
{
case NFileHeader::NHostOS::kAMIGA:
switch (highAttributes & NFileHeader::NAmigaAttribute::kIFMT)
@@ -109,44 +118,41 @@ bool CItem::IsDir() const
case NFileHeader::NHostOS::kAcorn:
case NFileHeader::NHostOS::kMVS:
return false; // change it throw kUnknownAttributes;
case NFileHeader::NHostOS::kUnix:
return (highAttributes & NFileHeader::NUnixAttribute::kIFDIR) != 0;
default:
/*
switch (highAttributes & NFileHeader::NUnixAttribute::kIFMT)
{
case NFileHeader::NUnixAttribute::kIFDIR:
return true;
default:
return false;
}
*/
return false;
}
}
UInt32 CLocalItem::GetWinAttributes() const
UInt32 CItem::GetWinAttrib() const
{
DWORD winAttributes = 0;
if (IsDir())
winAttributes |= FILE_ATTRIBUTE_DIRECTORY;
return winAttributes;
}
UInt32 CItem::GetWinAttributes() const
{
DWORD winAttributes = 0;
switch(MadeByVersion.HostOS)
DWORD winAttrib = 0;
switch (MadeByVersion.HostOS)
{
case NFileHeader::NHostOS::kFAT:
case NFileHeader::NHostOS::kNTFS:
if (FromCentral)
winAttributes = ExternalAttributes;
winAttrib = ExternalAttributes;
break;
default:
winAttributes = 0; // must be converted from unix value;
}
if (IsDir()) // test it;
winAttributes |= FILE_ATTRIBUTE_DIRECTORY;
return winAttributes;
winAttrib |= FILE_ATTRIBUTE_DIRECTORY;
return winAttrib;
}
bool CItem::GetPosixAttrib(UInt32 &attrib) const
{
// some archivers can store PosixAttrib in high 16 bits even with HostOS=FAT.
if (FromCentral && MadeByVersion.HostOS == NFileHeader::NHostOS::kUnix)
{
attrib = ExternalAttributes >> 16;
return (attrib != 0);
}
attrib = 0;
if (IsDir())
attrib = NFileHeader::NUnixAttribute::kIFDIR;
return false;
}
void CLocalItem::SetFlagBits(int startBitNumber, int numBits, int value)

View File

@@ -3,7 +3,6 @@
#ifndef __ARCHIVE_ZIP_ITEM_H
#define __ARCHIVE_ZIP_ITEM_H
#include "Common/Types.h"
#include "Common/MyString.h"
#include "Common/Buffer.h"
#include "Common/UTFConvert.h"
@@ -28,7 +27,7 @@ struct CExtraSubBlock
UInt16 ID;
CByteBuffer Data;
bool ExtractNtfsTime(int index, FILETIME &ft) const;
bool ExtractUnixTime(int index, UInt32 &res) const;
bool ExtractUnixTime(bool isCentral, int index, UInt32 &res) const;
};
struct CWzAesExtraField
@@ -152,13 +151,13 @@ struct CExtraBlock
return false;
}
bool GetUnixTime(int index, UInt32 &res) const
bool GetUnixTime(bool isCentral, int index, UInt32 &res) const
{
for (int i = 0; i < SubBlocks.Size(); i++)
{
const CExtraSubBlock &sb = SubBlocks[i];
if (sb.ID == NFileHeader::NExtraID::kUnixTime)
return sb.ExtractUnixTime(index, res);
return sb.ExtractUnixTime(isCentral, index, res);
}
return false;
}
@@ -205,7 +204,6 @@ public:
bool IsDir() const;
bool IgnoreItem() const { return false; }
UInt32 GetWinAttributes() const;
bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
@@ -252,7 +250,8 @@ public:
bool NtfsTimeIsDefined;
bool IsDir() const;
UInt32 GetWinAttributes() const;
UInt32 GetWinAttrib() const;
bool GetPosixAttrib(UInt32 &attrib) const;
bool IsThereCrc() const
{
@@ -277,5 +276,3 @@ public:
}}
#endif

View File

@@ -473,6 +473,9 @@ static HRESULT Update2St(
items.Add(item);
lps->ProgressOffset += NFileHeader::kLocalBlockSize;
}
lps->InSize = unpackSizeTotal;
lps->OutSize = packSizeTotal;
RINOK(lps->SetCur());
archive.WriteCentralDir(items, comment);
return S_OK;
}
@@ -493,7 +496,7 @@ static HRESULT Update2(
UInt64 numBytesToCompress = 0;
int i;
for(i = 0; i < updateItems.Size(); i++)
for (i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &ui = updateItems[i];
if (ui.NewData)
@@ -527,6 +530,10 @@ static HRESULT Update2(
complexity = 0;
CCompressionMethodMode options2;
if (options != 0)
options2 = *options;
#ifndef _7ZIP_ST
const size_t kNumMaxThreads = (1 << 10);
@@ -537,53 +544,58 @@ static HRESULT Update2(
const size_t kMemPerThread = (1 << 25);
const size_t kBlockSize = 1 << 16;
CCompressionMethodMode options2;
if (options != 0)
options2 = *options;
bool mtMode = ((options != 0) && (numThreads > 1));
if (numFilesToCompress <= 1)
mtMode = false;
if (mtMode)
if (!mtMode)
{
if (numThreads < 2)
if (options2.MethodInfo.FindProp(NCoderPropID::kNumThreads) < 0 &&
options2.NumThreadsWasChanged)
options2.MethodInfo.AddNumThreadsProp(1);
}
else
{
Byte method = options->MethodSequence.Front();
if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined)
mtMode = false;
numThreads = 1;
if (method == NFileHeader::NCompressionMethod::kBZip2)
{
bool fixedNumber;
UInt32 numBZip2Threads = options2.MethodInfo.Get_BZip2_NumThreads(fixedNumber);
if (!fixedNumber)
{
UInt64 averageSize = numBytesToCompress / numFilesToCompress;
UInt32 blockSize = options->DicSize;
if (blockSize == 0)
blockSize = 1;
UInt64 averageNumberOfBlocks = averageSize / blockSize;
UInt32 numBZip2Threads = 32;
UInt32 blockSize = options2.MethodInfo.Get_BZip2_BlockSize();
UInt64 averageNumberOfBlocks = averageSize / blockSize + 1;
numBZip2Threads = 32;
if (averageNumberOfBlocks < numBZip2Threads)
numBZip2Threads = (UInt32)averageNumberOfBlocks;
if (numBZip2Threads < 1)
numBZip2Threads = 1;
numThreads = numThreads / numBZip2Threads;
options2.NumThreads = numBZip2Threads;
if (numThreads <= 1)
mtMode = false;
options2.MethodInfo.AddNumThreadsProp(numBZip2Threads);
}
numThreads /= numBZip2Threads;
}
if (method == NFileHeader::NCompressionMethod::kLZMA)
{
UInt32 numLZMAThreads = (options->Algo > 0 ? 2 : 1);
bool fixedNumber;
// we suppose that default LZMA is 2 thread. So we don't change it
UInt32 numLZMAThreads = options2.MethodInfo.Get_Lzma_NumThreads(fixedNumber);
numThreads /= numLZMAThreads;
options2.NumThreads = numLZMAThreads;
}
if (numThreads > numFilesToCompress)
numThreads = (UInt32)numFilesToCompress;
if (numThreads <= 1)
mtMode = false;
}
}
if (!mtMode)
#endif
return Update2St(
EXTERNAL_CODECS_LOC_VARS
archive, inArchive,inStream,
inputItems, updateItems, options, comment, updateCallback);
archive, inArchive, inStream,
inputItems, updateItems, &options2, comment, updateCallback);
#ifndef _7ZIP_ST
@@ -606,7 +618,7 @@ static HRESULT Update2(
{
RINOK(memManager.AllocateSpaceAlways((size_t)numThreads * (kMemPerThread / kBlockSize)));
for(i = 0; i < updateItems.Size(); i++)
for (i = 0; i < updateItems.Size(); i++)
refs.Refs.Add(CMemBlocks2());
UInt32 i;
@@ -796,6 +808,7 @@ static HRESULT Update2(
mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
itemIndex++;
}
RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL));
archive.WriteCentralDir(items, comment);
return S_OK;
#endif

View File

@@ -1771,14 +1771,6 @@ SOURCE=..\..\UI\Common\UpdateProduce.cpp
SOURCE=..\..\UI\Common\UpdateProduce.h
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\WorkDir.cpp
# End Source File
# Begin Source File
SOURCE=..\..\UI\Common\WorkDir.h
# End Source File
# End Group
# Begin Group "Crypto"

View File

@@ -90,7 +90,6 @@ UI_COMMON_OBJS = \
$O\UpdateCallback.obj \
$O\UpdatePair.obj \
$O\UpdateProduce.obj \
$O\WorkDir.obj \
AR_OBJS = \
$O\Bz2Handler.obj \

View File

@@ -88,7 +88,6 @@ UI_COMMON_OBJS = \
$O\UpdateCallback.obj \
$O\UpdatePair.obj \
$O\UpdateProduce.obj \
$O\WorkDir.obj \
AR_OBJS = \
$O\LzmaHandler.obj \

View File

@@ -613,6 +613,14 @@ SOURCE=..\..\Common\FileStreams.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodProps.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodProps.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\ProgressUtils.cpp
# End Source File
# Begin Source File

View File

@@ -181,6 +181,7 @@ AR_OBJS = \
$O\SplitHandler.obj \
$O\SquashfsHandler.obj \
$O\SwfHandler.obj \
$O\UefiHandler.obj \
$O\VhdHandler.obj \
$O\XarHandler.obj \
$O\XzHandler.obj \

View File

@@ -3,5 +3,5 @@
STRINGTABLE
BEGIN
100 "7z zip bz2 bzip2 tbz2 tbz rar arj z taz lzh lha cab iso 001 rpm deb cpio tar gz gzip tgz tpz4 wim swm lzma dmg hfs xar vhd fat ntfs xz"
100 "7z zip rar 001 cab iso xz txz lzma tar cpio bz2 bzip2 tbz2 tbz gz gzip tgz tpz z taz lzh lha rpm deb arj vhd wim swm fat ntfs dmg hfs xar squashfs"
END

View File

@@ -109,7 +109,6 @@ CRYPTO_OBJS = \
$O\7zAesRegister.obj \
$O\MyAes.obj \
$O\RandGen.obj \
$O\Sha1.obj \
C_OBJS = \
$O\Alloc.obj \

View File

@@ -26,6 +26,7 @@ WIN_OBJS = \
$O\LimitedStreams.obj \
$O\LockedStream.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
$O\OutBuffer.obj \
$O\ProgressUtils.obj \
$O\StreamBinder.obj \

View File

@@ -2436,6 +2436,10 @@ SOURCE=..\..\Archive\SwfHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\UefiHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Archive\VhdHandler.cpp
# End Source File
# Begin Source File

View File

@@ -79,6 +79,7 @@ AR_OBJS = \
$O\SplitHandler.obj \
$O\SwfHandler.obj \
$O\SquashfsHandler.obj \
$O\UefiHandler.obj \
$O\VhdHandler.obj \
$O\XarHandler.obj \
$O\XzHandler.obj \

View File

@@ -1,6 +1,6 @@
#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za")
MY_VERSION_INFO_DLL("7z Plugin", "7z")
0 ICON "../../Archive/Icons/7z.ico"
@@ -33,5 +33,5 @@ MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za")
STRINGTABLE
BEGIN
100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 001:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15 lzma:16 dmg:17 hfs:18 xar:19 vhd:20 fat:21 ntfs:22 xz:23 txz:23 squashfs:24"
100 "7z:0 zip:1 rar:3 001:9 cab:7 iso:8 xz:23 txz:23 lzma:16 tar:13 cpio:12 bz2:2 bzip2:2 tbz2:2 tbz:2 gz:14 gzip:14 tgz:14 tpz:14 z:5 taz:5 lzh:6 lha:6 rpm:10 deb:11 arj:4 vhd:20 wim:15 swm:15 fat:21 ntfs:22 dmg:17 hfs:18 xar:19 squashfs:24"
END

View File

@@ -49,6 +49,8 @@ enum Enum
{
kHelp1 = 0,
kHelp2,
kMethod,
kLevel,
kAlgo,
kDict,
kFb,
@@ -69,6 +71,8 @@ static const CSwitchForm kSwitchForms[] =
{
{ L"?", NSwitchType::kSimple, false },
{ L"H", NSwitchType::kSimple, false },
{ L"MM", NSwitchType::kUnLimitedPostString, false, 1 },
{ L"X", NSwitchType::kUnLimitedPostString, false, 1 },
{ L"A", NSwitchType::kUnLimitedPostString, false, 1 },
{ L"D", NSwitchType::kUnLimitedPostString, false, 1 },
{ L"FB", NSwitchType::kUnLimitedPostString, false, 1 },
@@ -186,7 +190,7 @@ int main2(int numArgs, const char *args[])
IncorrectCommand();
}
if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
{
PrintHelp();
return 0;
@@ -198,21 +202,38 @@ int main2(int numArgs, const char *args[])
IncorrectCommand();
const UString &command = nonSwitchStrings[paramIndex++];
CObjectVector<CProperty> props;
bool dictDefined = false;
UInt32 dict = (UInt32)-1;
if(parser[NKey::kDict].ThereIs)
UInt32 dict = (UInt32)(Int32)-1;
if (parser[NKey::kDict].ThereIs)
{
UInt32 dicLog;
if (!GetNumber(parser[NKey::kDict].PostStrings[0], dicLog))
const UString &s = parser[NKey::kDict].PostStrings[0];
if (!GetNumber(s, dicLog))
IncorrectCommand();
dict = 1 << dicLog;
dictDefined = true;
CProperty prop;
prop.Name = L"d";
prop.Value = s;
props.Add(prop);
}
if (parser[NKey::kLevel].ThereIs)
{
UInt32 level = 5;
const UString &s = parser[NKey::kLevel].PostStrings[0];
if (!GetNumber(s, level))
IncorrectCommand();
CProperty prop;
prop.Name = L"x";
prop.Value = s;
props.Add(prop);
}
UString mf = L"BT4";
if (parser[NKey::kMatchFinder].ThereIs)
mf = parser[NKey::kMatchFinder].PostStrings[0];
UInt32 numThreads = (UInt32)-1;
UInt32 numThreads = (UInt32)(Int32)-1;
#ifndef _7ZIP_ST
if (parser[NKey::kMultiThread].ThereIs)
@@ -224,9 +245,24 @@ int main2(int numArgs, const char *args[])
else
if (!GetNumber(s, numThreads))
IncorrectCommand();
CProperty prop;
prop.Name = L"mt";
prop.Value = s;
props.Add(prop);
}
#endif
if (parser[NKey::kMethod].ThereIs)
{
UString s = parser[NKey::kMethod].PostStrings[0];
if (s.IsEmpty() || s[0] != '=')
IncorrectCommand();
CProperty prop;
prop.Name = L"m";
prop.Value = s.Mid(1);
props.Add(prop);
}
if (command.CompareNoCase(L"b") == 0)
{
const UInt32 kNumDefaultItereations = 1;
@@ -236,10 +272,19 @@ int main2(int numArgs, const char *args[])
if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))
numIterations = kNumDefaultItereations;
}
return LzmaBenchCon(stderr, numIterations, numThreads, dict);
HRESULT res = BenchCon(props, numIterations, stderr);
if (res != S_OK)
{
if (res != E_ABORT)
{
PrintMessage("Benchmark Error");
return 1;
}
}
return 0;
}
if (numThreads == (UInt32)-1)
if (numThreads == (UInt32)(Int32)-1)
numThreads = 1;
bool encodeMode = false;
@@ -267,7 +312,7 @@ int main2(int numArgs, const char *args[])
const UString &inputName = nonSwitchStrings[paramIndex++];
inStreamSpec = new CInFileStream;
inStream = inStreamSpec;
if (!inStreamSpec->Open(GetSystemString(inputName)))
if (!inStreamSpec->Open(us2fs(inputName)))
{
fprintf(stderr, "\nError: can not open input file %s\n",
(const char *)GetOemString(inputName));
@@ -289,7 +334,7 @@ int main2(int numArgs, const char *args[])
const UString &outputName = nonSwitchStrings[paramIndex++];
outStreamSpec = new COutFileStream;
outStream = outStreamSpec;
if (!outStreamSpec->Create(GetSystemString(outputName), true))
if (!outStreamSpec->Create(us2fs(outputName), true))
{
fprintf(stderr, "\nError: can not open output file %s\n",
(const char *)GetOemString(outputName));
@@ -398,7 +443,7 @@ int main2(int numArgs, const char *args[])
if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc))
IncorrectCommand();
PROPID propIDs[] =
const PROPID propIDs[] =
{
NCoderPropID::kDictionarySize,
NCoderPropID::kPosStateBits,
@@ -512,7 +557,7 @@ int main2(int numArgs, const char *args[])
int MY_CDECL main(int numArgs, const char *args[])
{
try { return main2(numArgs, args); }
catch(const char *s)
catch (const char *s)
{
fprintf(stderr, "\nError: %s\n", s);
return 1;

View File

@@ -132,6 +132,14 @@ SOURCE=..\..\..\Windows\FileIO.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Synchronization.cpp
# End Source File
# Begin Source File
@@ -280,6 +288,14 @@ SOURCE=..\..\Common\FilterCoder.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodProps.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\MethodProps.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamUtils.cpp
# End Source File
# Begin Source File

View File

@@ -21,6 +21,7 @@ COMMON_OBJS = \
WIN_OBJS = \
$O\FileIO.obj \
$O\PropVariant.obj \
$O\System.obj
7ZIP_COMMON_OBJS = \
@@ -28,6 +29,7 @@ WIN_OBJS = \
$O\CreateCoder.obj \
$O\FileStreams.obj \
$O\FilterCoder.obj \
$O\MethodProps.obj \
$O\OutBuffer.obj \
$O\StreamUtils.obj \

View File

@@ -30,15 +30,18 @@ OBJS = \
CWrappers.o \
FileStreams.o \
FilterCoder.o \
MethodProps.o \
StreamUtils.o \
$(FILE_IO).o \
CommandLineParser.o \
CRC.o \
IntToString.o \
MyString.o \
MyVector.o \
MyWindows.o \
StringConvert.o \
StringToInt.o \
MyVector.o \
PropVariant.o \
7zCrc.o \
7zCrcOpt.o \
Alloc.o \
@@ -89,6 +92,9 @@ FileStreams.o: ../../Common/FileStreams.cpp
FilterCoder.o: ../../Common/FilterCoder.cpp
$(CXX) $(CFLAGS) ../../Common/FilterCoder.cpp
MethodProps.o: ../../Common/MethodProps.cpp
$(CXX) $(CFLAGS) ../../Common/MethodProps.cpp
StreamUtils.o: ../../Common/StreamUtils.cpp
$(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp
@@ -102,23 +108,26 @@ CommandLineParser.o: ../../../Common/CommandLineParser.cpp
CRC.o: ../../../Common/CRC.cpp
$(CXX) $(CFLAGS) ../../../Common/CRC.cpp
MyWindows.o: ../../../Common/MyWindows.cpp
$(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp
IntToString.o: ../../../Common/IntToString.cpp
$(CXX) $(CFLAGS) ../../../Common/IntToString.cpp
MyString.o: ../../../Common/MyString.cpp
$(CXX) $(CFLAGS) ../../../Common/MyString.cpp
MyVector.o: ../../../Common/MyVector.cpp
$(CXX) $(CFLAGS) ../../../Common/MyVector.cpp
MyWindows.o: ../../../Common/MyWindows.cpp
$(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp
StringConvert.o: ../../../Common/StringConvert.cpp
$(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp
StringToInt.o: ../../../Common/StringToInt.cpp
$(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp
MyVector.o: ../../../Common/MyVector.cpp
$(CXX) $(CFLAGS) ../../../Common/MyVector.cpp
PropVariant.o: ../../../Windows/PropVariant.cpp
$(CXX) $(CFLAGS) ../../../Windows/PropVariant.cpp
7zCrc.o: ../../../../C/7zCrc.c
$(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c

View File

@@ -11,6 +11,7 @@
#include "Windows/DLL.h"
#include "Windows/FileDir.h"
#endif
#include "Windows/FileName.h"
#include "../../UI/Common/ExitCode.h"
#include "../../UI/Common/Extract.h"
@@ -25,6 +26,9 @@ using namespace NWindows;
using namespace NFile;
using namespace NCommandLineParser;
#ifdef _WIN32
HINSTANCE g_hInstance = 0;
#endif
int g_CodePage = -1;
extern CStdOutStream *g_StdStream;
@@ -261,12 +265,11 @@ int Main2(
#ifdef _WIN32
UString arcPath;
FString arcPath;
{
UString path;
NDLL::MyGetModuleFileName(NULL, path);
int fileNamePartStartIndex;
if (!NDirectory::MyGetFullPathName(path, arcPath, fileNamePartStartIndex))
FString path;
NDLL::MyGetModuleFileName(path);
if (!NDirectory::MyGetFullPathName(path, arcPath))
{
g_StdOut << "GetFullPathName Error";
return NExitCode::kFatalError;
@@ -291,7 +294,7 @@ int Main2(
PrintHelpAndExit();
}
if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
{
PrintHelp();
return 0;
@@ -330,23 +333,23 @@ int Main2(
bool passwordEnabled = parser[NKey::kPassword].ThereIs;
UString password;
if(passwordEnabled)
if (passwordEnabled)
password = parser[NKey::kPassword].PostStrings[0];
if (!NFind::DoesFileExist(arcPath))
throw kCantFindSFX;
UString outputDir;
FString outputDir;
if (parser[NKey::kOutputDir].ThereIs)
{
outputDir = parser[NKey::kOutputDir].PostStrings[0];
outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]);
NName::NormalizeDirPathPrefix(outputDir);
}
{
UStringVector v1, v2;
v1.Add(arcPath);
v2.Add(arcPath);
v1.Add(fs2us(arcPath));
v2.Add(fs2us(arcPath));
const NWildcard::CCensorNode &wildcardCensorHead =
wildcardCensor.Pairs.Front().Head;
@@ -362,7 +365,7 @@ int Main2(
if (result != S_OK)
throw CSystemException(result);
if(command.CommandType != NCommandType::kList)
if (command.CommandType != NCommandType::kList)
{
CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;

View File

@@ -6,6 +6,7 @@
#include "Windows/FileDir.h"
#include "Windows/FileFind.h"
#include "Windows/FileName.h"
#include "Windows/PropVariant.h"
#include "ExtractCallback.h"
@@ -18,7 +19,7 @@ static LPCWSTR kCantOpenFile = L"Can not open output file";
static LPCWSTR kUnsupportedMethod = L"Unsupported Method";
void CExtractCallbackImp::Init(IInArchive *archiveHandler,
const UString &directoryPath,
const FString &directoryPath,
const UString &itemDefaultName,
const FILETIME &defaultMTime,
UInt32 defaultAttributes)
@@ -76,12 +77,12 @@ STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue)
void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts)
{
UString fullPath = _directoryPath;
for(int i = 0; i < dirPathParts.Size(); i++)
FString fullPath = _directoryPath;
for (int i = 0; i < dirPathParts.Size(); i++)
{
fullPath += dirPathParts[i];
fullPath += us2fs(dirPathParts[i]);
NDirectory::MyCreateDirectory(fullPath);
fullPath += NName::kDirDelimiter;
fullPath += FCHAR_PATH_SEPARATOR;
}
}
@@ -153,7 +154,7 @@ STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index,
CreateComplexDirectory(pathParts);
}
UString fullProcessedPath = _directoryPath + processedPath;
FString fullProcessedPath = _directoryPath + us2fs(processedPath);
if (_processedFileInfo.IsDir)
{
@@ -166,7 +167,7 @@ STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index,
return S_OK;
}
NFind::CFileInfoW fileInfo;
NFind::CFileInfo fileInfo;
if (fileInfo.Find(fullProcessedPath))
{
if (!NDirectory::DeleteFileAlways(fullProcessedPath))

View File

@@ -31,9 +31,9 @@ public:
private:
CMyComPtr<IInArchive> _archiveHandler;
UString _directoryPath;
FString _directoryPath;
UString _filePath;
UString _diskFilePath;
FString _diskFilePath;
bool _extractMode;
struct CProcessedFileInfo
@@ -60,7 +60,7 @@ public:
UString _message;
void Init(IInArchive *archiveHandler,
const UString &directoryPath,
const FString &directoryPath,
const UString &itemDefaultName,
const FILETIME &defaultMTime,
UInt32 defaultAttributes);

View File

@@ -3,6 +3,7 @@
#include "StdAfx.h"
#include "Windows/FileDir.h"
#include "Windows/FileName.h"
#include "Windows/Thread.h"
#include "../../UI/Common/OpenArchive.h"
@@ -20,8 +21,8 @@ static LPCWSTR kCantOpenArchive = L"Can not open the file as archive";
struct CThreadExtracting
{
CCodecs *Codecs;
UString FileName;
UString DestFolder;
FString FileName;
FString DestFolder;
CExtractCallbackImp *ExtractCallbackSpec;
CMyComPtr<IArchiveExtractCallback> ExtractCallback;
@@ -32,7 +33,7 @@ struct CThreadExtracting
void Process2()
{
NFile::NFind::CFileInfoW fi;
NFile::NFind::CFileInfo fi;
if (!fi.Find(FileName))
{
ErrorMessage = kCantFindArchive;
@@ -40,7 +41,7 @@ struct CThreadExtracting
return;
}
Result = ArchiveLink.Open2(Codecs, CIntVector(), false, NULL, FileName, ExtractCallbackSpec);
Result = ArchiveLink.Open2(Codecs, CIntVector(), false, NULL, fs2us(FileName), ExtractCallbackSpec);
if (Result != S_OK)
{
if (Result != S_OK)
@@ -48,7 +49,7 @@ struct CThreadExtracting
return;
}
UString dirPath = DestFolder;
FString dirPath = DestFolder;
NFile::NName::NormalizeDirPathPrefix(dirPath);
if (!NFile::NDirectory::CreateComplexDirectory(dirPath))
@@ -57,7 +58,7 @@ struct CThreadExtracting
#ifdef LANG
0x02000603,
#endif
dirPath);
fs2us(dirPath));
Result = E_FAIL;
return;
}
@@ -86,7 +87,7 @@ struct CThreadExtracting
}
};
HRESULT ExtractArchive(CCodecs *codecs,const UString &fileName, const UString &destFolder,
HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder,
bool showProgress, bool &isCorrupt, UString &errorMessage)
{
isCorrupt = false;

Some files were not shown because too many files have changed in this diff Show More