9.21
65
C/7zCrc.c
@@ -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
|
||||
}
|
||||
|
||||
38
C/7zCrcOpt.c
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
26
C/Lzma2Dec.c
@@ -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;
|
||||
}
|
||||
|
||||
22
C/LzmaDec.c
@@ -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;
|
||||
}
|
||||
|
||||
14
C/LzmaEnc.c
@@ -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)
|
||||
|
||||
12
C/LzmaEnc.h
@@ -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
|
||||
|
||||
7
C/Ppmd.h
@@ -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 *
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
48
C/XzDec.c
@@ -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
@@ -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;
|
||||
|
||||
32
C/XzEnc.h
@@ -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
|
||||
|
||||
33
C/XzIn.c
@@ -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);
|
||||
|
||||
@@ -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); }
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -133,6 +133,7 @@ class CInArchive
|
||||
CInByte2 *_inByteBack;
|
||||
|
||||
UInt64 _arhiveBeginStreamPosition;
|
||||
UInt64 _fileEndPosition;
|
||||
|
||||
Byte _header[kHeaderSize];
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -39,7 +39,7 @@ struct CItem
|
||||
{
|
||||
if (Name.Length() == 0)
|
||||
return false;
|
||||
return (Name[Name.Length() - 1] == '/');
|
||||
return (Name.Back() == '/');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -18,6 +18,7 @@ struct CCoder: public CCoderInfo, public CVirtThread
|
||||
|
||||
virtual void Execute();
|
||||
void Code(ICompressProgressInfo *progress);
|
||||
~CCoder() { CVirtThread::WaitThreadFinish(); }
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 ¶m, 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 ¶m = 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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ class CHandler:
|
||||
UInt64 _headersSize;
|
||||
bool _phySizeDefined;
|
||||
AString _errorMessage;
|
||||
bool _isSparse;
|
||||
|
||||
NCompress::CCopyCoder *copyCoderSpec;
|
||||
CMyComPtr<ICompressCoder> copyCoder;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -90,7 +90,6 @@ UI_COMMON_OBJS = \
|
||||
$O\UpdateCallback.obj \
|
||||
$O\UpdatePair.obj \
|
||||
$O\UpdateProduce.obj \
|
||||
$O\WorkDir.obj \
|
||||
|
||||
AR_OBJS = \
|
||||
$O\Bz2Handler.obj \
|
||||
|
||||
@@ -88,7 +88,6 @@ UI_COMMON_OBJS = \
|
||||
$O\UpdateCallback.obj \
|
||||
$O\UpdatePair.obj \
|
||||
$O\UpdateProduce.obj \
|
||||
$O\WorkDir.obj \
|
||||
|
||||
AR_OBJS = \
|
||||
$O\LzmaHandler.obj \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -109,7 +109,6 @@ CRYPTO_OBJS = \
|
||||
$O\7zAesRegister.obj \
|
||||
$O\MyAes.obj \
|
||||
$O\RandGen.obj \
|
||||
$O\Sha1.obj \
|
||||
|
||||
C_OBJS = \
|
||||
$O\Alloc.obj \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||