9.04 beta

This commit is contained in:
Igor Pavlov
2009-06-02 00:00:00 +00:00
committed by Kornel Lesiński
parent 8874e4fbc9
commit 829409452d
440 changed files with 19803 additions and 9941 deletions

View File

@@ -24,8 +24,8 @@ CrcUpdateT8 PROC
push RDI push RDI
push RBP push RBP
mov EAX, ECX mov EAX, ECX
mov RSI, RDX mov RSI, RDX
mov RDI, R9 mov RDI, R9
@@ -77,8 +77,8 @@ CrcUpdateT8 PROC
xor EAX,EDX xor EAX,EDX
cmp RSI, R9 cmp RSI, R9
jne main_loop jne main_loop
xor EAX, [RSI] xor EAX, [RSI]

View File

@@ -24,9 +24,9 @@ public @CrcUpdateT8@16
push EDI push EDI
push EBP push EBP
mov EAX, ECX mov EAX, ECX
mov ESI, EDX mov ESI, EDX
mov EDI, [ESP + data_size] mov EDI, [ESP + data_size]
mov EBP, [ESP + crc_table] mov EBP, [ESP + crc_table]
test EDI, EDI test EDI, EDI
@@ -77,8 +77,8 @@ public @CrcUpdateT8@16
xor EAX,EDX xor EAX,EDX
cmp ESI, EDI cmp ESI, EDI
jne main_loop jne main_loop
xor EAX, [ESI] xor EAX, [ESI]
mov EDI, [ESP + data_size] mov EDI, [ESP + data_size]

View File

@@ -1,11 +1,15 @@
/* 7zBuf.h -- Byte Buffer /* 7zBuf.h -- Byte Buffer
2008-10-04 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_BUF_H #ifndef __7Z_BUF_H
#define __7Z_BUF_H #define __7Z_BUF_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct typedef struct
{ {
Byte *data; Byte *data;
@@ -28,4 +32,8 @@ void DynBuf_SeekToBeg(CDynBuf *p);
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,7 +1,5 @@
/* 7zCrc.h -- CRC32 calculation /* 7zCrc.h -- CRC32 calculation
2008-03-13 2009-02-07 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __7Z_CRC_H #ifndef __7Z_CRC_H
#define __7Z_CRC_H #define __7Z_CRC_H
@@ -10,6 +8,10 @@ Public domain */
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
extern UInt32 g_CrcTable[]; extern UInt32 g_CrcTable[];
void MY_FAST_CALL CrcGenerateTable(void); void MY_FAST_CALL CrcGenerateTable(void);
@@ -21,4 +23,8 @@ void MY_FAST_CALL CrcGenerateTable(void);
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,5 +1,5 @@
/* 7zFile.h -- File IO /* 7zFile.h -- File IO
2008-11-22 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_FILE_H #ifndef __7Z_FILE_H
#define __7Z_FILE_H #define __7Z_FILE_H
@@ -16,6 +16,10 @@
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ---------- File ---------- */ /* ---------- File ---------- */
@@ -71,4 +75,8 @@ typedef struct
void FileOutStream_CreateVTable(CFileOutStream *p); void FileOutStream_CreateVTable(CFileOutStream *p);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,7 +1,7 @@
#define MY_VER_MAJOR 4 #define MY_VER_MAJOR 9
#define MY_VER_MINOR 65 #define MY_VER_MINOR 04
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION "4.65" #define MY_VERSION "9.04 beta"
#define MY_DATE "2009-02-03" #define MY_DATE "2009-05-30"
#define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_COPYRIGHT ": Igor Pavlov : Public domain"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

12
C/Aes.h
View File

@@ -1,13 +1,15 @@
/* Aes.h -- AES encryption / decryption /* Aes.h -- AES encryption / decryption
2008-08-05 2009-02-07 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __AES_H #ifndef __AES_H
#define __AES_H #define __AES_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define AES_BLOCK_SIZE 16 #define AES_BLOCK_SIZE 16
typedef struct typedef struct
@@ -45,4 +47,8 @@ void AesCbc_Init(CAesCbc *p, const Byte *iv); /* iv size is AES_BLOCK_SIZE */
SizeT AesCbc_Encode(CAesCbc *p, Byte *data, SizeT size); SizeT AesCbc_Encode(CAesCbc *p, Byte *data, SizeT size);
SizeT AesCbc_Decode(CAesCbc *p, Byte *data, SizeT size); SizeT AesCbc_Decode(CAesCbc *p, Byte *data, SizeT size);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,13 +1,15 @@
/* Alloc.h -- Memory allocation functions /* Alloc.h -- Memory allocation functions
2008-03-13 2009-02-07 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __COMMON_ALLOC_H #ifndef __COMMON_ALLOC_H
#define __COMMON_ALLOC_H #define __COMMON_ALLOC_H
#include <stddef.h> #include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void *MyAlloc(size_t size); void *MyAlloc(size_t size);
void MyFree(void *address); void MyFree(void *address);
@@ -29,4 +31,8 @@ void BigFree(void *address);
#endif #endif
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -132,6 +132,14 @@ SOURCE=..\..\Bra86.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Lzma2Dec.c
# End Source File
# Begin Source File
SOURCE=..\..\Lzma2Dec.h
# End Source File
# Begin Source File
SOURCE=..\..\LzmaDec.c SOURCE=..\..\LzmaDec.c
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -1,15 +1,23 @@
/* 7zAlloc.h -- Allocation functions /* 7zAlloc.h -- Allocation functions
2008-10-04 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_ALLOC_H #ifndef __7Z_ALLOC_H
#define __7Z_ALLOC_H #define __7Z_ALLOC_H
#include <stddef.h> #include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void *SzAlloc(void *p, size_t size); void *SzAlloc(void *p, size_t size);
void SzFree(void *p, void *address); void SzFree(void *p, void *address);
void *SzAllocTemp(void *p, size_t size); void *SzAllocTemp(void *p, size_t size);
void SzFreeTemp(void *p, void *address); void SzFreeTemp(void *p, void *address);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,14 +1,17 @@
/* 7zDecode.c -- Decoding from 7z folder /* 7zDecode.c -- Decoding from 7z folder
2008-11-23 : Igor Pavlov : Public domain */ 2009-05-03 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
#include "../../Bcj2.h" #include "../../Bcj2.h"
#include "../../Bra.h" #include "../../Bra.h"
#include "../../LzmaDec.h" #include "../../LzmaDec.h"
#include "../../Lzma2Dec.h"
#include "7zDecode.h" #include "7zDecode.h"
#define k_Copy 0 #define k_Copy 0
#define k_LZMA2 0x21
#define k_LZMA 0x30101 #define k_LZMA 0x30101
#define k_BCJ 0x03030103 #define k_BCJ 0x03030103
#define k_BCJ2 0x0303011B #define k_BCJ2 0x0303011B
@@ -61,6 +64,55 @@ static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt
return res; return res;
} }
static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{
CLzma2Dec state;
SRes res = SZ_OK;
Lzma2Dec_Construct(&state);
if (coder->Props.size != 1)
return SZ_ERROR_DATA;
RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));
state.decoder.dic = outBuffer;
state.decoder.dicBufSize = outSize;
Lzma2Dec_Init(&state);
for (;;)
{
Byte *inBuf = NULL;
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead);
if (res != SZ_OK)
break;
{
SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
ELzmaStatus status;
res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
lookahead -= inProcessed;
inSize -= inProcessed;
if (res != SZ_OK)
break;
if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
{
if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
(status != LZMA_STATUS_FINISHED_WITH_MARK))
res = SZ_ERROR_DATA;
break;
}
res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK)
break;
}
}
Lzma2Dec_FreeProbs(&state, allocMain);
return res;
}
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
{ {
while (inSize > 0) while (inSize > 0)
@@ -80,7 +132,7 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
return SZ_OK; return SZ_OK;
} }
#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) #define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA && (m) != k_LZMA2)
#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) #define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
@@ -152,7 +204,7 @@ SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
{ {
CSzCoderInfo *coder = &folder->Coders[ci]; CSzCoderInfo *coder = &folder->Coders[ci];
if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA || coder->MethodID == k_LZMA2)
{ {
UInt32 si = 0; UInt32 si = 0;
UInt64 offset; UInt64 offset;
@@ -196,10 +248,14 @@ SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
} }
else else if (coder->MethodID == k_LZMA)
{ {
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
} }
else
{
RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
}
} }
else if (coder->MethodID == k_BCJ) else if (coder->MethodID == k_BCJ)
{ {

View File

@@ -1,13 +1,21 @@
/* 7zDecode.h -- Decoding from 7z folder /* 7zDecode.h -- Decoding from 7z folder
2008-11-23 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_DECODE_H #ifndef __7Z_DECODE_H
#define __7Z_DECODE_H #define __7Z_DECODE_H
#include "7zItem.h" #include "7zItem.h"
#ifdef __cplusplus
extern "C" {
#endif
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
ILookInStream *stream, UInt64 startPos, ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,11 +1,15 @@
/* 7zExtract.h -- Extracting from 7z archive /* 7zExtract.h -- Extracting from 7z archive
2008-11-23 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_EXTRACT_H #ifndef __7Z_EXTRACT_H
#define __7Z_EXTRACT_H #define __7Z_EXTRACT_H
#include "7zIn.h" #include "7zIn.h"
#ifdef __cplusplus
extern "C" {
#endif
/* /*
SzExtract extracts file from archive SzExtract extracts file from archive
@@ -38,4 +42,8 @@ SRes SzAr_Extract(
ISzAlloc *allocMain, ISzAlloc *allocMain,
ISzAlloc *allocTemp); ISzAlloc *allocTemp);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,11 +1,15 @@
/* 7zHeader.h -- 7z Headers /* 7zHeader.h -- 7z Headers
2008-10-04 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_HEADER_H #ifndef __7Z_HEADER_H
#define __7Z_HEADER_H #define __7Z_HEADER_H
#include "../../Types.h" #include "../../Types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define k7zSignatureSize 6 #define k7zSignatureSize 6
extern Byte k7zSignature[k7zSignatureSize]; extern Byte k7zSignature[k7zSignatureSize];
@@ -54,4 +58,8 @@ enum EIdEnum
k7zIdDummy k7zIdDummy
}; };
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,5 +1,5 @@
/* 7zIn.h -- 7z Input functions /* 7zIn.h -- 7z Input
2008-11-23 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_IN_H #ifndef __7Z_IN_H
#define __7Z_IN_H #define __7Z_IN_H
@@ -7,6 +7,10 @@
#include "7zHeader.h" #include "7zHeader.h"
#include "7zItem.h" #include "7zItem.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct typedef struct
{ {
CSzAr db; CSzAr db;
@@ -38,4 +42,8 @@ SZ_ERROR_FAIL
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,11 +1,15 @@
/* 7zItem.h -- 7z Items /* 7zItem.h -- 7z Items
2008-10-04 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_ITEM_H #ifndef __7Z_ITEM_H
#define __7Z_ITEM_H #define __7Z_ITEM_H
#include "../../7zBuf.h" #include "../../7zBuf.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct typedef struct
{ {
UInt32 NumInStreams; UInt32 NumInStreams;
@@ -81,4 +85,8 @@ typedef struct
void SzAr_Init(CSzAr *p); void SzAr_Init(CSzAr *p);
void SzAr_Free(CSzAr *p, ISzAlloc *alloc); void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,5 +1,5 @@
/* 7zMain.c - Test application for 7z Decoder /* 7zMain.c - Test application for 7z Decoder
2008-11-23 : Igor Pavlov : Public domain */ 2009-04-04 : Igor Pavlov : Public domain */
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@@ -13,6 +13,37 @@
#include "7zExtract.h" #include "7zExtract.h"
#include "7zIn.h" #include "7zIn.h"
#ifndef USE_WINDOWS_FILE
/* for mkdir */
#ifdef _WIN32
#include <direct.h>
#else
#include <sys/stat.h>
#include <errno.h>
#endif
#endif
#ifdef _WIN32
#define CHAR_PATH_SEPARATOR '\\'
#else
#define CHAR_PATH_SEPARATOR '/'
#endif
static WRes MyCreateDir(const char *name)
{
#ifdef USE_WINDOWS_FILE
return CreateDirectoryA(name, NULL) ? 0 : GetLastError();
#else
#ifdef _WIN32
return _mkdir(name)
#else
return mkdir(name, 0777)
#endif
== 0 ? 0 : errno;
#endif
}
static void ConvertNumberToString(UInt64 value, char *s) static void ConvertNumberToString(UInt64 value, char *s)
{ {
char temp[32]; char temp[32];
@@ -33,7 +64,7 @@ static void ConvertNumberToString(UInt64 value, char *s)
#define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_100 (PERIOD_4 * 25 - 1)
#define PERIOD_400 (PERIOD_100 * 4 + 1) #define PERIOD_400 (PERIOD_100 * 4 + 1)
static void ConvertFileTimeToString(CNtfsFileTime *ft, char *s) static void ConvertFileTimeToString(const CNtfsFileTime *ft, char *s)
{ {
unsigned year, mon, day, hour, min, sec; unsigned year, mon, day, hour, min, sec;
UInt64 v64 = ft->Low | ((UInt64)ft->High << 32); UInt64 v64 = ft->Low | ((UInt64)ft->High << 32);
@@ -97,16 +128,19 @@ int MY_CDECL main(int numargs, char *args[])
SRes res; SRes res;
ISzAlloc allocImp; ISzAlloc allocImp;
ISzAlloc allocTempImp; ISzAlloc allocTempImp;
char *temp = NULL;
size_t tempSize = 0;
printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n"); printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");
if (numargs == 1) if (numargs == 1)
{ {
printf( printf(
"\nUsage: 7zDec <command> <archive_name>\n\n" "Usage: 7zDec <command> <archive_name>\n\n"
"<Commands>\n" "<Commands>\n"
" e: Extract files from archive\n" " e: Extract files from archive (without using directory names)\n"
" l: List contents of archive\n" " l: List contents of archive\n"
" t: Test integrity of archive\n"); " t: Test integrity of archive\n"
" x: eXtract files with full paths\n");
return 0; return 0;
} }
if (numargs < 3) if (numargs < 3)
@@ -141,17 +175,18 @@ int MY_CDECL main(int numargs, char *args[])
if (res == SZ_OK) if (res == SZ_OK)
{ {
char *command = args[1]; char *command = args[1];
int listCommand = 0, testCommand = 0, extractCommand = 0; int listCommand = 0, testCommand = 0, extractCommand = 0, fullPaths = 0;
if (strcmp(command, "l") == 0) listCommand = 1; if (strcmp(command, "l") == 0) listCommand = 1;
else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "t") == 0) testCommand = 1;
else if (strcmp(command, "e") == 0) extractCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1;
else if (strcmp(command, "x") == 0) { extractCommand = 1; fullPaths = 1; }
if (listCommand) if (listCommand)
{ {
UInt32 i; UInt32 i;
for (i = 0; i < db.db.NumFiles; i++) for (i = 0; i < db.db.NumFiles; i++)
{ {
CSzFileItem *f = db.db.Files + i; const CSzFileItem *f = db.db.Files + i;
char s[32], t[32]; char s[32], t[32];
ConvertNumberToString(f->Size, s); ConvertNumberToString(f->Size, s);
if (f->MTimeDefined) if (f->MTimeDefined)
@@ -159,7 +194,10 @@ int MY_CDECL main(int numargs, char *args[])
else else
strcpy(t, " "); strcpy(t, " ");
printf("%s %10s %s\n", t, s, f->Name); printf("%s %10s %s", t, s, f->Name);
if (f->IsDir)
printf("/");
printf("\n");
} }
} }
else if (testCommand || extractCommand) else if (testCommand || extractCommand)
@@ -174,44 +212,67 @@ int MY_CDECL main(int numargs, char *args[])
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
printf("\n");
for (i = 0; i < db.db.NumFiles; i++) for (i = 0; i < db.db.NumFiles; i++)
{ {
size_t offset; size_t offset;
size_t outSizeProcessed; size_t outSizeProcessed;
CSzFileItem *f = db.db.Files + i; const CSzFileItem *f = db.db.Files + i;
if (f->IsDir) if (f->IsDir && !fullPaths)
printf("Directory "); continue;
else printf(testCommand ?
printf(testCommand ?
"Testing ": "Testing ":
"Extracting"); "Extracting");
printf(" %s", f->Name); printf(" %s", f->Name);
if (f->IsDir) if (f->IsDir)
printf("/");
else
{ {
printf("\n"); res = SzAr_Extract(&db, &lookStream.s, i,
continue; &blockIndex, &outBuffer, &outBufferSize,
&offset, &outSizeProcessed,
&allocImp, &allocTempImp);
if (res != SZ_OK)
break;
} }
res = SzAr_Extract(&db, &lookStream.s, i,
&blockIndex, &outBuffer, &outBufferSize,
&offset, &outSizeProcessed,
&allocImp, &allocTempImp);
if (res != SZ_OK)
break;
if (!testCommand) if (!testCommand)
{ {
CSzFile outFile; CSzFile outFile;
size_t processedSize; size_t processedSize;
char *fileName = f->Name; size_t j, nameLen = strlen(f->Name);
size_t nameLen = strlen(f->Name); const char *destPath;
for (; nameLen > 0; nameLen--) if (nameLen + 1 > tempSize)
if (f->Name[nameLen - 1] == '/') {
SzFree(NULL, temp);
tempSize = nameLen + 1;
temp = (char *)SzAlloc(NULL, tempSize);
if (temp == 0)
{ {
fileName = f->Name + nameLen; res = SZ_ERROR_MEM;
break; break;
} }
}
if (OutFile_Open(&outFile, fileName)) destPath = temp;
strcpy(temp, f->Name);
for (j = 0; j < nameLen; j++)
if (temp[j] == '/')
{
if (fullPaths)
{
temp[j] = 0;
MyCreateDir(temp);
temp[j] = CHAR_PATH_SEPARATOR;
}
else
destPath = temp + j + 1;
}
if (f->IsDir)
{
MyCreateDir(destPath);
printf("\n");
continue;
}
else if (OutFile_Open(&outFile, destPath))
{ {
PrintError("can not open output file"); PrintError("can not open output file");
res = SZ_ERROR_FAIL; res = SZ_ERROR_FAIL;
@@ -243,6 +304,7 @@ int MY_CDECL main(int numargs, char *args[])
} }
} }
SzArEx_Free(&db, &allocImp); SzArEx_Free(&db, &allocImp);
SzFree(NULL, temp);
File_Close(&archiveStream.file); File_Close(&archiveStream.file);
if (res == SZ_OK) if (res == SZ_OK)

View File

@@ -7,6 +7,7 @@ C_OBJS = \
$O\7zBuf2.obj \ $O\7zBuf2.obj \
$O\7zCrc.obj \ $O\7zCrc.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
$O\Lzma2Dec.obj \
$O\Bra86.obj \ $O\Bra86.obj \
$O\Bcj2.obj \ $O\Bcj2.obj \
$O\7zFile.obj \ $O\7zFile.obj \

View File

@@ -4,7 +4,7 @@ LIB =
RM = rm -f RM = rm -f
CFLAGS = -c -O2 -Wall CFLAGS = -c -O2 -Wall
OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o LzmaDec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o LzmaDec.o Lzma2Dec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o
all: $(PROG) all: $(PROG)
@@ -44,6 +44,9 @@ $(PROG): $(OBJS)
LzmaDec.o: ../../LzmaDec.c LzmaDec.o: ../../LzmaDec.c
$(CXX) $(CFLAGS) ../../LzmaDec.c $(CXX) $(CFLAGS) ../../LzmaDec.c
Lzma2Dec.o: ../../Lzma2Dec.c
$(CXX) $(CFLAGS) ../../Lzma2Dec.c
Bra86.o: ../../Bra86.c Bra86.o: ../../Bra86.c
$(CXX) $(CFLAGS) ../../Bra86.c $(CXX) $(CFLAGS) ../../Bra86.c

View File

@@ -1,11 +1,15 @@
/* Bcj2.h -- Converter for x86 code (BCJ2) /* Bcj2.h -- Converter for x86 code (BCJ2)
2008-10-04 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __BCJ2_H #ifndef __BCJ2_H
#define __BCJ2_H #define __BCJ2_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* /*
Conditions: Conditions:
outSize <= FullOutputSize, outSize <= FullOutputSize,
@@ -27,4 +31,8 @@ int Bcj2_Decode(
const Byte *buf3, SizeT size3, const Byte *buf3, SizeT size3,
Byte *outBuf, SizeT outSize); Byte *outBuf, SizeT outSize);
#ifdef __cplusplus
}
#endif
#endif #endif

10
C/Bra.h
View File

@@ -1,11 +1,15 @@
/* Bra.h -- Branch converters for executables /* Bra.h -- Branch converters for executables
2008-10-04 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __BRA_H #ifndef __BRA_H
#define __BRA_H #define __BRA_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* /*
These functions convert relative addresses to absolute addresses These functions convert relative addresses to absolute addresses
in CALL instructions to increase the compression ratio. in CALL instructions to increase the compression ratio.
@@ -57,4 +61,8 @@ SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,13 +1,15 @@
/* BwtSort.h -- BWT block sorting /* BwtSort.h -- BWT block sorting
2008-03-26 2009-02-07 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __BWTSORT_H #ifndef __BWT_SORT_H
#define __BWTSORT_H #define __BWT_SORT_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */ /* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */
/* #define BLOCK_SORT_EXTERNAL_FLAGS */ /* #define BLOCK_SORT_EXTERNAL_FLAGS */
@@ -21,4 +23,8 @@ Public domain */
UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize); UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,10 +1,12 @@
/* CpuArch.h /* CpuArch.h
2008-08-05 2009-03-22 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __CPUARCH_H #ifndef __CPU_ARCH_H
#define __CPUARCH_H #define __CPU_ARCH_H
#ifdef __cplusplus
extern "C" {
#endif
/* /*
LITTLE_ENDIAN_UNALIGN means: LITTLE_ENDIAN_UNALIGN means:
@@ -23,6 +25,7 @@ about these properties of platform.
#define GetUi16(p) (*(const UInt16 *)(p)) #define GetUi16(p) (*(const UInt16 *)(p))
#define GetUi32(p) (*(const UInt32 *)(p)) #define GetUi32(p) (*(const UInt32 *)(p))
#define GetUi64(p) (*(const UInt64 *)(p)) #define GetUi64(p) (*(const UInt64 *)(p))
#define SetUi16(p, d) *(UInt16 *)(p) = (d);
#define SetUi32(p, d) *(UInt32 *)(p) = (d); #define SetUi32(p, d) *(UInt32 *)(p) = (d);
#else #else
@@ -37,6 +40,10 @@ about these properties of platform.
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
#define SetUi16(p, d) { UInt32 _x_ = (d); \
((Byte *)(p))[0] = (Byte)_x_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); }
#define SetUi32(p, d) { UInt32 _x_ = (d); \ #define SetUi32(p, d) { UInt32 _x_ = (d); \
((Byte *)(p))[0] = (Byte)_x_; \ ((Byte *)(p))[0] = (Byte)_x_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
@@ -66,4 +73,8 @@ about these properties of platform.
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) #define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
#ifdef __cplusplus
}
#endif
#endif #endif

62
C/Delta.c Executable file
View File

@@ -0,0 +1,62 @@
/* Delta.c -- Delta converter
2009-05-26 : Igor Pavlov : Public domain */
#include "Delta.h"
void Delta_Init(Byte *state)
{
unsigned i;
for (i = 0; i < DELTA_STATE_SIZE; i++)
state[i] = 0;
}
static void MyMemCpy(Byte *dest, const Byte *src, unsigned size)
{
unsigned i;
for (i = 0; i < size; i++)
dest[i] = src[i];
}
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)
{
Byte buf[DELTA_STATE_SIZE];
unsigned j = 0;
MyMemCpy(buf, state, delta);
{
SizeT i;
for (i = 0; i < size;)
{
for (j = 0; j < delta && i < size; i++, j++)
{
Byte b = data[i];
data[i] = (Byte)(b - buf[j]);
buf[j] = b;
}
}
}
if (j == delta)
j = 0;
MyMemCpy(state, buf + j, delta - j);
MyMemCpy(state + delta - j, buf, j);
}
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)
{
Byte buf[DELTA_STATE_SIZE];
unsigned j = 0;
MyMemCpy(buf, state, delta);
{
SizeT i;
for (i = 0; i < size;)
{
for (j = 0; j < delta && i < size; i++, j++)
{
buf[j] = data[i] = (Byte)(buf[j] + data[i]);
}
}
}
if (j == delta)
j = 0;
MyMemCpy(state, buf + j, delta - j);
MyMemCpy(state + delta - j, buf, j);
}

23
C/Delta.h Executable file
View File

@@ -0,0 +1,23 @@
/* Delta.h -- Delta converter
2009-04-15 : Igor Pavlov : Public domain */
#ifndef __DELTA_H
#define __DELTA_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define DELTA_STATE_SIZE 256
void Delta_Init(Byte *state);
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size);
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,13 +1,15 @@
/* HuffEnc.h -- functions for Huffman encoding /* HuffEnc.h -- Huffman encoding
2008-03-26 2009-02-07 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __HUFFENC_H #ifndef __HUFF_ENC_H
#define __HUFFENC_H #define __HUFF_ENC_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* /*
Conditions: Conditions:
num <= 1024 = 2 ^ NUM_BITS num <= 1024 = 2 ^ NUM_BITS
@@ -18,4 +20,8 @@ Conditions:
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen); void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms /* LzFind.c -- Match finder for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain */ 2009-04-22 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
@@ -58,6 +58,17 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
{ {
if (p->streamEndWasReached || p->result != SZ_OK) if (p->streamEndWasReached || p->result != SZ_OK)
return; return;
if (p->directInput)
{
UInt32 curSize = 0xFFFFFFFF - p->streamPos;
if (curSize > p->directInputRem)
curSize = (UInt32)p->directInputRem;
p->directInputRem -= curSize;
p->streamPos += curSize;
if (p->directInputRem == 0)
p->streamEndWasReached = 1;
return;
}
for (;;) for (;;)
{ {
Byte *dest = p->buffer + (p->streamPos - p->pos); Byte *dest = p->buffer + (p->streamPos - p->pos);
@@ -88,6 +99,8 @@ void MatchFinder_MoveBlock(CMatchFinder *p)
int MatchFinder_NeedMove(CMatchFinder *p) int MatchFinder_NeedMove(CMatchFinder *p)
{ {
if (p->directInput)
return 0;
/* if (p->streamEndWasReached) return 0; */ /* if (p->streamEndWasReached) return 0; */
return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
} }
@@ -112,8 +125,6 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
p->cutValue = 32; p->cutValue = 32;
p->btMode = 1; p->btMode = 1;
p->numHashBytes = 4; p->numHashBytes = 4;
/* p->skipModeBits = 0; */
p->directInput = 0;
p->bigHash = 0; p->bigHash = 0;
} }
@@ -177,7 +188,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
if (LzInWindow_Create(p, sizeReserv, alloc)) if (LzInWindow_Create(p, sizeReserv, alloc))
{ {
UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; UInt32 newCyclicBufferSize = historySize + 1;
UInt32 hs; UInt32 hs;
p->matchMaxLen = matchMaxLen; p->matchMaxLen = matchMaxLen;
{ {
@@ -192,7 +203,6 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
hs |= (hs >> 4); hs |= (hs >> 4);
hs |= (hs >> 8); hs |= (hs >> 8);
hs >>= 1; hs >>= 1;
/* hs >>= p->skipModeBits; */
hs |= 0xFFFF; /* don't change it! It's required for Deflate */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */
if (hs > (1 << 24)) if (hs > (1 << 24))
{ {

View File

@@ -1,11 +1,15 @@
/* LzFind.h -- Match finder for LZ algorithms /* LzFind.h -- Match finder for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain */ 2009-04-22 : Igor Pavlov : Public domain */
#ifndef __LZFIND_H #ifndef __LZ_FIND_H
#define __LZFIND_H #define __LZ_FIND_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef UInt32 CLzRef; typedef UInt32 CLzRef;
typedef struct _CMatchFinder typedef struct _CMatchFinder
@@ -35,8 +39,8 @@ typedef struct _CMatchFinder
UInt32 numHashBytes; UInt32 numHashBytes;
int directInput; int directInput;
size_t directInputRem;
int btMode; int btMode;
/* int skipModeBits; */
int bigHash; int bigHash;
UInt32 historySize; UInt32 historySize;
UInt32 fixedHashSize; UInt32 fixedHashSize;
@@ -104,4 +108,8 @@ UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,5 +1,5 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms /* LzFindMt.c -- multithreaded Match finder for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain */ 2009-05-26 : Igor Pavlov : Public domain */
#include "LzHash.h" #include "LzHash.h"
@@ -143,7 +143,7 @@ DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc;
DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)
DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) /* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */
void HashThreadFunc(CMatchFinderMt *mt) void HashThreadFunc(CMatchFinderMt *mt)
{ {

View File

@@ -1,11 +1,15 @@
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms /* LzFindMt.h -- multithreaded Match finder for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZFINDMT_H #ifndef __LZ_FIND_MT_H
#define __LZFINDMT_H #define __LZ_FIND_MT_H
#include "Threads.h"
#include "LzFind.h" #include "LzFind.h"
#include "Threads.h"
#ifdef __cplusplus
extern "C" {
#endif
#define kMtHashBlockSize (1 << 13) #define kMtHashBlockSize (1 << 13)
#define kMtHashNumBlocks (1 << 3) #define kMtHashNumBlocks (1 << 3)
@@ -94,4 +98,8 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,8 +1,8 @@
/* LzHash.h -- HASH functions for LZ algorithms /* LzHash.h -- HASH functions for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZHASH_H #ifndef __LZ_HASH_H
#define __LZHASH_H #define __LZ_HASH_H
#define kHash2Size (1 << 10) #define kHash2Size (1 << 10)
#define kHash3Size (1 << 16) #define kHash3Size (1 << 16)

356
C/Lzma2Dec.c Executable file
View File

@@ -0,0 +1,356 @@
/* Lzma2Dec.c -- LZMA2 Decoder
2009-05-03 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */
#ifdef SHOW_DEBUG_INFO
#include <stdio.h>
#endif
#include <string.h>
#include "Lzma2Dec.h"
/*
00000000 - EOS
00000001 U U - Uncompressed Reset Dic
00000010 U U - Uncompressed No Reset
100uuuuu U U P P - LZMA no reset
101uuuuu U U P P - LZMA reset state
110uuuuu U U P P S - LZMA reset state + new prop
111uuuuu U U P P S - LZMA reset state + new prop + reset dic
u, U - Unpack Size
P - Pack Size
S - Props
*/
#define LZMA2_CONTROL_LZMA (1 << 7)
#define LZMA2_CONTROL_COPY_NO_RESET 2
#define LZMA2_CONTROL_COPY_RESET_DIC 1
#define LZMA2_CONTROL_EOF 0
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
#define LZMA2_LCLP_MAX 4
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
#ifdef SHOW_DEBUG_INFO
#define PRF(x) x
#else
#define PRF(x)
#endif
typedef enum
{
LZMA2_STATE_CONTROL,
LZMA2_STATE_UNPACK0,
LZMA2_STATE_UNPACK1,
LZMA2_STATE_PACK0,
LZMA2_STATE_PACK1,
LZMA2_STATE_PROP,
LZMA2_STATE_DATA,
LZMA2_STATE_DATA_CONT,
LZMA2_STATE_FINISHED,
LZMA2_STATE_ERROR
} ELzma2State;
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
{
UInt32 dicSize;
if (prop > 40)
return SZ_ERROR_UNSUPPORTED;
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
props[0] = (Byte)LZMA2_LCLP_MAX;
props[1] = (Byte)(dicSize);
props[2] = (Byte)(dicSize >> 8);
props[3] = (Byte)(dicSize >> 16);
props[4] = (Byte)(dicSize >> 24);
return SZ_OK;
}
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
{
Byte props[LZMA_PROPS_SIZE];
RINOK(Lzma2Dec_GetOldProps(prop, props));
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
}
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
{
Byte props[LZMA_PROPS_SIZE];
RINOK(Lzma2Dec_GetOldProps(prop, props));
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
}
void Lzma2Dec_Init(CLzma2Dec *p)
{
p->state = LZMA2_STATE_CONTROL;
p->needInitDic = True;
p->needInitState = True;
p->needInitProp = True;
LzmaDec_Init(&p->decoder);
}
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
{
switch(p->state)
{
case LZMA2_STATE_CONTROL:
p->control = b;
PRF(printf("\n %4X ", p->decoder.dicPos));
PRF(printf(" %2X", b));
if (p->control == 0)
return LZMA2_STATE_FINISHED;
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{
if ((p->control & 0x7F) > 2)
return LZMA2_STATE_ERROR;
p->unpackSize = 0;
}
else
p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
return LZMA2_STATE_UNPACK0;
case LZMA2_STATE_UNPACK0:
p->unpackSize |= (UInt32)b << 8;
return LZMA2_STATE_UNPACK1;
case LZMA2_STATE_UNPACK1:
p->unpackSize |= (UInt32)b;
p->unpackSize++;
PRF(printf(" %8d", p->unpackSize));
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
case LZMA2_STATE_PACK0:
p->packSize = (UInt32)b << 8;
return LZMA2_STATE_PACK1;
case LZMA2_STATE_PACK1:
p->packSize |= (UInt32)b;
p->packSize++;
PRF(printf(" %8d", p->packSize));
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
case LZMA2_STATE_PROP:
{
int lc, lp;
if (b >= (9 * 5 * 5))
return LZMA2_STATE_ERROR;
lc = b % 9;
b /= 9;
p->decoder.prop.pb = b / 5;
lp = b % 5;
if (lc + lp > LZMA2_LCLP_MAX)
return LZMA2_STATE_ERROR;
p->decoder.prop.lc = lc;
p->decoder.prop.lp = lp;
p->needInitProp = False;
return LZMA2_STATE_DATA;
}
}
return LZMA2_STATE_ERROR;
}
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
{
memcpy(p->dic + p->dicPos, src, size);
p->dicPos += size;
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
p->checkDicSize = p->prop.dicSize;
p->processedPos += (UInt32)size;
}
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT inSize = *srcLen;
*srcLen = 0;
*status = LZMA_STATUS_NOT_SPECIFIED;
while (p->state != LZMA2_STATE_FINISHED)
{
SizeT dicPos = p->decoder.dicPos;
if (p->state == LZMA2_STATE_ERROR)
return SZ_ERROR_DATA;
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
{
*status = LZMA_STATUS_NOT_FINISHED;
return SZ_OK;
}
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
{
if (*srcLen == inSize)
{
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
(*srcLen)++;
p->state = Lzma2Dec_UpdateState(p, *src++);
continue;
}
{
SizeT destSizeCur = dicLimit - dicPos;
SizeT srcSizeCur = inSize - *srcLen;
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
if (p->unpackSize <= destSizeCur)
{
destSizeCur = (SizeT)p->unpackSize;
curFinishMode = LZMA_FINISH_END;
}
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{
if (*srcLen == inSize)
{
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
if (p->state == LZMA2_STATE_DATA)
{
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
if (initDic)
p->needInitProp = p->needInitState = True;
else if (p->needInitDic)
return SZ_ERROR_DATA;
p->needInitDic = False;
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
}
if (srcSizeCur > destSizeCur)
srcSizeCur = destSizeCur;
if (srcSizeCur == 0)
return SZ_ERROR_DATA;
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
src += srcSizeCur;
*srcLen += srcSizeCur;
p->unpackSize -= (UInt32)srcSizeCur;
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
}
else
{
SizeT outSizeProcessed;
SRes res;
if (p->state == LZMA2_STATE_DATA)
{
int mode = LZMA2_GET_LZMA_MODE(p);
Bool initDic = (mode == 3);
Bool initState = (mode > 0);
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
return SZ_ERROR_DATA;
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
p->needInitDic = False;
p->needInitState = False;
p->state = LZMA2_STATE_DATA_CONT;
}
if (srcSizeCur > p->packSize)
srcSizeCur = (SizeT)p->packSize;
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
src += srcSizeCur;
*srcLen += srcSizeCur;
p->packSize -= (UInt32)srcSizeCur;
outSizeProcessed = p->decoder.dicPos - dicPos;
p->unpackSize -= (UInt32)outSizeProcessed;
RINOK(res);
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
return res;
if (srcSizeCur == 0 && outSizeProcessed == 0)
{
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
p->unpackSize != 0 || p->packSize != 0)
return SZ_ERROR_DATA;
p->state = LZMA2_STATE_CONTROL;
}
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
*status = LZMA_STATUS_NOT_FINISHED;
}
}
}
*status = LZMA_STATUS_FINISHED_WITH_MARK;
return SZ_OK;
}
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT outSize = *destLen, inSize = *srcLen;
*srcLen = *destLen = 0;
for (;;)
{
SizeT srcSizeCur = inSize, outSizeCur, dicPos;
ELzmaFinishMode curFinishMode;
SRes res;
if (p->decoder.dicPos == p->decoder.dicBufSize)
p->decoder.dicPos = 0;
dicPos = p->decoder.dicPos;
if (outSize > p->decoder.dicBufSize - dicPos)
{
outSizeCur = p->decoder.dicBufSize;
curFinishMode = LZMA_FINISH_ANY;
}
else
{
outSizeCur = dicPos + outSize;
curFinishMode = finishMode;
}
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
src += srcSizeCur;
inSize -= srcSizeCur;
*srcLen += srcSizeCur;
outSizeCur = p->decoder.dicPos - dicPos;
memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
dest += outSizeCur;
outSize -= outSizeCur;
*destLen += outSizeCur;
if (res != 0)
return res;
if (outSizeCur == 0 || outSize == 0)
return SZ_OK;
}
}
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
{
CLzma2Dec decoder;
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));
*srcLen = inSize;
res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
*destLen = decoder.decoder.dicPos;
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
res = SZ_ERROR_INPUT_EOF;
LzmaDec_FreeProbs(&decoder.decoder, alloc);
return res;
}

84
C/Lzma2Dec.h Executable file
View File

@@ -0,0 +1,84 @@
/* Lzma2Dec.h -- LZMA2 Decoder
2009-05-03 : Igor Pavlov : Public domain */
#ifndef __LZMA2_DEC_H
#define __LZMA2_DEC_H
#include "LzmaDec.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ---------- State Interface ---------- */
typedef struct
{
CLzmaDec decoder;
UInt32 packSize;
UInt32 unpackSize;
int state;
Byte control;
Bool needInitDic;
Bool needInitState;
Bool needInitProp;
} CLzma2Dec;
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
void Lzma2Dec_Init(CLzma2Dec *p);
/*
finishMode:
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_NEEDS_MORE_INPUT
SZ_ERROR_DATA - Data error
*/
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- One Call Interface ---------- */
/*
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
#ifdef __cplusplus
}
#endif
#endif

484
C/Lzma2Enc.c Executable file
View File

@@ -0,0 +1,484 @@
/* Lzma2Enc.c -- LZMA2 Encoder
2009-05-26 : Igor Pavlov : Public domain */
/* #include <stdio.h> */
#include <string.h>
#include "Lzma2Enc.h"
/* #define COMPRESS_MT */
#ifdef COMPRESS_MT
#include "MtCoder.h"
#else
#define NUM_MT_CODER_THREADS_MAX 1
#endif
#define LZMA2_CONTROL_LZMA (1 << 7)
#define LZMA2_CONTROL_COPY_NO_RESET 2
#define LZMA2_CONTROL_COPY_RESET_DIC 1
#define LZMA2_CONTROL_EOF 0
#define LZMA2_LCLP_MAX 4
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
#define LZMA2_PACK_SIZE_MAX (1 << 16)
#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX
#define LZMA2_UNPACK_SIZE_MAX (1 << 21)
#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX
#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16)
#define PRF(x) /* x */
/* ---------- CLzma2EncInt ---------- */
typedef struct
{
CLzmaEncHandle enc;
UInt64 srcPos;
Byte props;
Bool needInitState;
Bool needInitProp;
} CLzma2EncInt;
static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props)
{
Byte propsEncoded[LZMA_PROPS_SIZE];
SizeT propsSize = LZMA_PROPS_SIZE;
RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
p->srcPos = 0;
p->props = propsEncoded[0];
p->needInitState = True;
p->needInitProp = True;
return SZ_OK;
}
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
ISzAlloc *alloc, ISzAlloc *allocBig);
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig);
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
void LzmaEnc_Finish(CLzmaEncHandle pp);
void LzmaEnc_SaveState(CLzmaEncHandle pp);
void LzmaEnc_RestoreState(CLzmaEncHandle pp);
static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
size_t *packSizeRes, ISeqOutStream *outStream)
{
size_t packSizeLimit = *packSizeRes;
size_t packSize = packSizeLimit;
UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;
unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);
Bool useCopyBlock;
SRes res;
*packSizeRes = 0;
if (packSize < lzHeaderSize)
return SZ_ERROR_OUTPUT_EOF;
packSize -= lzHeaderSize;
LzmaEnc_SaveState(p->enc);
res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,
outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);
PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize));
if (unpackSize == 0)
return res;
if (res == SZ_OK)
useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16));
else
{
if (res != SZ_ERROR_OUTPUT_EOF)
return res;
res = SZ_OK;
useCopyBlock = True;
}
if (useCopyBlock)
{
size_t destPos = 0;
PRF(printf("################# COPY "));
while (unpackSize > 0)
{
UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
if (packSizeLimit - destPos < u + 3)
return SZ_ERROR_OUTPUT_EOF;
outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);
outBuf[destPos++] = (Byte)((u - 1) >> 8);
outBuf[destPos++] = (Byte)(u - 1);
memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);
unpackSize -= u;
destPos += u;
p->srcPos += u;
if (outStream)
{
*packSizeRes += destPos;
if (outStream->Write(outStream, outBuf, destPos) != destPos)
return SZ_ERROR_WRITE;
destPos = 0;
}
else
*packSizeRes = destPos;
/* needInitState = True; */
}
LzmaEnc_RestoreState(p->enc);
return SZ_OK;
}
{
size_t destPos = 0;
UInt32 u = unpackSize - 1;
UInt32 pm = (UInt32)(packSize - 1);
unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);
PRF(printf(" "));
outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | (u >> 16) & 0x1F);
outBuf[destPos++] = (Byte)(u >> 8);
outBuf[destPos++] = (Byte)u;
outBuf[destPos++] = (Byte)(pm >> 8);
outBuf[destPos++] = (Byte)pm;
if (p->needInitProp)
outBuf[destPos++] = p->props;
p->needInitProp = False;
p->needInitState = False;
destPos += packSize;
p->srcPos += unpackSize;
if (outStream)
if (outStream->Write(outStream, outBuf, destPos) != destPos)
return SZ_ERROR_WRITE;
*packSizeRes = destPos;
return SZ_OK;
}
}
/* ---------- Lzma2 Props ---------- */
void Lzma2EncProps_Init(CLzma2EncProps *p)
{
LzmaEncProps_Init(&p->lzmaProps);
p->numTotalThreads = -1;
p->numBlockThreads = -1;
p->blockSize = 0;
}
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
{
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
}
/* ---------- Lzma2 ---------- */
extern struct _CLzma2Enc;
typedef struct _CLzma2Enc
{
Byte propEncoded;
CLzma2EncProps props;
Byte *outBuf;
ISzAlloc *alloc;
ISzAlloc *allocBig;
CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX];
#ifdef COMPRESS_MT
CMtCoder mtCoder;
#endif
} CLzma2Enc;
/* ---------- Lzma2EncThread ---------- */
static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
{
UInt64 packTotal = 0;
SRes res = SZ_OK;
if (mainEncoder->outBuf == 0)
{
mainEncoder->outBuf = IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
if (mainEncoder->outBuf == 0)
return SZ_ERROR_MEM;
}
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,
mainEncoder->alloc, mainEncoder->allocBig));
for (;;)
{
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream);
if (res != SZ_OK)
break;
packTotal += packSize;
res = Progress(progress, p->srcPos, packTotal);
if (res != SZ_OK)
break;
if (packSize == 0)
break;
}
LzmaEnc_Finish(p->enc);
if (res == SZ_OK)
{
Byte b = 0;
if (outStream->Write(outStream, &b, 1) != 1)
return SZ_ERROR_WRITE;
}
return res;
}
#ifdef COMPRESS_MT
typedef struct
{
IMtCoderCallback funcTable;
CLzma2Enc *lzma2Enc;
} CMtCallbackImp;
static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize,
const Byte *src, size_t srcSize, int finished)
{
CMtCallbackImp *imp = (CMtCallbackImp *)pp;
CLzma2Enc *mainEncoder = imp->lzma2Enc;
CLzma2EncInt *p = &mainEncoder->coders[index];
SRes res = SZ_OK;
{
size_t destLim = *destSize;
*destSize = 0;
if (srcSize != 0)
{
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE,
mainEncoder->alloc, mainEncoder->allocBig));
while (p->srcPos < srcSize)
{
size_t packSize = destLim - *destSize;
res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL);
if (res != SZ_OK)
break;
*destSize += packSize;
if (packSize == 0)
{
res = SZ_ERROR_FAIL;
break;
}
if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK)
{
res = SZ_ERROR_PROGRESS;
break;
}
}
LzmaEnc_Finish(p->enc);
if (res != SZ_OK)
return res;
}
if (finished)
{
if (*destSize == destLim)
return SZ_ERROR_OUTPUT_EOF;
dest[(*destSize)++] = 0;
}
}
return res;
}
#endif
/* ---------- Lzma2Enc ---------- */
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
{
CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));
if (p == 0)
return NULL;
Lzma2EncProps_Init(&p->props);
Lzma2EncProps_Normalize(&p->props);
p->outBuf = 0;
p->alloc = alloc;
p->allocBig = allocBig;
{
unsigned i;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
p->coders[i].enc = 0;
}
#ifdef COMPRESS_MT
MtCoder_Construct(&p->mtCoder);
#endif
return p;
}
void Lzma2Enc_Destroy(CLzma2EncHandle pp)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
unsigned i;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
{
CLzma2EncInt *t = &p->coders[i];
if (t->enc)
{
LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
t->enc = 0;
}
}
#ifdef COMPRESS_MT
MtCoder_Destruct(&p->mtCoder);
#endif
IAlloc_Free(p->alloc, p->outBuf);
IAlloc_Free(p->alloc, pp);
}
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
{
int t1, t1n, t2, t3;
CLzmaEncProps lzmaProps = p->lzmaProps;
LzmaEncProps_Normalize(&lzmaProps);
t1 = p->lzmaProps.numThreads;
t1n = lzmaProps.numThreads;
t2 = p->numBlockThreads;
t3 = p->numTotalThreads;
#ifdef COMPRESS_MT
if (t2 > NUM_MT_CODER_THREADS_MAX)
t2 = NUM_MT_CODER_THREADS_MAX;
#else
t2 = 1;
#endif
if (t3 <= 0)
{
if (t2 <= 0)
t2 = 1;
t3 = t1n * t2;
}
else
{
if (t2 <= 0)
{
t2 = t3 / t1n;
if (t2 == 0)
{
t1 = 1;
t2 = t3;
}
}
else if (t1 <= 0)
{
t1 = t3 / t2;
if (t1 == 0)
t1 = 1;
}
else
t3 = t1n * t2;
}
p->lzmaProps.numThreads = t1;
p->numBlockThreads = t2;
p->numTotalThreads = t3;
LzmaEncProps_Normalize(&p->lzmaProps);
if (p->blockSize == 0)
{
UInt64 blockSize = (UInt64)lzmaProps.dictSize << 2;
const UInt32 kMinSize = (UInt32)1 << 20;
const UInt32 kMaxSize = (UInt32)1 << 28;
if (blockSize < kMinSize) blockSize = kMinSize;
if (blockSize > kMaxSize) blockSize = kMaxSize;
if (blockSize < lzmaProps.dictSize)
blockSize = lzmaProps.dictSize;
p->blockSize = (size_t)blockSize;
}
}
SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
CLzmaEncProps lzmaProps = props->lzmaProps;
LzmaEncProps_Normalize(&lzmaProps);
if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)
return SZ_ERROR_PARAM;
p->props = *props;
Lzma2EncProps_Normalize(&p->props);
return SZ_OK;
}
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
unsigned i;
UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);
for (i = 0; i < 40; i++)
if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))
break;
return (Byte)i;
}
SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
int i;
for (i = 0; i < p->props.numBlockThreads; i++)
{
CLzma2EncInt *t = &p->coders[i];
if (t->enc == NULL)
{
t->enc = LzmaEnc_Create(p->alloc);
if (t->enc == NULL)
return SZ_ERROR_MEM;
}
}
#ifdef COMPRESS_MT
if (p->props.numBlockThreads <= 1)
#endif
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
#ifdef COMPRESS_MT
{
CMtCallbackImp mtCallback;
mtCallback.funcTable.Code = MtCallbackImp_Code;
mtCallback.lzma2Enc = p;
p->mtCoder.progress = progress;
p->mtCoder.inStream = inStream;
p->mtCoder.outStream = outStream;
p->mtCoder.alloc = p->alloc;
p->mtCoder.mtCallback = &mtCallback.funcTable;
p->mtCoder.blockSize = p->props.blockSize;
p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;
p->mtCoder.numThreads = p->props.numBlockThreads;
return MtCoder_Code(&p->mtCoder);
}
#endif
}

66
C/Lzma2Enc.h Executable file
View File

@@ -0,0 +1,66 @@
/* Lzma2Enc.h -- LZMA2 Encoder
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZMA2_ENC_H
#define __LZMA2_ENC_H
#include "LzmaEnc.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
CLzmaEncProps lzmaProps;
size_t blockSize;
int numBlockThreads;
int numTotalThreads;
} CLzma2EncProps;
void Lzma2EncProps_Init(CLzma2EncProps *p);
void Lzma2EncProps_Normalize(CLzma2EncProps *p);
/* ---------- CLzmaEnc2Handle Interface ---------- */
/* Lzma2Enc_* functions can return the following exit codes:
Returns:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater in props
SZ_ERROR_WRITE - Write callback error
SZ_ERROR_PROGRESS - some break from progress callback
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
*/
typedef void * CLzma2EncHandle;
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig);
void Lzma2Enc_Destroy(CLzma2EncHandle p);
SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);
SRes Lzma2Enc_Encode(CLzma2EncHandle p,
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress);
/* ---------- One Call Interface ---------- */
/* Lzma2Encode
Return code:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater
SZ_ERROR_OUTPUT_EOF - output buffer overflow
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
*/
/*
SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
*/
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,11 +1,15 @@
/* LzmaDec.h -- LZMA Decoder /* LzmaDec.h -- LZMA Decoder
2008-10-04 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZMADEC_H #ifndef __LZMA_DEC_H
#define __LZMADEC_H #define __LZMA_DEC_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* #define _LZMA_PROB32 */ /* #define _LZMA_PROB32 */
/* _LZMA_PROB32 can increase the speed on some CPUs, /* _LZMA_PROB32 can increase the speed on some CPUs,
but memory usage for CLzmaDec::probs will be doubled in that case */ but memory usage for CLzmaDec::probs will be doubled in that case */
@@ -220,4 +224,8 @@ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAlloc *alloc); ELzmaStatus *status, ISzAlloc *alloc);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder /* LzmaEnc.c -- LZMA Encoder
2009-02-02 : Igor Pavlov : Public domain */ 2009-04-22 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
@@ -139,7 +139,7 @@ void LzmaEnc_FastPosInit(Byte *g_FastPos)
typedef unsigned CState; typedef unsigned CState;
typedef struct _COptimal typedef struct
{ {
UInt32 price; UInt32 price;
@@ -218,7 +218,7 @@ typedef struct
UInt32 counters[LZMA_NUM_PB_STATES_MAX]; UInt32 counters[LZMA_NUM_PB_STATES_MAX];
} CLenPriceEnc; } CLenPriceEnc;
typedef struct _CRangeEnc typedef struct
{ {
UInt32 range; UInt32 range;
Byte cache; Byte cache;
@@ -232,26 +232,6 @@ typedef struct _CRangeEnc
SRes res; SRes res;
} CRangeEnc; } CRangeEnc;
typedef struct _CSeqInStreamBuf
{
ISeqInStream funcTable;
const Byte *data;
SizeT rem;
} CSeqInStreamBuf;
static SRes MyRead(void *pp, void *data, size_t *size)
{
size_t curSize = *size;
CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp;
if (p->rem < curSize)
curSize = p->rem;
memcpy(data, p->data, curSize);
p->rem -= curSize;
p->data += curSize;
*size = curSize;
return SZ_OK;
}
typedef struct typedef struct
{ {
CLzmaProb *litProbs; CLzmaProb *litProbs;
@@ -274,7 +254,7 @@ typedef struct
UInt32 state; UInt32 state;
} CSaveState; } CSaveState;
typedef struct _CLzmaEnc typedef struct
{ {
IMatchFinder matchFinder; IMatchFinder matchFinder;
void *matchFinderObj; void *matchFinderObj;
@@ -351,8 +331,7 @@ typedef struct _CLzmaEnc
UInt32 dictSize; UInt32 dictSize;
UInt32 matchFinderCycles; UInt32 matchFinderCycles;
ISeqInStream *inStream; int needInit;
CSeqInStreamBuf seqBufInStream;
CSaveState saveState; CSaveState saveState;
} CLzmaEnc; } CLzmaEnc;
@@ -1754,11 +1733,10 @@ void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
{ {
UInt32 nowPos32, startPos32; UInt32 nowPos32, startPos32;
if (p->inStream != 0) if (p->needInit)
{ {
p->matchFinderBase.stream = p->inStream;
p->matchFinder.Init(p->matchFinderObj); p->matchFinder.Init(p->matchFinderObj);
p->inStream = 0; p->needInit = 0;
} }
if (p->finished) if (p->finished)
@@ -2056,11 +2034,12 @@ static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *a
return SZ_OK; return SZ_OK;
} }
static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
ISzAlloc *alloc, ISzAlloc *allocBig) ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEnc *p = (CLzmaEnc *)pp;
p->inStream = inStream; p->matchFinderBase.stream = inStream;
p->needInit = 1;
p->rc.outStream = outStream; p->rc.outStream = outStream;
return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
} }
@@ -2070,15 +2049,16 @@ SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
ISzAlloc *alloc, ISzAlloc *allocBig) ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEnc *p = (CLzmaEnc *)pp;
p->inStream = inStream; p->matchFinderBase.stream = inStream;
p->needInit = 1;
return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
} }
static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
{ {
p->seqBufInStream.funcTable.Read = MyRead; p->matchFinderBase.directInput = 1;
p->seqBufInStream.data = src; p->matchFinderBase.bufferBase = (Byte *)src;
p->seqBufInStream.rem = srcLen; p->matchFinderBase.directInputRem = srcLen;
} }
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
@@ -2086,7 +2066,8 @@ SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
{ {
CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEnc *p = (CLzmaEnc *)pp;
LzmaEnc_SetInputBuf(p, src, srcLen); LzmaEnc_SetInputBuf(p, src, srcLen);
p->inStream = &p->seqBufInStream.funcTable; p->needInit = 1;
return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
} }
@@ -2101,7 +2082,7 @@ void LzmaEnc_Finish(CLzmaEncHandle pp)
#endif #endif
} }
typedef struct _CSeqOutStreamBuf typedef struct
{ {
ISeqOutStream funcTable; ISeqOutStream funcTable;
Byte *data; Byte *data;
@@ -2170,10 +2151,8 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
return res; return res;
} }
SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
CLzmaEnc *p = (CLzmaEnc *)pp;
SRes res = SZ_OK; SRes res = SZ_OK;
#ifdef COMPRESS_MF_MT #ifdef COMPRESS_MF_MT
@@ -2183,8 +2162,6 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i
allocaDummy[i] = (Byte)i; allocaDummy[i] = (Byte)i;
#endif #endif
RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig));
for (;;) for (;;)
{ {
res = LzmaEnc_CodeOneBlock(p, False, 0, 0); res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
@@ -2200,10 +2177,17 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i
} }
} }
} }
LzmaEnc_Finish(pp); LzmaEnc_Finish(p);
return res; return res;
} }
SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
ISzAlloc *alloc, ISzAlloc *allocBig)
{
RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));
return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
}
SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
{ {
CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEnc *p = (CLzmaEnc *)pp;
@@ -2249,8 +2233,11 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
outStream.overflow = False; outStream.overflow = False;
p->writeEndMark = writeEndMark; p->writeEndMark = writeEndMark;
res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable,
progress, alloc, allocBig); p->rc.outStream = &outStream.funcTable;
res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
if (res == SZ_OK)
res = LzmaEnc_Encode2(p, progress);
*destLen -= outStream.rem; *destLen -= outStream.rem;
if (outStream.overflow) if (outStream.overflow)

View File

@@ -1,11 +1,15 @@
/* LzmaEnc.h -- LZMA Encoder /* LzmaEnc.h -- LZMA Encoder
2008-10-04 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZMAENC_H #ifndef __LZMA_ENC_H
#define __LZMAENC_H #define __LZMA_ENC_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LZMA_PROPS_SIZE 5 #define LZMA_PROPS_SIZE 5
typedef struct _CLzmaEncProps typedef struct _CLzmaEncProps
@@ -69,4 +73,8 @@ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,20 +1,16 @@
/* LzmaLib.h -- LZMA library interface /* LzmaLib.h -- LZMA library interface
2008-08-05 2009-04-07 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __LZMALIB_H #ifndef __LZMA_LIB_H
#define __LZMALIB_H #define __LZMA_LIB_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus #ifdef __cplusplus
#define MY_EXTERN_C extern "C" extern "C" {
#else
#define MY_EXTERN_C extern
#endif #endif
#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL #define MY_STDAPI int MY_STD_CALL
#define LZMA_PROPS_SIZE 5 #define LZMA_PROPS_SIZE 5
@@ -132,4 +128,8 @@ Returns:
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
const unsigned char *props, size_t propsSize); const unsigned char *props, size_t propsSize);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,13 +1,15 @@
/* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder /* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder
2008-08-05 2009-02-07 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __LZMA86DEC_H #ifndef __LZMA86_DEC_H
#define __LZMA86DEC_H #define __LZMA86_DEC_H
#include "../Types.h" #include "../Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* /*
Lzma86_GetUnpackSize: Lzma86_GetUnpackSize:
In: In:
@@ -42,4 +44,8 @@ Lzma86_Decode:
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,13 +1,15 @@
/* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder /* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder
2008-08-05 2009-02-07 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __LZMA86ENC_H #ifndef __LZMA86_ENC_H
#define __LZMA86ENC_H #define __LZMA86_ENC_H
#include "../Types.h" #include "../Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* /*
It's an example for LZMA + x86 Filter use. It's an example for LZMA + x86 Filter use.
You can use .lzma86 extension, if you write that stream to file. You can use .lzma86 extension, if you write that stream to file.
@@ -69,4 +71,8 @@ enum ESzFilterMode
SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
int level, UInt32 dictSize, int filterMode); int level, UInt32 dictSize, int filterMode);
#ifdef __cplusplus
}
#endif
#endif #endif

327
C/MtCoder.c Executable file
View File

@@ -0,0 +1,327 @@
/* MtCoder.c -- Multi-thread Coder
2009-03-26 : Igor Pavlov : Public domain */
#include <stdio.h>
#include "MtCoder.h"
void LoopThread_Construct(CLoopThread *p)
{
Thread_Construct(&p->thread);
Event_Construct(&p->startEvent);
Event_Construct(&p->finishedEvent);
}
void LoopThread_Close(CLoopThread *p)
{
Thread_Close(&p->thread);
Event_Close(&p->startEvent);
Event_Close(&p->finishedEvent);
}
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp)
{
CLoopThread *p = (CLoopThread *)pp;
for (;;)
{
if (Event_Wait(&p->startEvent) != 0)
return SZ_ERROR_THREAD;
if (p->stop)
return 0;
p->res = p->func(p->param);
if (Event_Set(&p->finishedEvent) != 0)
return SZ_ERROR_THREAD;
}
}
WRes LoopThread_Create(CLoopThread *p)
{
p->stop = 0;
RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent));
RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent));
return Thread_Create(&p->thread, LoopThreadFunc, p);
}
WRes LoopThread_StopAndWait(CLoopThread *p)
{
p->stop = 1;
if (Event_Set(&p->startEvent) != 0)
return SZ_ERROR_THREAD;
return Thread_Wait(&p->thread);
}
WRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); }
WRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); }
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
{
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
}
static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)
{
unsigned i;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
p->inSizes[i] = p->outSizes[i] = 0;
p->totalInSize = p->totalOutSize = 0;
p->progress = progress;
p->res = SZ_OK;
}
static void MtProgress_Reinit(CMtProgress *p, unsigned index)
{
p->inSizes[index] = 0;
p->outSizes[index] = 0;
}
#define UPDATE_PROGRESS(size, prev, total) \
if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; }
SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize)
{
SRes res;
CriticalSection_Enter(&p->cs);
UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize)
UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize)
if (p->res == SZ_OK)
p->res = Progress(p->progress, p->totalInSize, p->totalOutSize);
res = p->res;
CriticalSection_Leave(&p->cs);
return res;
}
static void MtProgress_SetError(CMtProgress *p, SRes res)
{
CriticalSection_Enter(&p->cs);
if (p->res == SZ_OK)
p->res = res;
CriticalSection_Leave(&p->cs);
}
static void MtCoder_SetError(CMtCoder* p, SRes res)
{
CriticalSection_Enter(&p->cs);
if (p->res == SZ_OK)
p->res = res;
CriticalSection_Leave(&p->cs);
}
/* ---------- MtThread ---------- */
void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)
{
p->mtCoder = mtCoder;
p->outBuf = 0;
p->inBuf = 0;
Event_Construct(&p->canRead);
Event_Construct(&p->canWrite);
LoopThread_Construct(&p->thread);
}
#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; }
static void CMtThread_CloseEvents(CMtThread *p)
{
Event_Close(&p->canRead);
Event_Close(&p->canWrite);
}
static void CMtThread_Destruct(CMtThread *p)
{
CMtThread_CloseEvents(p);
if (Thread_WasCreated(&p->thread.thread))
{
LoopThread_StopAndWait(&p->thread);
LoopThread_Close(&p->thread);
}
if (p->mtCoder->alloc)
IAlloc_Free(p->mtCoder->alloc, p->outBuf);
p->outBuf = 0;
if (p->mtCoder->alloc)
IAlloc_Free(p->mtCoder->alloc, p->inBuf);
p->inBuf = 0;
}
#define MY_BUF_ALLOC(buf, size, newSize) \
if (buf == 0 || size != newSize) \
{ IAlloc_Free(p->mtCoder->alloc, buf); \
size = newSize; buf = IAlloc_Alloc(p->mtCoder->alloc, size); \
if (buf == 0) return SZ_ERROR_MEM; }
static SRes CMtThread_Prepare(CMtThread *p)
{
MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize)
MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize)
p->stopReading = False;
p->stopWriting = False;
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead));
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite));
return SZ_OK;
}
static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
{
size_t size = *processedSize;
*processedSize = 0;
while (size != 0)
{
size_t curSize = size;
SRes res = stream->Read(stream, data, &curSize);
*processedSize += curSize;
data += curSize;
size -= curSize;
RINOK(res);
if (curSize == 0)
return SZ_OK;
}
return SZ_OK;
}
#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads - 1 ? 0 : p->index + 1]
static SRes MtThread_Process(CMtThread *p, Bool *stop)
{
CMtThread *next;
*stop = True;
if (Event_Wait(&p->canRead) != 0)
return SZ_ERROR_THREAD;
next = GET_NEXT_THREAD(p);
if (p->stopReading)
{
next->stopReading = True;
return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD;
}
{
size_t size = p->mtCoder->blockSize;
size_t destSize = p->outBufSize;
RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size));
next->stopReading = *stop = (size != p->mtCoder->blockSize);
if (Event_Set(&next->canRead) != 0)
return SZ_ERROR_THREAD;
RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index,
p->outBuf, &destSize, p->inBuf, size, *stop));
MtProgress_Reinit(&p->mtCoder->mtProgress, p->index);
if (Event_Wait(&p->canWrite) != 0)
return SZ_ERROR_THREAD;
if (p->stopWriting)
return SZ_ERROR_FAIL;
if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize)
return SZ_ERROR_WRITE;
return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD;
}
}
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
{
CMtThread *p = (CMtThread *)pp;
for (;;)
{
Bool stop;
CMtThread *next = GET_NEXT_THREAD(p);
SRes res = MtThread_Process(p, &stop);
if (res != SZ_OK)
{
MtCoder_SetError(p->mtCoder, res);
MtProgress_SetError(&p->mtCoder->mtProgress, res);
next->stopReading = True;
next->stopWriting = True;
Event_Set(&next->canRead);
Event_Set(&next->canWrite);
return res;
}
if (stop)
return 0;
}
}
void MtCoder_Construct(CMtCoder* p)
{
unsigned i;
p->alloc = 0;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
{
CMtThread *t = &p->threads[i];
t->index = i;
CMtThread_Construct(t, p);
}
CriticalSection_Init(&p->cs);
CriticalSection_Init(&p->mtProgress.cs);
}
void MtCoder_Destruct(CMtCoder* p)
{
unsigned i;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
CMtThread_Destruct(&p->threads[i]);
CriticalSection_Delete(&p->cs);
CriticalSection_Delete(&p->mtProgress.cs);
}
SRes MtCoder_Code(CMtCoder *p)
{
unsigned i, numThreads = p->numThreads;
SRes res = SZ_OK;
p->res = SZ_OK;
MtProgress_Init(&p->mtProgress, p->progress);
for (i = 0; i < numThreads; i++)
{
RINOK(CMtThread_Prepare(&p->threads[i]));
}
for (i = 0; i < numThreads; i++)
{
CMtThread *t = &p->threads[i];
CLoopThread *lt = &t->thread;
if (!Thread_WasCreated(&lt->thread))
{
lt->func = ThreadFunc;
lt->param = t;
if (LoopThread_Create(lt) != SZ_OK)
{
res = SZ_ERROR_THREAD;
break;
}
}
}
if (res == SZ_OK)
{
unsigned j;
for (i = 0; i < numThreads; i++)
{
CMtThread *t = &p->threads[i];
if (LoopThread_StartSubThread(&t->thread) != SZ_OK || i == 10)
{
res = SZ_ERROR_THREAD;
p->threads[0].stopReading = True;
break;
}
}
Event_Set(&p->threads[0].canWrite);
Event_Set(&p->threads[0].canRead);
for (j = 0; j < i; j++)
LoopThread_WaitSubThread(&p->threads[j].thread);
}
for (i = 0; i < numThreads; i++)
CMtThread_CloseEvents(&p->threads[i]);
return (res == SZ_OK) ? p->res : res;
}

102
C/MtCoder.h Executable file
View File

@@ -0,0 +1,102 @@
/* MtCoder.h -- Multi-thread Coder
2009-03-26 : Igor Pavlov : Public domain */
#ifndef __MT_CODER_H
#define __MT_CODER_H
#include "Threads.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
CThread thread;
CAutoResetEvent startEvent;
CAutoResetEvent finishedEvent;
int stop;
THREAD_FUNC_TYPE func;
LPVOID param;
THREAD_FUNC_RET_TYPE res;
} CLoopThread;
void LoopThread_Construct(CLoopThread *p);
void LoopThread_Close(CLoopThread *p);
WRes LoopThread_Create(CLoopThread *p);
WRes LoopThread_StopAndWait(CLoopThread *p);
WRes LoopThread_StartSubThread(CLoopThread *p);
WRes LoopThread_WaitSubThread(CLoopThread *p);
#ifdef COMPRESS_MT
#define NUM_MT_CODER_THREADS_MAX 32
#else
#define NUM_MT_CODER_THREADS_MAX 1
#endif
typedef struct
{
UInt64 totalInSize;
UInt64 totalOutSize;
ICompressProgress *progress;
SRes res;
CCriticalSection cs;
UInt64 inSizes[NUM_MT_CODER_THREADS_MAX];
UInt64 outSizes[NUM_MT_CODER_THREADS_MAX];
} CMtProgress;
SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize);
struct _CMtCoder;
typedef struct
{
struct _CMtCoder *mtCoder;
Byte *outBuf;
size_t outBufSize;
Byte *inBuf;
size_t inBufSize;
unsigned index;
CLoopThread thread;
Bool stopReading;
Bool stopWriting;
CAutoResetEvent canRead;
CAutoResetEvent canWrite;
} CMtThread;
typedef struct
{
SRes (*Code)(void *p, unsigned index, Byte *dest, size_t *destSize,
const Byte *src, size_t srcSize, int finished);
} IMtCoderCallback;
typedef struct _CMtCoder
{
size_t blockSize;
size_t destBlockSize;
unsigned numThreads;
ISeqInStream *inStream;
ISeqOutStream *outStream;
ICompressProgress *progress;
ISzAlloc *alloc;
IMtCoderCallback *mtCallback;
CCriticalSection cs;
SRes res;
CMtProgress mtProgress;
CMtThread threads[NUM_MT_CODER_THREADS_MAX];
} CMtCoder;
void MtCoder_Construct(CMtCoder* p);
void MtCoder_Destruct(CMtCoder* p);
SRes MtCoder_Code(CMtCoder *p);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,10 +1,8 @@
/* RotateDefs.h -- Rotate functions /* RotateDefs.h -- Rotate functions
2008-08-05 2009-02-07 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __ROTATEDEFS_H #ifndef __ROTATE_DEFS_H
#define __ROTATEDEFS_H #define __ROTATE_DEFS_H
#ifdef _MSC_VER #ifdef _MSC_VER

View File

@@ -1,11 +1,15 @@
/* Crypto/Sha256.h -- SHA-256 Hash function /* Sha256.h -- SHA-256 Hash
2008-10-04 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __CRYPTO_SHA256_H #ifndef __CRYPTO_SHA256_H
#define __CRYPTO_SHA256_H #define __CRYPTO_SHA256_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SHA256_DIGEST_SIZE 32 #define SHA256_DIGEST_SIZE 32
typedef struct typedef struct
@@ -19,4 +23,8 @@ void Sha256_Init(CSha256 *p);
void Sha256_Update(CSha256 *p, const Byte *data, size_t size); void Sha256_Update(CSha256 *p, const Byte *data, size_t size);
void Sha256_Final(CSha256 *p, Byte *digest); void Sha256_Final(CSha256 *p, Byte *digest);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,14 +1,20 @@
/* Sort.h -- Sort functions /* Sort.h -- Sort functions
2008-03-19 2009-02-07 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __7Z_SORT_H #ifndef __7Z_SORT_H
#define __7Z_SORT_H #define __7Z_SORT_H
#include "Types.h" #include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
void HeapSort(UInt32 *p, UInt32 size); void HeapSort(UInt32 *p, UInt32 size);
/* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */ /* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -1,10 +1,9 @@
/* Threads.c -- multithreading library /* Threads.c -- multithreading library
2008-08-05 2009-03-27 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */ #include <process.h>
#include "Threads.h" #include "Threads.h"
#include <process.h>
static WRes GetError() static WRes GetError()
{ {
@@ -15,85 +14,53 @@ static WRes GetError()
WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }
WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
static WRes MyCloseHandle(HANDLE *h) WRes HandlePtr_Close(HANDLE *p)
{ {
if (*h != NULL) if (*p != NULL)
if (!CloseHandle(*h)) if (!CloseHandle(*p))
return GetError(); return GetError();
*h = NULL; *p = NULL;
return 0; return 0;
} }
WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); }
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
{ {
unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
thread->handle = *p =
/* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ /* CreateThread(0, 0, startAddress, param, 0, &threadId); */
(HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);
/* maybe we must use errno here, but probably GetLastError() is also OK. */ /* maybe we must use errno here, but probably GetLastError() is also OK. */
return HandleToWRes(thread->handle); return HandleToWRes(*p);
} }
WRes WaitObject(HANDLE h) WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
{ {
return (WRes)WaitForSingleObject(h, INFINITE); *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);
return HandleToWRes(*p);
} }
WRes Thread_Wait(CThread *thread) WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); }
WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); }
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); }
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); }
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); }
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); }
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
{ {
if (thread->handle == NULL) *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);
return 1; return HandleToWRes(*p);
return WaitObject(thread->handle);
} }
WRes Thread_Close(CThread *thread) static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
{ { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }
return MyCloseHandle(&thread->handle); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)
} { return Semaphore_Release(p, (LONG)num, NULL); }
WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }
WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled)
{
p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL);
return HandleToWRes(p->handle);
}
WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled)
{ return Event_Create(p, TRUE, initialSignaled); }
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p)
{ return ManualResetEvent_Create(p, 0); }
WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled)
{ return Event_Create(p, FALSE, initialSignaled); }
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p)
{ return AutoResetEvent_Create(p, 0); }
WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(p->handle)); }
WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(p->handle)); }
WRes Event_Wait(CEvent *p) { return WaitObject(p->handle); }
WRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); }
WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount)
{
p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL);
return HandleToWRes(p->handle);
}
WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
{
return BOOLToWRes(ReleaseSemaphore(p->handle, releaseCount, previousCount));
}
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount)
{
return Semaphore_Release(p, (LONG)releaseCount, NULL);
}
WRes Semaphore_Release1(CSemaphore *p)
{
return Semaphore_ReleaseN(p, 1);
}
WRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); }
WRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); }
WRes CriticalSection_Init(CCriticalSection *p) WRes CriticalSection_Init(CCriticalSection *p)
{ {
@@ -106,4 +73,3 @@ WRes CriticalSection_Init(CCriticalSection *p)
__except (EXCEPTION_EXECUTE_HANDLER) { return 1; } __except (EXCEPTION_EXECUTE_HANDLER) { return 1; }
return 0; return 0;
} }

View File

@@ -1,68 +1,59 @@
/* Threads.h -- multithreading library /* Threads.h -- multithreading library
2008-11-22 : Igor Pavlov : Public domain */ 2009-03-27 : Igor Pavlov : Public domain */
#ifndef __7Z_THRESDS_H #ifndef __7Z_THREADS_H
#define __7Z_THRESDS_H #define __7Z_THREADS_H
#include "Types.h" #include "Types.h"
typedef struct _CThread #ifdef __cplusplus
{ extern "C" {
HANDLE handle; #endif
} CThread;
#define Thread_Construct(thread) (thread)->handle = NULL WRes HandlePtr_Close(HANDLE *h);
#define Thread_WasCreated(thread) ((thread)->handle != NULL) WRes Handle_WaitObject(HANDLE h);
typedef HANDLE CThread;
#define Thread_Construct(p) *(p) = NULL
#define Thread_WasCreated(p) (*(p) != NULL)
#define Thread_Close(p) HandlePtr_Close(p)
#define Thread_Wait(p) Handle_WaitObject(*(p))
typedef unsigned THREAD_FUNC_RET_TYPE; typedef unsigned THREAD_FUNC_RET_TYPE;
#define THREAD_FUNC_CALL_TYPE MY_STD_CALL #define THREAD_FUNC_CALL_TYPE MY_STD_CALL
#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter); typedef HANDLE CEvent;
WRes Thread_Wait(CThread *thread);
WRes Thread_Close(CThread *thread);
typedef struct _CEvent
{
HANDLE handle;
} CEvent;
typedef CEvent CAutoResetEvent; typedef CEvent CAutoResetEvent;
typedef CEvent CManualResetEvent; typedef CEvent CManualResetEvent;
#define Event_Construct(p) *(p) = NULL
#define Event_IsCreated(p) (*(p) != NULL)
#define Event_Close(p) HandlePtr_Close(p)
#define Event_Wait(p) Handle_WaitObject(*(p))
WRes Event_Set(CEvent *p);
WRes Event_Reset(CEvent *p);
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
#define Event_Construct(event) (event)->handle = NULL typedef HANDLE CSemaphore;
#define Event_IsCreated(event) ((event)->handle != NULL) #define Semaphore_Construct(p) (*p) = NULL
#define Semaphore_Close(p) HandlePtr_Close(p)
WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); #define Semaphore_Wait(p) Handle_WaitObject(*(p))
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
WRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled);
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event);
WRes Event_Set(CEvent *event);
WRes Event_Reset(CEvent *event);
WRes Event_Wait(CEvent *event);
WRes Event_Close(CEvent *event);
typedef struct _CSemaphore
{
HANDLE handle;
} CSemaphore;
#define Semaphore_Construct(p) (p)->handle = NULL
WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount);
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
WRes Semaphore_Release1(CSemaphore *p); WRes Semaphore_Release1(CSemaphore *p);
WRes Semaphore_Wait(CSemaphore *p);
WRes Semaphore_Close(CSemaphore *p);
typedef CRITICAL_SECTION CCriticalSection; typedef CRITICAL_SECTION CCriticalSection;
WRes CriticalSection_Init(CCriticalSection *p); WRes CriticalSection_Init(CCriticalSection *p);
#define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Delete(p) DeleteCriticalSection(p)
#define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p)
#define CriticalSection_Leave(p) LeaveCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p)
#ifdef __cplusplus
}
#endif #endif
#endif

View File

@@ -1,5 +1,5 @@
/* Types.h -- Basic types /* Types.h -- Basic types
2008-11-23 : Igor Pavlov : Public domain */ 2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H #ifndef __7Z_TYPES_H
#define __7Z_TYPES_H #define __7Z_TYPES_H
@@ -10,6 +10,10 @@
#include <windows.h> #include <windows.h>
#endif #endif
#ifdef __cplusplus
extern "C" {
#endif
#define SZ_OK 0 #define SZ_OK 0
#define SZ_ERROR_DATA 1 #define SZ_ERROR_DATA 1
@@ -205,4 +209,8 @@ typedef struct
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
#define IAlloc_Free(p, a) (p)->Free((p), a) #define IAlloc_Free(p, a) (p)->Free((p), a)
#ifdef __cplusplus
}
#endif
#endif #endif

88
C/Xz.c Executable file
View File

@@ -0,0 +1,88 @@
/* Xz.c - Xz
2009-04-15 : Igor Pavlov : Public domain */
#include "7zCrc.h"
#include "CpuArch.h"
#include "Xz.h"
#include "XzCrc64.h"
Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 };
Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' };
unsigned Xz_WriteVarInt(Byte *buf, UInt64 v)
{
unsigned i = 0;
do
{
buf[i++] = (Byte)((v & 0x7F) | 0x80);
v >>= 7;
}
while (v != 0);
buf[i - 1] &= 0x7F;
return i;
}
void Xz_Construct(CXzStream *p)
{
p->numBlocks = p->numBlocksAllocated = 0;
p->blocks = 0;
p->flags = 0;
}
void Xz_Free(CXzStream *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->blocks);
p->numBlocks = p->numBlocksAllocated = 0;
p->blocks = 0;
}
unsigned XzFlags_GetCheckSize(CXzStreamFlags f)
{
int t = XzFlags_GetCheckType(f);
return (t == 0) ? 0 : (4 << ((t - 1) / 3));
}
void XzCheck_Init(CXzCheck *p, int mode)
{
p->mode = mode;
switch (mode)
{
case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break;
case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break;
case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break;
}
}
void XzCheck_Update(CXzCheck *p, const void *data, size_t size)
{
switch (p->mode)
{
case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break;
case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break;
case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break;
}
}
int XzCheck_Final(CXzCheck *p, Byte *digest)
{
switch (p->mode)
{
case XZ_CHECK_CRC32:
SetUi32(digest, CRC_GET_DIGEST(p->crc));
break;
case XZ_CHECK_CRC64:
{
int i;
UInt64 v = CRC64_GET_DIGEST(p->crc64);
for (i = 0; i < 8; i++, v >>= 8)
digest[i] = (Byte)(v & 0xFF);
break;
}
case XZ_CHECK_SHA256:
Sha256_Final(&p->sha, digest);
break;
default:
return 0;
}
return 1;
}

256
C/Xz.h Executable file
View File

@@ -0,0 +1,256 @@
/* Xz.h - Xz interface
2009-04-15 : Igor Pavlov : Public domain */
#ifndef __XZ_H
#define __XZ_H
#include "Sha256.h"
#ifdef __cplusplus
extern "C" {
#endif
#define XZ_ID_Subblock 1
#define XZ_ID_Delta 3
#define XZ_ID_X86 4
#define XZ_ID_PPC 5
#define XZ_ID_IA64 6
#define XZ_ID_ARM 7
#define XZ_ID_ARMT 8
#define XZ_ID_SPARC 9
#define XZ_ID_LZMA2 0x21
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value);
unsigned Xz_WriteVarInt(Byte *buf, UInt64 v);
/* ---------- xz block ---------- */
#define XZ_BLOCK_HEADER_SIZE_MAX 1024
#define XZ_NUM_FILTERS_MAX 4
#define XZ_BF_NUM_FILTERS_MASK 3
#define XZ_BF_PACK_SIZE (1 << 6)
#define XZ_BF_UNPACK_SIZE (1 << 7)
#define XZ_FILTER_PROPS_SIZE_MAX 20
typedef struct
{
UInt64 id;
UInt32 propsSize;
Byte props[XZ_FILTER_PROPS_SIZE_MAX];
} CXzFilter;
typedef struct
{
UInt64 packSize;
UInt64 unpackSize;
Byte flags;
CXzFilter filters[XZ_NUM_FILTERS_MAX];
} CXzBlock;
#define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1)
#define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0)
#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0)
SRes XzBlock_Parse(CXzBlock *p, const Byte *header);
SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes);
/* ---------- xz stream ---------- */
#define XZ_SIG_SIZE 6
#define XZ_FOOTER_SIG_SIZE 2
extern Byte XZ_SIG[XZ_SIG_SIZE];
extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
#define XZ_STREAM_FLAGS_SIZE 2
#define XZ_STREAM_CRC_SIZE 4
#define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE)
#define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4)
#define XZ_CHECK_MASK 0xF
#define XZ_CHECK_NO 0
#define XZ_CHECK_CRC32 1
#define XZ_CHECK_CRC64 4
#define XZ_CHECK_SHA256 10
typedef struct
{
int mode;
UInt32 crc;
UInt64 crc64;
CSha256 sha;
} CXzCheck;
void XzCheck_Init(CXzCheck *p, int mode);
void XzCheck_Update(CXzCheck *p, const void *data, size_t size);
int XzCheck_Final(CXzCheck *p, Byte *digest);
typedef UInt16 CXzStreamFlags;
#define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK)
#define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK)
#define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32)
unsigned XzFlags_GetCheckSize(CXzStreamFlags f);
SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf);
SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream);
typedef struct
{
UInt64 unpackSize;
UInt64 totalSize;
} CXzBlockSizes;
typedef struct
{
CXzStreamFlags flags;
size_t numBlocks;
size_t numBlocksAllocated;
CXzBlockSizes *blocks;
UInt64 startOffset;
} CXzStream;
void Xz_Construct(CXzStream *p);
void Xz_Free(CXzStream *p, ISzAlloc *alloc);
#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1)
UInt64 Xz_GetUnpackSize(const CXzStream *p);
UInt64 Xz_GetPackSize(const CXzStream *p);
typedef struct
{
size_t num;
size_t numAllocated;
CXzStream *streams;
} CXzs;
void Xzs_Construct(CXzs *p);
void Xzs_Free(CXzs *p, ISzAlloc *alloc);
SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc);
UInt64 Xzs_GetNumBlocks(const CXzs *p);
UInt64 Xzs_GetUnpackSize(const CXzs *p);
typedef enum
{
CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */
CODER_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
CODER_STATUS_NOT_FINISHED, /* stream was not finished */
CODER_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
} ECoderStatus;
typedef enum
{
CODER_FINISH_ANY, /* finish at any point */
CODER_FINISH_END /* block must be finished at the end */
} ECoderFinishMode;
typedef struct _IStateCoder
{
void *p;
void (*Free)(void *p, ISzAlloc *alloc);
SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);
void (*Init)(void *p);
SRes (*Code)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished);
} IStateCoder;
#define MIXCODER_NUM_FILTERS_MAX 4
typedef struct
{
ISzAlloc *alloc;
Byte *buf;
int numCoders;
int finished[MIXCODER_NUM_FILTERS_MAX - 1];
size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];
size_t size[MIXCODER_NUM_FILTERS_MAX - 1];
UInt64 ids[MIXCODER_NUM_FILTERS_MAX];
IStateCoder coders[MIXCODER_NUM_FILTERS_MAX];
} CMixCoder;
void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc);
void MixCoder_Free(CMixCoder *p);
void MixCoder_Init(CMixCoder *p);
SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId);
SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, int srcWasFinished,
ECoderFinishMode finishMode, ECoderStatus *status);
typedef enum
{
XZ_STATE_STREAM_HEADER,
XZ_STATE_STREAM_INDEX,
XZ_STATE_STREAM_INDEX_CRC,
XZ_STATE_STREAM_FOOTER,
XZ_STATE_STREAM_PADDING,
XZ_STATE_BLOCK_HEADER,
XZ_STATE_BLOCK,
XZ_STATE_BLOCK_FOOTER
} EXzState;
typedef struct
{
EXzState state;
UInt32 pos;
unsigned alignPos;
unsigned indexPreSize;
CXzStreamFlags streamFlags;
UInt32 blockHeaderSize;
UInt64 packSize;
UInt64 unpackSize;
UInt64 numBlocks;
UInt64 indexSize;
UInt64 indexPos;
UInt64 padSize;
UInt64 numStreams;
UInt32 crc;
CMixCoder decoder;
CXzBlock block;
CXzCheck check;
CSha256 sha;
Byte shaDigest[SHA256_DIGEST_SIZE];
Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];
} CXzUnpacker;
SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc);
void XzUnpacker_Free(CXzUnpacker *p);
/*
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, /* int srcWasFinished, */ int finishMode,
ECoderStatus *status);
Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p);
#ifdef __cplusplus
}
#endif
#endif

33
C/XzCrc64.c Executable file
View File

@@ -0,0 +1,33 @@
/* XzCrc64.c -- CRC64 calculation
2009-04-15 : Igor Pavlov : Public domain */
#include "XzCrc64.h"
#define kCrc64Poly 0xC96C5795D7870F42
UInt64 g_Crc64Table[256];
void MY_FAST_CALL Crc64GenerateTable(void)
{
UInt32 i;
for (i = 0; i < 256; i++)
{
UInt64 r = i;
int j;
for (j = 0; j < 8; j++)
r = (r >> 1) ^ ((UInt64)kCrc64Poly & ~((r & 1) - 1));
g_Crc64Table[i] = r;
}
}
UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size)
{
const Byte *p = (const Byte *)data;
for (; size > 0 ; size--, p++)
v = CRC64_UPDATE_BYTE(v, *p);
return v;
}
UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size)
{
return CRC64_GET_DIGEST(Crc64Update(CRC64_INIT_VAL, data, size));
}

30
C/XzCrc64.h Executable file
View File

@@ -0,0 +1,30 @@
/* XzCrc64.c -- CRC64 calculation
2009-04-15 : Igor Pavlov : Public domain */
#ifndef __XZ_CRC64_H
#define __XZ_CRC64_H
#include <stddef.h>
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
extern UInt64 g_Crc64Table[];
void MY_FAST_CALL Crc64GenerateTable(void);
#define CRC64_INIT_VAL 0xFFFFFFFFFFFFFFFF
#define CRC64_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFFFFFFFFFF)
#define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt64 MY_FAST_CALL Crc64Update(UInt64 crc, const void *data, size_t size);
UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size);
#ifdef __cplusplus
}
#endif
#endif

872
C/XzDec.c Executable file
View File

@@ -0,0 +1,872 @@
/* XzDec.c -- Xz Decode
2009-05-29 : Igor Pavlov : Public domain */
/* #define XZ_DUMP */
#ifdef XZ_DUMP
#include <stdio.h>
#endif
#include <stdlib.h>
#include <string.h>
#include "7zCrc.h"
#include "Alloc.h"
#include "Bra.h"
#include "CpuArch.h"
#include "Delta.h"
#include "Lzma2Dec.h"
#ifdef USE_SUBBLOCK
#include "SbDec.h"
#endif
#include "Xz.h"
#define XZ_CHECK_SIZE_MAX 64
#define CODER_BUF_SIZE (1 << 17)
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
{
int i, limit;
*value = 0;
limit = (maxSize > 9) ? 9 : (int)maxSize;
for (i = 0; i < limit;)
{
Byte b = p[i];
*value |= (UInt64)(b & 0x7F) << (7 * i++);
if ((b & 0x80) == 0)
return (b == 0 && i != 1) ? 0 : i;
}
return 0;
}
/* ---------- BraState ---------- */
#define BRA_BUF_SIZE (1 << 14)
typedef struct
{
size_t bufPos;
size_t bufConv;
size_t bufTotal;
UInt32 methodId;
int encodeMode;
UInt32 delta;
UInt32 ip;
UInt32 x86State;
Byte deltaState[DELTA_STATE_SIZE];
Byte buf[BRA_BUF_SIZE];
} CBraState;
void BraState_Free(void *pp, ISzAlloc *alloc)
{
alloc->Free(alloc, pp);
}
SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
{
CBraState *p = ((CBraState *)pp);
alloc = alloc;
p->encodeMode = 0;
p->ip = 0;
if (p->methodId == XZ_ID_Delta)
{
if (propSize != 1)
return SZ_ERROR_UNSUPPORTED;
p->delta = (unsigned)props[0] + 1;
}
else
{
if (propSize == 4)
{
UInt32 v = GetUi32(props);
switch(p->methodId)
{
case XZ_ID_PPC:
case XZ_ID_ARM:
case XZ_ID_SPARC:
if ((v & 3) != 0)
return SZ_ERROR_UNSUPPORTED;
break;
case XZ_ID_ARMT:
if ((v & 1) != 0)
return SZ_ERROR_UNSUPPORTED;
break;
case XZ_ID_IA64:
if ((v & 0xF) != 0)
return SZ_ERROR_UNSUPPORTED;
break;
}
p->ip = v;
}
else if (propSize != 0)
return SZ_ERROR_UNSUPPORTED;
}
return SZ_OK;
}
void BraState_Init(void *pp)
{
CBraState *p = ((CBraState *)pp);
p->bufPos = p->bufConv = p->bufTotal = 0;
x86_Convert_Init(p->x86State);
if (p->methodId == XZ_ID_Delta)
Delta_Init(p->deltaState);
}
#define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break;
static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
{
CBraState *p = ((CBraState *)pp);
SizeT destLenOrig = *destLen;
SizeT srcLenOrig = *srcLen;
*destLen = 0;
*srcLen = 0;
finishMode = finishMode;
*wasFinished = 0;
while (destLenOrig > 0)
{
if (p->bufPos != p->bufConv)
{
size_t curSize = p->bufConv - p->bufPos;
if (curSize > destLenOrig)
curSize = destLenOrig;
memcpy(dest, p->buf + p->bufPos, curSize);
p->bufPos += curSize;
*destLen += curSize;
dest += curSize;
destLenOrig -= curSize;
continue;
}
p->bufTotal -= p->bufPos;
memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
p->bufPos = 0;
p->bufConv = 0;
{
size_t curSize = BRA_BUF_SIZE - p->bufTotal;
if (curSize > srcLenOrig)
curSize = srcLenOrig;
memcpy(p->buf + p->bufTotal, src, curSize);
*srcLen += curSize;
src += curSize;
srcLenOrig -= curSize;
p->bufTotal += curSize;
}
if (p->bufTotal == 0)
break;
switch(p->methodId)
{
case XZ_ID_Delta:
if (p->encodeMode)
Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal);
else
Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal);
p->bufConv = p->bufTotal;
break;
case XZ_ID_X86:
p->bufConv = x86_Convert(p->buf, p->bufTotal, p->ip, &p->x86State, p->encodeMode);
break;
CASE_BRA_CONV(PPC)
CASE_BRA_CONV(IA64)
CASE_BRA_CONV(ARM)
CASE_BRA_CONV(ARMT)
CASE_BRA_CONV(SPARC)
default:
return SZ_ERROR_UNSUPPORTED;
}
p->ip += (UInt32)p->bufConv;
if (p->bufConv == 0)
{
if (!srcWasFinished)
break;
p->bufConv = p->bufTotal;
}
}
if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished)
*wasFinished = 1;
return SZ_OK;
}
SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc)
{
CBraState *decoder;
if (id != XZ_ID_Delta &&
id != XZ_ID_X86 &&
id != XZ_ID_PPC &&
id != XZ_ID_IA64 &&
id != XZ_ID_ARM &&
id != XZ_ID_ARMT &&
id != XZ_ID_SPARC)
return SZ_ERROR_UNSUPPORTED;
p->p = 0;
decoder = alloc->Alloc(alloc, sizeof(CBraState));
if (decoder == 0)
return SZ_ERROR_MEM;
decoder->methodId = (UInt32)id;
p->p = decoder;
p->Free = BraState_Free;
p->SetProps = BraState_SetProps;
p->Init = BraState_Init;
p->Code = BraState_Code;
return SZ_OK;
}
/* ---------- SbState ---------- */
#ifdef USE_SUBBLOCK
static void SbState_Free(void *pp, ISzAlloc *alloc)
{
CSubblockDec *p = (CSubblockDec *)pp;
SubblockDec_Free(p, alloc);
alloc->Free(alloc, pp);
}
static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
{
pp = pp;
props = props;
alloc = alloc;
return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
}
static void SbState_Init(void *pp)
{
SubblockDec_Init((CSubblockDec *)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);
srcWasFinished = srcWasFinished;
*wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
return res;
}
SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
{
CSubblockDec *decoder;
p->p = 0;
decoder = alloc->Alloc(alloc, sizeof(CSubblockDec));
if (decoder == 0)
return SZ_ERROR_MEM;
p->p = decoder;
p->Free = SbState_Free;
p->SetProps = SbState_SetProps;
p->Init = SbState_Init;
p->Code = SbState_Code;
SubblockDec_Construct(decoder);
return SZ_OK;
}
#endif
/* ---------- Lzma2State ---------- */
static void Lzma2State_Free(void *pp, ISzAlloc *alloc)
{
Lzma2Dec_Free((CLzma2Dec *)pp, alloc);
alloc->Free(alloc, pp);
}
static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
{
if (propSize != 1)
return SZ_ERROR_UNSUPPORTED;
return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc);
}
static void Lzma2State_Init(void *pp)
{
Lzma2Dec_Init((CLzma2Dec *)pp);
}
static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
int srcWasFinished, ELzmaFinishMode finishMode, int *wasFinished)
{
ELzmaStatus status;
SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, finishMode, &status);
srcWasFinished = srcWasFinished;
*wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
return res;
}
static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
{
CLzma2Dec *decoder = alloc->Alloc(alloc, sizeof(CLzma2Dec));
p->p = decoder;
if (decoder == 0)
return SZ_ERROR_MEM;
p->Free = Lzma2State_Free;
p->SetProps = Lzma2State_SetProps;
p->Init = Lzma2State_Init;
p->Code = Lzma2State_Code;
Lzma2Dec_Construct(decoder);
return SZ_OK;
}
void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)
{
int i;
p->alloc = alloc;
p->buf = 0;
p->numCoders = 0;
for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
p->coders[i].p = NULL;
}
void MixCoder_Free(CMixCoder *p)
{
int i;
for (i = 0; i < p->numCoders; i++)
{
IStateCoder *sc = &p->coders[i];
if (p->alloc && sc->p)
sc->Free(sc->p, p->alloc);
}
p->numCoders = 0;
if (p->buf)
p->alloc->Free(p->alloc, p->buf);
}
void MixCoder_Init(CMixCoder *p)
{
int i;
for (i = 0; i < p->numCoders - 1; i++)
{
p->size[i] = 0;
p->pos[i] = 0;
p->finished[i] = 0;
}
for (i = 0; i < p->numCoders; i++)
{
IStateCoder *coder = &p->coders[i];
coder->Init(coder->p);
}
}
SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId)
{
IStateCoder *sc = &p->coders[coderIndex];
p->ids[coderIndex] = methodId;
switch(methodId)
{
case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc);
#ifdef USE_SUBBLOCK
case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);
#endif
}
if (coderIndex == 0)
return SZ_ERROR_UNSUPPORTED;
return BraState_SetFromMethod(sc, methodId, p->alloc);
}
SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, int srcWasFinished,
ELzmaFinishMode finishMode, ECoderStatus *status)
{
SizeT destLenOrig = *destLen;
SizeT srcLenOrig = *srcLen;
Bool allFinished = True;
*destLen = 0;
*srcLen = 0;
*status = CODER_STATUS_NOT_FINISHED;
if (p->buf == 0)
{
p->buf = p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
if (p->buf == 0)
return SZ_ERROR_MEM;
}
if (p->numCoders != 1)
finishMode = CODER_FINISH_ANY;
for (;;)
{
Bool processed = False;
int i;
/*
if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
break;
*/
for (i = 0; i < p->numCoders; i++)
{
SRes res;
IStateCoder *coder = &p->coders[i];
Byte *destCur;
SizeT destLenCur, srcLenCur;
const Byte *srcCur;
int srcFinishedCur;
int encodingWasFinished;
if (i == 0)
{
srcCur = src;
srcLenCur = srcLenOrig - *srcLen;
srcFinishedCur = srcWasFinished;
}
else
{
srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1];
srcLenCur = p->size[i - 1] - p->pos[i - 1];
srcFinishedCur = p->finished[i - 1];
}
if (i == p->numCoders - 1)
{
destCur = dest;
destLenCur = destLenOrig - *destLen;
}
else
{
if (p->pos[i] != p->size[i])
continue;
destCur = p->buf + (CODER_BUF_SIZE * i);
destLenCur = CODER_BUF_SIZE;
}
res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished);
if (!encodingWasFinished)
allFinished = False;
if (i == 0)
{
*srcLen += srcLenCur;
src += srcLenCur;
}
else
{
p->pos[i - 1] += srcLenCur;
}
if (i == p->numCoders - 1)
{
*destLen += destLenCur;
dest += destLenCur;
}
else
{
p->size[i] = destLenCur;
p->pos[i] = 0;
p->finished[i] = encodingWasFinished;
}
if (res != SZ_OK)
return res;
if (destLenCur != 0 || srcLenCur != 0)
processed = True;
}
if (!processed)
break;
}
if (allFinished)
*status = CODER_STATUS_FINISHED_WITH_MARK;
return SZ_OK;
}
SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
{
*p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
return SZ_ERROR_NO_ARCHIVE;
return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
}
static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
{
return
indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) &&
(GetUi32(buf) == CrcCalc(buf + 4, 6) &&
flags == GetBe16(buf + 8) &&
memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0);
}
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
{ unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
{
unsigned pos;
int numFilters, i;
UInt32 headerSize = (UInt32)header[0] << 2;
if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
return SZ_ERROR_ARCHIVE;
pos = 1;
if (pos == headerSize)
return SZ_ERROR_ARCHIVE;
p->flags = header[pos++];
if (XzBlock_HasPackSize(p))
{
READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);
if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)
return SZ_ERROR_ARCHIVE;
}
if (XzBlock_HasUnpackSize(p))
READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);
numFilters = XzBlock_GetNumFilters(p);
for (i = 0; i < numFilters; i++)
{
CXzFilter *filter = p->filters + i;
UInt64 size;
READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);
READ_VARINT_AND_CHECK(header, pos, headerSize, &size);
if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
return SZ_ERROR_ARCHIVE;
filter->propsSize = (UInt32)size;
memcpy(filter->props, header + pos, (size_t)size);
pos += (unsigned)size;
#ifdef XZ_DUMP
printf("\nf[%d] = %2X: ", i, filter->id);
{
int i;
for (i = 0; i < size; i++)
printf(" %2X", filter->props[i]);
}
#endif
}
while (pos < headerSize)
if (header[pos++] != 0)
return SZ_ERROR_ARCHIVE;
return SZ_OK;
}
SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
{
int i;
Bool needReInit = True;
int numFilters = XzBlock_GetNumFilters(block);
if (numFilters == p->numCoders)
{
for (i = 0; i < numFilters; i++)
if (p->ids[i] != block->filters[numFilters - 1 - i].id)
break;
needReInit = (i != numFilters);
}
if (needReInit)
{
MixCoder_Free(p);
p->numCoders = numFilters;
for (i = 0; i < numFilters; i++)
{
const CXzFilter *f = &block->filters[numFilters - 1 - i];
RINOK(MixCoder_SetFromMethod(p, i, f->id));
}
}
for (i = 0; i < numFilters; i++)
{
const CXzFilter *f = &block->filters[numFilters - 1 - i];
IStateCoder *sc = &p->coders[i];
RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
}
MixCoder_Init(p);
return SZ_OK;
}
SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc)
{
MixCoder_Construct(&p->decoder, alloc);
p->state = XZ_STATE_STREAM_HEADER;
p->pos = 0;
p->numStreams = 0;
return SZ_OK;
}
void XzUnpacker_Free(CXzUnpacker *p)
{
MixCoder_Free(&p->decoder);
}
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, int finishMode, ECoderStatus *status)
{
SizeT destLenOrig = *destLen;
SizeT srcLenOrig = *srcLen;
*destLen = 0;
*srcLen = 0;
*status = CODER_STATUS_NOT_SPECIFIED;
for (;;)
{
SizeT srcRem = srcLenOrig - *srcLen;
if (p->state == XZ_STATE_BLOCK)
{
SizeT destLen2 = destLenOrig - *destLen;
SizeT srcLen2 = srcLenOrig - *srcLen;
SRes res;
if (srcLen2 == 0 && destLen2 == 0)
{
*status = CODER_STATUS_NOT_FINISHED;
return SZ_OK;
}
res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status);
XzCheck_Update(&p->check, dest, destLen2);
(*srcLen) += srcLen2;
src += srcLen2;
p->packSize += srcLen2;
(*destLen) += destLen2;
dest += destLen2;
p->unpackSize += destLen2;
RINOK(res);
if (*status == CODER_STATUS_FINISHED_WITH_MARK)
{
Byte temp[32];
unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags));
num += Xz_WriteVarInt(temp + num, p->unpackSize);
Sha256_Update(&p->sha, temp, num);
p->indexSize += num;
p->numBlocks++;
p->state = XZ_STATE_BLOCK_FOOTER;
p->pos = 0;
p->alignPos = 0;
}
else if (srcLen2 == 0 && destLen2 == 0)
return SZ_OK;
continue;
}
if (srcRem == 0)
{
*status = CODER_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
switch(p->state)
{
case XZ_STATE_STREAM_HEADER:
{
if (p->pos < XZ_STREAM_HEADER_SIZE)
{
if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
return SZ_ERROR_NO_ARCHIVE;
p->buf[p->pos++] = *src++;
(*srcLen)++;
}
else
{
RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
p->state = XZ_STATE_BLOCK_HEADER;
Sha256_Init(&p->sha);
p->indexSize = 0;
p->numBlocks = 0;
p->pos = 0;
}
break;
}
case XZ_STATE_BLOCK_HEADER:
{
if (p->pos == 0)
{
p->buf[p->pos++] = *src++;
(*srcLen)++;
if (p->buf[0] == 0)
{
p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
p->indexPos = p->indexPreSize;
p->indexSize += p->indexPreSize;
Sha256_Final(&p->sha, p->shaDigest);
Sha256_Init(&p->sha);
p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
p->state = XZ_STATE_STREAM_INDEX;
}
p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
}
else if (p->pos != p->blockHeaderSize)
{
UInt32 cur = p->blockHeaderSize - p->pos;
if (cur > srcRem)
cur = (UInt32)srcRem;
memcpy(p->buf + p->pos, src, cur);
p->pos += cur;
(*srcLen) += cur;
src += cur;
}
else
{
RINOK(XzBlock_Parse(&p->block, p->buf));
p->state = XZ_STATE_BLOCK;
p->packSize = 0;
p->unpackSize = 0;
XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
RINOK(XzDec_Init(&p->decoder, &p->block));
}
break;
}
case XZ_STATE_BLOCK_FOOTER:
{
if (((p->packSize + p->alignPos) & 3) != 0)
{
(*srcLen)++;
p->alignPos++;
if (*src++ != 0)
return SZ_ERROR_CRC;
}
else
{
UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
UInt32 cur = checkSize - p->pos;
if (cur != 0)
{
if (cur > srcRem)
cur = (UInt32)srcRem;
memcpy(p->buf + p->pos, src, cur);
p->pos += cur;
(*srcLen) += cur;
src += cur;
}
else
{
Byte digest[XZ_CHECK_SIZE_MAX];
p->state = XZ_STATE_BLOCK_HEADER;
p->pos = 0;
if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
return SZ_ERROR_CRC;
}
}
break;
}
case XZ_STATE_STREAM_INDEX:
{
if (p->pos < p->indexPreSize)
{
(*srcLen)++;
if (*src++ != p->buf[p->pos++])
return SZ_ERROR_CRC;
}
else
{
if (p->indexPos < p->indexSize)
{
UInt64 cur = p->indexSize - p->indexPos;
if (srcRem > cur)
srcRem = (SizeT)cur;
p->crc = CrcUpdate(p->crc, src, srcRem);
Sha256_Update(&p->sha, src, srcRem);
(*srcLen) += srcRem;
src += srcRem;
p->indexPos += srcRem;
}
else if ((p->indexPos & 3) != 0)
{
Byte b = *src++;
p->crc = CRC_UPDATE_BYTE(p->crc, b);
(*srcLen)++;
p->indexPos++;
p->indexSize++;
if (b != 0)
return SZ_ERROR_CRC;
}
else
{
Byte digest[SHA256_DIGEST_SIZE];
p->state = XZ_STATE_STREAM_INDEX_CRC;
p->indexSize += 4;
p->pos = 0;
Sha256_Final(&p->sha, digest);
if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
return SZ_ERROR_CRC;
}
}
break;
}
case XZ_STATE_STREAM_INDEX_CRC:
{
if (p->pos < 4)
{
(*srcLen)++;
p->buf[p->pos++] = *src++;
}
else
{
p->state = XZ_STATE_STREAM_FOOTER;
p->pos = 0;
if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))
return SZ_ERROR_CRC;
}
break;
}
case XZ_STATE_STREAM_FOOTER:
{
UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
if (cur > srcRem)
cur = (UInt32)srcRem;
memcpy(p->buf + p->pos, src, cur);
p->pos += cur;
(*srcLen) += cur;
src += cur;
if (p->pos == XZ_STREAM_FOOTER_SIZE)
{
p->state = XZ_STATE_STREAM_PADDING;
p->numStreams++;
p->padSize = 0;
if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
return SZ_ERROR_CRC;
}
break;
}
case XZ_STATE_STREAM_PADDING:
{
if (*src != 0)
{
if (((UInt32)p->padSize & 3) != 0)
return SZ_ERROR_NO_ARCHIVE;
p->pos = 0;
p->state = XZ_STATE_STREAM_HEADER;
}
else
{
(*srcLen)++;
src++;
p->padSize++;
}
break;
}
}
}
/*
if (p->state == XZ_STATE_FINISHED)
*status = CODER_STATUS_FINISHED_WITH_MARK;
return SZ_OK;
*/
}
Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)
{
return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
}

497
C/XzEnc.c Executable file
View File

@@ -0,0 +1,497 @@
/* XzEnc.c -- Xz Encode
2009-05-26 : Igor Pavlov : Public domain */
#include <stdlib.h>
#include <string.h>
#include "7zCrc.h"
#include "Alloc.h"
#include "Bra.h"
#include "CpuArch.h"
#ifdef USE_SUBBLOCK
#include "SbEnc.h"
#endif
#include "XzEnc.h"
static void *SzBigAlloc(void *p, size_t size) { p = p; return BigAlloc(size); }
static void SzBigFree(void *p, void *address) { p = p; BigFree(address); }
static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
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 };
#define XzBlock_ClearFlags(p) (p)->flags = 0;
#define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1);
#define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE;
#define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE;
static SRes WriteBytes(ISeqOutStream *s, const void *buf, UInt32 size)
{
return (s->Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE;
}
static SRes WriteBytesAndCrc(ISeqOutStream *s, const void *buf, UInt32 size, UInt32 *crc)
{
*crc = CrcUpdate(*crc, buf, size);
return WriteBytes(s, buf, size);
}
SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s)
{
UInt32 crc;
Byte header[XZ_STREAM_HEADER_SIZE];
memcpy(header, XZ_SIG, XZ_SIG_SIZE);
header[XZ_SIG_SIZE] = (Byte)(f >> 8);
header[XZ_SIG_SIZE + 1] = (Byte)(f & 0xFF);
crc = CrcCalc(header + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE);
SetUi32(header + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE, crc);
return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE);
}
SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)
{
Byte header[XZ_BLOCK_HEADER_SIZE_MAX];
unsigned pos = 1;
int numFilters, i;
header[pos++] = p->flags;
if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize);
if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize);
numFilters = XzBlock_GetNumFilters(p);
for (i = 0; i < numFilters; i++)
{
const CXzFilter *f = &p->filters[i];
pos += Xz_WriteVarInt(header + pos, f->id);
pos += Xz_WriteVarInt(header + pos, f->propsSize);
memcpy(header + pos, f->props, f->propsSize);
pos += f->propsSize;
}
while((pos & 3) != 0)
header[pos++] = 0;
header[0] = (Byte)(pos >> 2);
SetUi32(header + pos, CrcCalc(header, pos));
return WriteBytes(s, header, pos + 4);
}
SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
{
Byte buf[32];
UInt64 globalPos;
{
UInt32 crc = CRC_INIT_VAL;
unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks);
size_t i;
globalPos = pos;
buf[0] = 0;
RINOK(WriteBytesAndCrc(s, buf, pos, &crc));
for (i = 0; i < p->numBlocks; i++)
{
const CXzBlockSizes *block = &p->blocks[i];
pos = Xz_WriteVarInt(buf, block->totalSize);
pos += Xz_WriteVarInt(buf + pos, block->unpackSize);
globalPos += pos;
RINOK(WriteBytesAndCrc(s, buf, pos, &crc));
}
pos = ((unsigned)globalPos & 3);
if (pos != 0)
{
buf[0] = buf[1] = buf[2] = 0;
RINOK(WriteBytesAndCrc(s, buf, 4 - pos, &crc));
globalPos += 4 - pos;
}
{
SetUi32(buf, CRC_GET_DIGEST(crc));
RINOK(WriteBytes(s, buf, 4));
globalPos += 4;
}
}
{
UInt32 indexSize = (UInt32)((globalPos >> 2) - 1);
SetUi32(buf + 4, indexSize);
buf[8] = (Byte)(p->flags >> 8);
buf[9] = (Byte)(p->flags & 0xFF);
SetUi32(buf, CrcCalc(buf + 4, 6));
memcpy(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE);
return WriteBytes(s, buf, 12);
}
}
SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc)
{
if (p->blocks == 0 || p->numBlocksAllocated == p->numBlocks)
{
size_t num = (p->numBlocks + 1) * 2;
size_t newSize = sizeof(CXzBlockSizes) * num;
CXzBlockSizes *blocks;
if (newSize / sizeof(CXzBlockSizes) != num)
return SZ_ERROR_MEM;
blocks = alloc->Alloc(alloc, newSize);
if (blocks == 0)
return SZ_ERROR_MEM;
if (p->numBlocks != 0)
{
memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes));
Xz_Free(p, alloc);
}
p->blocks = blocks;
p->numBlocksAllocated = num;
}
{
CXzBlockSizes *block = &p->blocks[p->numBlocks++];
block->totalSize = totalSize;
block->unpackSize = unpackSize;
}
return SZ_OK;
}
/* ---------- CSeqCheckInStream ---------- */
typedef struct
{
ISeqInStream p;
ISeqInStream *realStream;
UInt64 processed;
CXzCheck check;
} CSeqCheckInStream;
void SeqCheckInStream_Init(CSeqCheckInStream *p, int mode)
{
p->processed = 0;
XzCheck_Init(&p->check, mode);
}
void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)
{
XzCheck_Final(&p->check, digest);
}
static SRes SeqCheckInStream_Read(void *pp, void *data, size_t *size)
{
CSeqCheckInStream *p = (CSeqCheckInStream *)pp;
SRes res = p->realStream->Read(p->realStream, data, size);
XzCheck_Update(&p->check, data, *size);
p->processed += *size;
return res;
}
/* ---------- CSeqSizeOutStream ---------- */
typedef struct
{
ISeqOutStream p;
ISeqOutStream *realStream;
UInt64 processed;
} CSeqSizeOutStream;
static size_t MyWrite(void *pp, const void *data, size_t size)
{
CSeqSizeOutStream *p = (CSeqSizeOutStream *)pp;
size = p->realStream->Write(p->realStream, data, size);
p->processed += size;
return 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)
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;
} CSeqInFilter;
static SRes SeqInFilter_Read(void *pp, void *data, size_t *size)
{
CSeqInFilter *p = (CSeqInFilter *)pp;
size_t remSize = *size;
*size = 0;
while (remSize > 0)
{
int i;
if (p->convertedPosBegin != p->convertedPosEnd)
{
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;
}
{
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;
}
}
return res;
}
*/
#ifdef USE_SUBBLOCK
typedef struct
{
ISeqInStream p;
CSubblockEnc sb;
UInt64 processed;
} 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;
}
#endif
typedef struct
{
/* CMixCoderSeqInStream inStream; */
CLzma2EncHandle lzma2;
#ifdef USE_SUBBLOCK
CSbEncInStream sb;
#endif
ISzAlloc *alloc;
ISzAlloc *bigAlloc;
} CLzma2WithFilters;
static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, ISzAlloc *bigAlloc)
{
p->alloc = alloc;
p->bigAlloc = bigAlloc;
p->lzma2 = NULL;
#ifdef USE_SUBBLOCK
p->sb.p.Read = SbEncInStream_Read;
SubblockEnc_Construct(&p->sb.sb, p->alloc);
#endif
}
static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p)
{
p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc);
if (p->lzma2 == 0)
return SZ_ERROR_MEM;
return SZ_OK;
}
static void Lzma2WithFilters_Free(CLzma2WithFilters *p)
{
#ifdef USE_SUBBLOCK
SubblockEnc_Free(&p->sb.sb);
#endif
if (p->lzma2)
{
Lzma2Enc_Destroy(p->lzma2);
p->lzma2 = NULL;
}
}
static SRes Xz_Compress(CXzStream *xz,
CLzma2WithFilters *lzmaf,
ISeqOutStream *outStream,
ISeqInStream *inStream,
const CLzma2EncProps *lzma2Props,
Bool useSubblock,
ICompressProgress *progress)
{
xz->flags = XZ_CHECK_CRC32;
RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, lzma2Props));
RINOK(Xz_WriteHeader(xz->flags, outStream));
{
CSeqCheckInStream checkInStream;
CSeqSizeOutStream seqSizeOutStream;
CXzBlock block;
int filterIndex = 0;
XzBlock_ClearFlags(&block);
XzBlock_SetNumFilters(&block, 1 + (useSubblock ? 1 : 0));
if (useSubblock)
{
CXzFilter *f = &block.filters[filterIndex++];
f->id = XZ_ID_Subblock;
f->propsSize = 0;
}
{
CXzFilter *f = &block.filters[filterIndex++];
f->id = XZ_ID_LZMA2;
f->propsSize = 1;
f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2);
}
seqSizeOutStream.p.Write = MyWrite;
seqSizeOutStream.realStream = outStream;
seqSizeOutStream.processed = 0;
RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.p));
checkInStream.p.Read = SeqCheckInStream_Read;
checkInStream.realStream = inStream;
SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags));
#ifdef USE_SUBBLOCK
if (useSubblock)
{
lzmaf->sb.sb.inStream = &checkInStream.p;
SubblockEnc_Init(&lzmaf->sb.sb);
}
#endif
{
UInt64 packPos = seqSizeOutStream.processed;
HRESULT res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p,
#ifdef USE_SUBBLOCK
useSubblock ? &lzmaf->sb.p:
#endif
&checkInStream.p,
progress);
RINOK(res);
block.unpackSize = checkInStream.processed;
block.packSize = seqSizeOutStream.processed - packPos;
}
{
unsigned padSize = 0;
Byte buf[128];
while((((unsigned)block.packSize + padSize) & 3) != 0)
buf[padSize++] = 0;
SeqCheckInStream_GetDigest(&checkInStream, buf + padSize);
RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags)));
RINOK(Xz_AddIndexRecord(xz, block.unpackSize, seqSizeOutStream.processed - padSize, &g_Alloc));
}
}
return Xz_WriteFooter(xz, outStream);
}
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
const CLzma2EncProps *lzma2Props, Bool useSubblock,
ICompressProgress *progress)
{
SRes res;
CXzStream xz;
CLzma2WithFilters lzmaf;
Xz_Construct(&xz);
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);
Lzma2WithFilters_Free(&lzmaf);
Xz_Free(&xz, &g_Alloc);
return res;
}
SRes Xz_EncodeEmpty(ISeqOutStream *outStream)
{
SRes res;
CXzStream xz;
Xz_Construct(&xz);
res = Xz_WriteHeader(xz.flags, outStream);
if (res == SZ_OK)
res = Xz_WriteFooter(&xz, outStream);
Xz_Free(&xz, &g_Alloc);
return res;
}

25
C/XzEnc.h Executable file
View File

@@ -0,0 +1,25 @@
/* XzEnc.h -- Xz Encode
2009-04-15 : Igor Pavlov : Public domain */
#ifndef __XZ_ENC_H
#define __XZ_ENC_H
#include "Lzma2Enc.h"
#include "Xz.h"
#ifdef __cplusplus
extern "C" {
#endif
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
const CLzma2EncProps *lzma2Props, Bool useSubblock,
ICompressProgress *progress);
SRes Xz_EncodeEmpty(ISeqOutStream *outStream);
#ifdef __cplusplus
}
#endif
#endif

305
C/XzIn.c Executable file
View File

@@ -0,0 +1,305 @@
/* XzIn.c - Xz input
2009-04-15 : Igor Pavlov : Public domain */
#include "Xz.h"
#include "7zCrc.h"
#include "CpuArch.h"
SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream)
{
Byte sig[XZ_STREAM_HEADER_SIZE];
RINOK(SeqInStream_Read2(inStream, sig, XZ_STREAM_HEADER_SIZE, SZ_ERROR_NO_ARCHIVE));
if (memcmp(sig, XZ_SIG, XZ_SIG_SIZE) != 0)
return SZ_ERROR_NO_ARCHIVE;
return Xz_ParseHeader(p, sig);
}
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
{ unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes)
{
Byte header[XZ_BLOCK_HEADER_SIZE_MAX];
unsigned headerSize;
*headerSizeRes = 0;
RINOK(SeqInStream_ReadByte(inStream, &header[0]));
headerSize = ((unsigned)header[0] << 2) + 4;
if (headerSize == 0)
{
*headerSizeRes = 1;
*isIndex = True;
return SZ_OK;
}
*isIndex = False;
*headerSizeRes = headerSize;
RINOK(SeqInStream_Read(inStream, header + 1, headerSize - 1));
return XzBlock_Parse(p, header);
}
#define ADD_SIZE_CHECH(size, val) \
{ UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; }
UInt64 Xz_GetUnpackSize(const CXzStream *p)
{
UInt64 size = 0;
size_t i;
for (i = 0; i < p->numBlocks; i++)
ADD_SIZE_CHECH(size, p->blocks[i].unpackSize);
return size;
}
UInt64 Xz_GetPackSize(const CXzStream *p)
{
UInt64 size = 0;
size_t i;
for (i = 0; i < p->numBlocks; i++)
ADD_SIZE_CHECH(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3);
return size;
}
/*
SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStream *inStream)
{
return SeqInStream_Read(inStream, p->check, XzFlags_GetCheckSize(f));
}
*/
static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc)
{
size_t i, numBlocks, crcStartPos, pos = 1;
UInt32 crc;
if (size < 5 || buf[0] != 0)
return SZ_ERROR_ARCHIVE;
size -= 4;
crc = CrcCalc(buf, size);
if (crc != GetUi32(buf + size))
return SZ_ERROR_ARCHIVE;
{
UInt64 numBlocks64;
READ_VARINT_AND_CHECK(buf, pos, size, &numBlocks64);
numBlocks = (size_t)numBlocks64;
if (numBlocks != numBlocks64 || numBlocks * 2 > size)
return SZ_ERROR_ARCHIVE;
}
crcStartPos = pos;
Xz_Free(p, alloc);
if (numBlocks != 0)
{
p->numBlocks = numBlocks;
p->numBlocksAllocated = numBlocks;
p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);
if (p->blocks == 0)
return SZ_ERROR_MEM;
for (i = 0; i < numBlocks; i++)
{
CXzBlockSizes *block = &p->blocks[i];
READ_VARINT_AND_CHECK(buf, pos, size, &block->totalSize);
READ_VARINT_AND_CHECK(buf, pos, size, &block->unpackSize);
if (block->totalSize == 0)
return SZ_ERROR_ARCHIVE;
}
}
while ((pos & 3) != 0)
if (buf[pos++] != 0)
return SZ_ERROR_ARCHIVE;
return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
}
static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize, ISzAlloc *alloc)
{
SRes res;
size_t size;
Byte *buf;
if (indexSize > ((UInt32)1 << 31))
return SZ_ERROR_UNSUPPORTED;
size = (size_t)indexSize;
if (size != indexSize)
return SZ_ERROR_UNSUPPORTED;
buf = alloc->Alloc(alloc, size);
if (buf == 0)
return SZ_ERROR_MEM;
res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED);
if (res == SZ_OK)
res = Xz_ReadIndex2(p, buf, size, alloc);
alloc->Free(alloc, buf);
return res;
}
static SRes SeekFromCur(ILookInStream *inStream, Int64 *res)
{
return inStream->Seek(inStream, res, SZ_SEEK_CUR);
}
static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAlloc *alloc)
{
UInt64 indexSize;
Byte buf[XZ_STREAM_FOOTER_SIZE];
if ((*startOffset & 3) != 0 || *startOffset < XZ_STREAM_FOOTER_SIZE)
return SZ_ERROR_NO_ARCHIVE;
*startOffset = -XZ_STREAM_FOOTER_SIZE;
RINOK(SeekFromCur(stream, startOffset));
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)
{
Int64 i = 0;
*startOffset += XZ_STREAM_FOOTER_SIZE;
for (;;)
{
int j;
size_t processedSize;
#define TEMP_BUF_SIZE (1 << 10)
Byte tempBuf[TEMP_BUF_SIZE];
if (*startOffset < XZ_STREAM_FOOTER_SIZE || i > (1 << 16))
return SZ_ERROR_NO_ARCHIVE;
processedSize = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset;
i += processedSize;
*startOffset = -(Int64)processedSize;
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)
break;
if (j != 0)
{
if ((j & 3) != 0)
return SZ_ERROR_NO_ARCHIVE;
*startOffset += j;
if (*startOffset < XZ_STREAM_FOOTER_SIZE)
return SZ_ERROR_NO_ARCHIVE;
*startOffset -= XZ_STREAM_FOOTER_SIZE;
RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET));
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);
if (!XzFlags_IsSupported(p->flags))
return SZ_ERROR_UNSUPPORTED;
if (GetUi32(buf) != CrcCalc(buf + 4, 6))
return SZ_ERROR_ARCHIVE;
indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2;
*startOffset = -(Int64)(indexSize + XZ_STREAM_FOOTER_SIZE);
RINOK(SeekFromCur(stream, startOffset));
RINOK(Xz_ReadIndex(p, stream, indexSize, alloc));
{
UInt64 totalSize = Xz_GetPackSize(p);
UInt64 sum = XZ_STREAM_HEADER_SIZE + totalSize + indexSize;
if (totalSize == XZ_SIZE_OVERFLOW ||
sum >= ((UInt64)1 << 63) ||
totalSize >= ((UInt64)1 << 63))
return SZ_ERROR_ARCHIVE;
*startOffset = -(Int64)sum;
RINOK(SeekFromCur(stream, startOffset));
}
{
CXzStreamFlags headerFlags;
CSecToRead secToRead;
SecToRead_CreateVTable(&secToRead);
secToRead.realStream = stream;
RINOK(Xz_ReadHeader(&headerFlags, &secToRead.s));
return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE;
}
}
/* ---------- Xz Streams ---------- */
void Xzs_Construct(CXzs *p)
{
p->num = p->numAllocated = 0;
p->streams = 0;
}
void Xzs_Free(CXzs *p, ISzAlloc *alloc)
{
size_t i;
for (i = 0; i < p->num; i++)
Xz_Free(&p->streams[i], alloc);
alloc->Free(alloc, p->streams);
p->num = p->numAllocated = 0;
p->streams = 0;
}
UInt64 Xzs_GetNumBlocks(const CXzs *p)
{
UInt64 num = 0;
size_t i;
for (i = 0; i < p->num; i++)
num += p->streams[i].numBlocks;
return num;
}
UInt64 Xzs_GetUnpackSize(const CXzs *p)
{
UInt64 size = 0;
size_t i;
for (i = 0; i < p->num; i++)
ADD_SIZE_CHECH(size, Xz_GetUnpackSize(&p->streams[i]));
return size;
}
/*
UInt64 Xzs_GetPackSize(const CXzs *p)
{
UInt64 size = 0;
size_t i;
for (i = 0; i < p->num; i++)
ADD_SIZE_CHECH(size, Xz_GetTotalSize(&p->streams[i]));
return size;
}
*/
SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc)
{
Int64 endOffset = 0;
RINOK(stream->Seek(stream, &endOffset, SZ_SEEK_END));
*startOffset = endOffset;
for (;;)
{
CXzStream st;
SRes res;
Xz_Construct(&st);
res = Xz_ReadBackward(&st, stream, startOffset, alloc);
st.startOffset = *startOffset;
RINOK(res);
if (p->num == p->numAllocated)
{
size_t newNum = p->num + p->num / 4 + 1;
Byte *data = (Byte *)alloc->Alloc(alloc, newNum * sizeof(CXzStream));
if (data == 0)
return SZ_ERROR_MEM;
p->numAllocated = newNum;
memcpy(data, p->streams, p->num * sizeof(CXzStream));
alloc->Free(alloc, p->streams);
p->streams = (CXzStream *)data;
}
p->streams[p->num++] = st;
if (*startOffset == 0)
break;
RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET));
if (progress && progress->Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK)
return SZ_ERROR_PROGRESS;
}
return SZ_OK;
}

View File

@@ -598,11 +598,11 @@ SOURCE=..\..\..\Windows\Thread.h
# PROP Default_Filter "" # PROP Default_Filter ""
# Begin Source File # Begin Source File
SOURCE=..\..\Compress\Copy\CopyCoder.cpp SOURCE=..\..\Compress\CopyCoder.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Compress\Copy\CopyCoder.h SOURCE=..\..\Compress\CopyCoder.h
# End Source File # End Source File
# End Group # End Group
# Begin Group "C" # Begin Group "C"

View File

@@ -1,21 +1,21 @@
// Encode.cpp // 7zEncode.cpp
#include "StdAfx.h" #include "StdAfx.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/FilterCoder.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/InOutTempBuffer.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
#include "7zEncode.h" #include "7zEncode.h"
#include "7zSpecStream.h" #include "7zSpecStream.h"
#include "../../IPassword.h" static const UInt64 k_Delta = 0x03;
#include "../../Common/ProgressUtils.h" static const UInt64 k_BCJ = 0x03030103;
#include "../../Common/LimitedStreams.h"
#include "../../Common/InOutTempBuffer.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/FilterCoder.h"
static const UInt64 k_AES = 0x06F10701;
static const UInt64 k_BCJ = 0x03030103;
static const UInt64 k_BCJ2 = 0x0303011B; static const UInt64 k_BCJ2 = 0x0303011B;
static const UInt64 k_AES = 0x06F10701;
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
@@ -240,10 +240,10 @@ HRESULT CEncoder::Encode(
UInt32 progressIndex = mainCoderIndex; UInt32 progressIndex = mainCoderIndex;
for (i = 0; i < _codersInfo.Size(); i++) for (i = 0; i + 1 < _codersInfo.Size(); i++)
{ {
const CCoderInfo &e = _codersInfo[i]; UInt64 m = _codersInfo[i].MethodID;
if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size()) if (m == k_Delta || m == k_BCJ || m == k_BCJ2)
progressIndex = i + 1; progressIndex = i + 1;
} }

View File

@@ -9,156 +9,132 @@ namespace N7z {
CFolderOutStream::CFolderOutStream() CFolderOutStream::CFolderOutStream()
{ {
_outStreamWithHashSpec = new COutStreamWithCRC; _crcStreamSpec = new COutStreamWithCRC;
_outStreamWithHash = _outStreamWithHashSpec; _crcStream = _crcStreamSpec;
} }
HRESULT CFolderOutStream::Init( HRESULT CFolderOutStream::Init(
const CArchiveDatabaseEx *archiveDatabase, const CArchiveDatabaseEx *archiveDatabase,
UInt32 ref2Offset, UInt32 ref2Offset, UInt32 startIndex,
UInt32 startIndex,
const CBoolVector *extractStatuses, const CBoolVector *extractStatuses,
IArchiveExtractCallback *extractCallback, IArchiveExtractCallback *extractCallback,
bool testMode, bool testMode, bool checkCrc)
bool checkCrc)
{ {
_archiveDatabase = archiveDatabase; _db = archiveDatabase;
_ref2Offset = ref2Offset; _ref2Offset = ref2Offset;
_startIndex = startIndex; _startIndex = startIndex;
_extractStatuses = extractStatuses; _extractStatuses = extractStatuses;
_extractCallback = extractCallback; _extractCallback = extractCallback;
_testMode = testMode; _testMode = testMode;
_checkCrc = checkCrc; _checkCrc = checkCrc;
_currentIndex = 0; _currentIndex = 0;
_fileIsOpen = false; _fileIsOpen = false;
return WriteEmptyFiles(); return ProcessEmptyFiles();
} }
HRESULT CFolderOutStream::OpenFile() HRESULT CFolderOutStream::OpenFile()
{ {
Int32 askMode; Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ?
if((*_extractStatuses)[_currentIndex]) NArchive::NExtract::NAskMode::kTest :
askMode = _testMode ? NArchive::NExtract::NAskMode::kExtract):
NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kSkip;
NArchive::NExtract::NAskMode::kExtract;
else
askMode = NArchive::NExtract::NAskMode::kSkip;
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
UInt32 index = _startIndex + _currentIndex; UInt32 index = _startIndex + _currentIndex;
RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
_crcStreamSpec->SetStream(realOutStream);
_outStreamWithHashSpec->SetStream(realOutStream); _crcStreamSpec->Init(_checkCrc);
_outStreamWithHashSpec->Init(_checkCrc); _fileIsOpen = true;
if (askMode == NArchive::NExtract::NAskMode::kExtract && const CFileItem &fi = _db->Files[index];
(!realOutStream)) _rem = fi.Size;
{ if (askMode == NArchive::NExtract::NAskMode::kExtract && !realOutStream &&
const CFileItem &fi = _archiveDatabase->Files[index]; !_db->IsItemAnti(index) && !fi.IsDir)
if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir) askMode = NArchive::NExtract::NAskMode::kSkip;
askMode = NArchive::NExtract::NAskMode::kSkip;
}
return _extractCallback->PrepareOperation(askMode); return _extractCallback->PrepareOperation(askMode);
} }
HRESULT CFolderOutStream::WriteEmptyFiles() HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res)
{ {
for(;_currentIndex < _extractStatuses->Size(); _currentIndex++) _crcStreamSpec->ReleaseStream();
_fileIsOpen = false;
_currentIndex++;
return _extractCallback->SetOperationResult(res);
}
HRESULT CFolderOutStream::CloseFileAndSetResult()
{
const CFileItem &fi = _db->Files[_startIndex + _currentIndex];
return CloseFileAndSetResult(
(fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ?
NArchive::NExtract::NOperationResult::kOK :
NArchive::NExtract::NOperationResult::kCRCError);
}
HRESULT CFolderOutStream::ProcessEmptyFiles()
{
while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
{ {
UInt32 index = _startIndex + _currentIndex;
const CFileItem &fi = _archiveDatabase->Files[index];
if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir && fi.Size != 0)
return S_OK;
RINOK(OpenFile()); RINOK(OpenFile());
RINOK(_extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(CloseFileAndSetResult());
_outStreamWithHashSpec->ReleaseStream();
} }
return S_OK; return S_OK;
} }
STDMETHODIMP CFolderOutStream::Write(const void *data, STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
UInt32 size, UInt32 *processedSize)
{ {
UInt32 realProcessedSize = 0; if (processedSize != NULL)
while(_currentIndex < _extractStatuses->Size()) *processedSize = 0;
while (size != 0)
{ {
if (_fileIsOpen) if (_fileIsOpen)
{ {
UInt32 index = _startIndex + _currentIndex; UInt32 cur = size < _rem ? size : (UInt32)_rem;
const CFileItem &fi = _archiveDatabase->Files[index]; RINOK(_crcStream->Write(data, cur, &cur));
UInt64 fileSize = fi.Size; if (cur == 0)
break;
UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos, data = (const Byte *)data + cur;
UInt64(size - realProcessedSize)); size -= cur;
_rem -= cur;
UInt32 processedSizeLocal; if (processedSize != NULL)
RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, *processedSize += cur;
numBytesToWrite, &processedSizeLocal)); if (_rem == 0)
_filePos += processedSizeLocal;
realProcessedSize += processedSizeLocal;
if (_filePos == fileSize)
{ {
bool digestsAreEqual; RINOK(CloseFileAndSetResult());
if (fi.CrcDefined && _checkCrc) RINOK(ProcessEmptyFiles());
digestsAreEqual = fi.Crc == _outStreamWithHashSpec->GetCRC(); continue;
else
digestsAreEqual = true;
RINOK(_extractCallback->SetOperationResult(
digestsAreEqual ?
NArchive::NExtract::NOperationResult::kOK :
NArchive::NExtract::NOperationResult::kCRCError));
_outStreamWithHashSpec->ReleaseStream();
_fileIsOpen = false;
_currentIndex++;
}
if (realProcessedSize == size)
{
if (processedSize != NULL)
*processedSize = realProcessedSize;
return WriteEmptyFiles();
} }
} }
else else
{ {
RINOK(ProcessEmptyFiles());
if (_currentIndex == _extractStatuses->Size())
{
// we support partial extracting
if (processedSize != NULL)
*processedSize += size;
break;
}
RINOK(OpenFile()); RINOK(OpenFile());
_fileIsOpen = true;
_filePos = 0;
} }
} }
if (processedSize != NULL)
*processedSize = size;
return S_OK; return S_OK;
} }
HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
{ {
while(_currentIndex < _extractStatuses->Size()) while (_currentIndex < _extractStatuses->Size())
{ {
if (_fileIsOpen) if (_fileIsOpen)
{ {
RINOK(_extractCallback->SetOperationResult(resultEOperationResult)); RINOK(CloseFileAndSetResult(resultEOperationResult));
_outStreamWithHashSpec->ReleaseStream();
_fileIsOpen = false;
_currentIndex++;
} }
else else
{ {
RINOK(OpenFile()); RINOK(OpenFile());
_fileIsOpen = true;
} }
} }
return S_OK; return S_OK;
} }
HRESULT CFolderOutStream::WasWritingFinished()
{
if (_currentIndex == _extractStatuses->Size())
return S_OK;
return E_FAIL;
}
}} }}

View File

@@ -1,7 +1,7 @@
// 7zFolderOutStream.h // 7zFolderOutStream.h
#ifndef __7Z_FOLDEROUTSTREAM_H #ifndef __7Z_FOLDER_OUT_STREAM_H
#define __7Z_FOLDEROUTSTREAM_H #define __7Z_FOLDER_OUT_STREAM_H
#include "7zIn.h" #include "7zIn.h"
@@ -16,43 +16,39 @@ class CFolderOutStream:
public ISequentialOutStream, public ISequentialOutStream,
public CMyUnknownImp public CMyUnknownImp
{ {
COutStreamWithCRC *_crcStreamSpec;
CMyComPtr<ISequentialOutStream> _crcStream;
const CArchiveDatabaseEx *_db;
const CBoolVector *_extractStatuses;
CMyComPtr<IArchiveExtractCallback> _extractCallback;
UInt32 _ref2Offset;
UInt32 _startIndex;
int _currentIndex;
bool _testMode;
bool _checkCrc;
bool _fileIsOpen;
UInt64 _rem;
HRESULT OpenFile();
HRESULT CloseFileAndSetResult(Int32 res);
HRESULT CloseFileAndSetResult();
HRESULT ProcessEmptyFiles();
public: public:
MY_UNKNOWN_IMP MY_UNKNOWN_IMP
CFolderOutStream(); CFolderOutStream();
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
private:
COutStreamWithCRC *_outStreamWithHashSpec;
CMyComPtr<ISequentialOutStream> _outStreamWithHash;
const CArchiveDatabaseEx *_archiveDatabase;
const CBoolVector *_extractStatuses;
UInt32 _startIndex;
UInt32 _ref2Offset;
int _currentIndex;
// UInt64 _currentDataPos;
CMyComPtr<IArchiveExtractCallback> _extractCallback;
bool _testMode;
bool _fileIsOpen;
bool _checkCrc;
UInt64 _filePos;
HRESULT OpenFile();
HRESULT WriteEmptyFiles();
public:
HRESULT Init( HRESULT Init(
const CArchiveDatabaseEx *archiveDatabase, const CArchiveDatabaseEx *archiveDatabase,
UInt32 ref2Offset, UInt32 ref2Offset, UInt32 startIndex,
UInt32 startIndex,
const CBoolVector *extractStatuses, const CBoolVector *extractStatuses,
IArchiveExtractCallback *extractCallback, IArchiveExtractCallback *extractCallback,
bool testMode, bool testMode, bool checkCrc);
bool checkCrc);
HRESULT FlushCorrupted(Int32 resultEOperationResult); HRESULT FlushCorrupted(Int32 resultEOperationResult);
HRESULT WasWritingFinished(); HRESULT WasWritingFinished() const
{ return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
}; };
}} }}

View File

@@ -2,10 +2,7 @@
#include "StdAfx.h" #include "StdAfx.h"
extern "C" #include "../../../../C/CpuArch.h"
{
#include "../../../../C/CpuArch.h"
}
#include "../../../Common/ComTry.h" #include "../../../Common/ComTry.h"
#include "../../../Common/IntToString.h" #include "../../../Common/IntToString.h"
@@ -176,6 +173,8 @@ static UString GetStringForSizeValue(UInt32 value)
} }
static const UInt64 k_Copy = 0x0; 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_LZMA = 0x030101;
static const UInt64 k_PPMD = 0x030401; static const UInt64 k_PPMD = 0x030401;
@@ -183,12 +182,10 @@ static wchar_t GetHex(Byte value)
{ {
return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
} }
static inline UString GetHex2(Byte value) static inline void AddHexToString(UString &res, Byte value)
{ {
UString result; res += GetHex((Byte)(value >> 4));
result += GetHex((Byte)(value >> 4)); res += GetHex((Byte)(value & 0xF));
result += GetHex((Byte)(value & 0xF));
return result;
} }
#endif #endif
@@ -273,89 +270,82 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
UString methodsString; UString methodsString;
for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
{ {
const CCoderInfo &coderInfo = folderInfo.Coders[i]; const CCoderInfo &coder = folderInfo.Coders[i];
if (!methodsString.IsEmpty()) if (!methodsString.IsEmpty())
methodsString += L' '; methodsString += L' ';
UString methodName, propsString;
bool methodIsKnown = FindMethod(
EXTERNAL_CODECS_VARS
coder.MethodID, methodName);
if (!methodIsKnown)
methodsString += ConvertMethodIdToString(coder.MethodID);
else
{ {
UString methodName; methodsString += methodName;
bool methodIsKnown = FindMethod( if (coder.MethodID == k_Delta && coder.Props.GetCapacity() == 1)
EXTERNAL_CODECS_VARS propsString = ConvertUInt32ToString((UInt32)coder.Props[0] + 1);
coderInfo.MethodID, methodName); else if (coder.MethodID == k_LZMA && coder.Props.GetCapacity() == 5)
if (methodIsKnown)
{ {
methodsString += methodName; UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
if (coderInfo.MethodID == k_LZMA) propsString = GetStringForSizeValue(dicSize);
}
else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1)
{
Byte p = coder.Props[0];
UInt32 dicSize = (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11));
propsString = GetStringForSizeValue(dicSize);
}
else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5)
{
Byte order = *(const Byte *)coder.Props;
methodsString += L'o';
methodsString += ConvertUInt32ToString(order);
methodsString += L":mem";
UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
propsString = GetStringForSizeValue(dicSize);
}
else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1)
{
const Byte *data = (const Byte *)coder.Props;
Byte firstByte = *data++;
UInt32 numCyclesPower = firstByte & 0x3F;
propsString = ConvertUInt32ToString(numCyclesPower);
/*
if ((firstByte & 0xC0) != 0)
{ {
if (coderInfo.Props.GetCapacity() >= 5) UInt32 saltSize = (firstByte >> 7) & 1;
UInt32 ivSize = (firstByte >> 6) & 1;
if (coder.Props.GetCapacity() >= 2)
{ {
methodsString += L":"; Byte secondByte = *data++;
UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); saltSize += (secondByte >> 4);
methodsString += GetStringForSizeValue(dicSize); ivSize += (secondByte & 0x0F);
} }
} }
else if (coderInfo.MethodID == k_PPMD) */
}
}
if (!propsString.IsEmpty())
{
methodsString += L':';
methodsString += propsString;
}
else if (coder.Props.GetCapacity() > 0)
{
methodsString += L":[";
for (size_t bi = 0; bi < coder.Props.GetCapacity(); bi++)
{
if (bi > 5 && bi + 1 < coder.Props.GetCapacity())
{ {
if (coderInfo.Props.GetCapacity() >= 5) methodsString += L"..";
{ break;
Byte order = *(const Byte *)coderInfo.Props;
methodsString += L":o";
methodsString += ConvertUInt32ToString(order);
methodsString += L":mem";
UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1);
methodsString += GetStringForSizeValue(dicSize);
}
}
else if (coderInfo.MethodID == k_AES)
{
if (coderInfo.Props.GetCapacity() >= 1)
{
methodsString += L":";
const Byte *data = (const Byte *)coderInfo.Props;
Byte firstByte = *data++;
UInt32 numCyclesPower = firstByte & 0x3F;
methodsString += ConvertUInt32ToString(numCyclesPower);
/*
if ((firstByte & 0xC0) != 0)
{
methodsString += L":";
return S_OK;
UInt32 saltSize = (firstByte >> 7) & 1;
UInt32 ivSize = (firstByte >> 6) & 1;
if (coderInfo.Props.GetCapacity() >= 2)
{
Byte secondByte = *data++;
saltSize += (secondByte >> 4);
ivSize += (secondByte & 0x0F);
}
}
*/
}
} }
else else
{ AddHexToString(methodsString, coder.Props[bi]);
if (coderInfo.Props.GetCapacity() > 0)
{
methodsString += L":[";
for (size_t bi = 0; bi < coderInfo.Props.GetCapacity(); bi++)
{
if (bi > 5 && bi + 1 < coderInfo.Props.GetCapacity())
{
methodsString += L"..";
break;
}
else
methodsString += GetHex2(coderInfo.Props[bi]);
}
methodsString += L"]";
}
}
}
else
{
methodsString += ConvertMethodIdToString(coderInfo.MethodID);
} }
methodsString += L']';
} }
} }
prop = methodsString; prop = methodsString;

View File

@@ -5,9 +5,6 @@
#include "../../ICoder.h" #include "../../ICoder.h"
#include "../IArchive.h" #include "../IArchive.h"
#include "7zIn.h"
#include "7zCompressionMode.h"
#include "../../Common/CreateCoder.h" #include "../../Common/CreateCoder.h"
@@ -15,6 +12,9 @@
#include "../Common/HandlerOut.h" #include "../Common/HandlerOut.h"
#endif #endif
#include "7zCompressionMode.h"
#include "7zIn.h"
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
@@ -90,8 +90,6 @@ private:
CRecordVector<CBind> _binds; CRecordVector<CBind> _binds;
HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback);
HRESULT SetCompressionMethod(CCompressionMethodMode &method, HRESULT SetCompressionMethod(CCompressionMethodMode &method,
CObjectVector<COneMethodInfo> &methodsInfo CObjectVector<COneMethodInfo> &methodsInfo
#ifdef COMPRESS_MT #ifdef COMPRESS_MT

View File

@@ -40,31 +40,6 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
return S_OK; return S_OK;
} }
HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode,
IArchiveUpdateCallback *updateCallback)
{
CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
if (!getTextPassword)
{
CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback);
udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
}
if (getTextPassword)
{
CMyComBSTR password;
Int32 passwordIsDefined;
RINOK(getTextPassword->CryptoGetTextPassword2(
&passwordIsDefined, &password));
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
if (methodMode.PasswordIsDefined)
methodMode.Password = password;
}
else
methodMode.PasswordIsDefined = false;
return S_OK;
}
HRESULT CHandler::SetCompressionMethod( HRESULT CHandler::SetCompressionMethod(
CCompressionMethodMode &methodMode, CCompressionMethodMode &methodMode,
CCompressionMethodMode &headerMethod) CCompressionMethodMode &headerMethod)
@@ -210,7 +185,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
const CArchiveDatabaseEx *db = 0; const CArchiveDatabaseEx *db = 0;
#ifdef _7Z_VOL #ifdef _7Z_VOL
if(_volumes.Size() > 1) if (_volumes.Size() > 1)
return E_FAIL; return E_FAIL;
const CVolume *volume = 0; const CVolume *volume = 0;
if (_volumes.Size() == 1) if (_volumes.Size() == 1)
@@ -227,14 +202,13 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
for (UInt32 i = 0; i < numItems; i++) for (UInt32 i = 0; i < numItems; i++)
{ {
Int32 newData; Int32 newData, newProps;
Int32 newProperties;
UInt32 indexInArchive; UInt32 indexInArchive;
if (!updateCallback) if (!updateCallback)
return E_FAIL; return E_FAIL;
RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
CUpdateItem ui; CUpdateItem ui;
ui.NewProperties = IntToBool(newProperties); ui.NewProps = IntToBool(newProps);
ui.NewData = IntToBool(newData); ui.NewData = IntToBool(newData);
ui.IndexInArchive = indexInArchive; ui.IndexInArchive = indexInArchive;
ui.IndexInClient = i; ui.IndexInClient = i;
@@ -243,6 +217,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (ui.IndexInArchive != -1) if (ui.IndexInArchive != -1)
{ {
if (db == 0 || ui.IndexInArchive >= db->Files.Size())
return E_INVALIDARG;
const CFileItem &fi = db->Files[ui.IndexInArchive]; const CFileItem &fi = db->Files[ui.IndexInArchive];
ui.Name = fi.Name; ui.Name = fi.Name;
ui.IsDir = fi.IsDir; ui.IsDir = fi.IsDir;
@@ -254,7 +230,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime); ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime);
} }
if (ui.NewProperties) if (ui.NewProps)
{ {
bool nameIsDefined; bool nameIsDefined;
bool folderStatusIsDefined; bool folderStatusIsDefined;
@@ -350,7 +326,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
headerMethod.NumThreads = 1; headerMethod.NumThreads = 1;
#endif #endif
RINOK(SetPassword(methodMode, updateCallback)); CMyComPtr<ICryptoGetTextPassword2> getPassword2;
updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2);
if (getPassword2)
{
CMyComBSTR password;
Int32 passwordIsDefined;
RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
if (methodMode.PasswordIsDefined)
methodMode.Password = password;
}
else
methodMode.PasswordIsDefined = false;
bool compressMainHeader = _compressHeaders; // check it bool compressMainHeader = _compressHeaders; // check it
@@ -365,8 +354,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
encryptHeaders = _passwordIsDefined; encryptHeaders = _passwordIsDefined;
#endif #endif
compressMainHeader = true; compressMainHeader = true;
if(encryptHeaders) if (encryptHeaders)
RINOK(SetPassword(headerMethod, updateCallback)); {
headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined;
headerMethod.Password = methodMode.Password;
}
} }
if (numItems < 2) if (numItems < 2)
@@ -391,6 +383,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COutArchive archive; COutArchive archive;
CArchiveDatabase newDatabase; CArchiveDatabase newDatabase;
CMyComPtr<ICryptoGetTextPassword> getPassword;
updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword);
HRESULT res = Update( HRESULT res = Update(
EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS
#ifdef _7Z_VOL #ifdef _7Z_VOL
@@ -401,7 +397,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
db, db,
#endif #endif
updateItems, updateItems,
archive, newDatabase, outStream, updateCallback, options); archive, newDatabase, outStream, updateCallback, options
#ifndef _NO_CRYPTO
, getPassword
#endif
);
RINOK(res); RINOK(res);

View File

@@ -2,11 +2,8 @@
#include "StdAfx.h" #include "StdAfx.h"
extern "C" #include "../../../../C/7zCrc.h"
{ #include "../../../../C/CpuArch.h"
#include "../../../../C/7zCrc.h"
#include "../../../../C/CpuArch.h"
}
#include "../../Common/StreamObjects.h" #include "../../Common/StreamObjects.h"
#include "../../Common/StreamUtils.h" #include "../../Common/StreamUtils.h"
@@ -198,16 +195,16 @@ void CInByte2::ReadBytes(Byte *data, size_t size)
data[i] = _buffer[_pos++]; data[i] = _buffer[_pos++];
} }
void CInByte2::SkeepData(UInt64 size) void CInByte2::SkipData(UInt64 size)
{ {
if (size > _size - _pos) if (size > _size - _pos)
ThrowEndOfData(); ThrowEndOfData();
_pos += (size_t)size; _pos += (size_t)size;
} }
void CInByte2::SkeepData() void CInByte2::SkipData()
{ {
SkeepData(ReadNumber()); SkipData(ReadNumber());
} }
UInt64 CInByte2::ReadNumber() UInt64 CInByte2::ReadNumber()
@@ -363,7 +360,7 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
{ {
if (ReadID() == NID::kEnd) if (ReadID() == NID::kEnd)
break; break;
SkeepData(); SkipData();
} }
} }
@@ -456,7 +453,7 @@ void CInArchive::WaitAttribute(UInt64 attribute)
return; return;
if (type == NID::kEnd) if (type == NID::kEnd)
ThrowIncorrect(); ThrowIncorrect();
SkeepData(); SkipData();
} }
} }
@@ -502,7 +499,7 @@ void CInArchive::ReadPackInfo(
ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs);
continue; continue;
} }
SkeepData(); SkipData();
} }
if (packCRCsDefined.IsEmpty()) if (packCRCsDefined.IsEmpty())
{ {
@@ -563,7 +560,7 @@ void CInArchive::ReadUnpackInfo(
} }
continue; continue;
} }
SkeepData(); SkipData();
} }
} }
@@ -590,7 +587,7 @@ void CInArchive::ReadSubStreamsInfo(
break; break;
if (type == NID::kEnd) if (type == NID::kEnd)
break; break;
SkeepData(); SkipData();
} }
if (numUnpackStreamsInFolders.IsEmpty()) if (numUnpackStreamsInFolders.IsEmpty())
@@ -665,7 +662,7 @@ void CInArchive::ReadSubStreamsInfo(
return; return;
} }
else else
SkeepData(); SkipData();
type = ReadID(); type = ReadID();
} }
} }
@@ -1006,7 +1003,7 @@ HRESULT CInArchive::ReadHeader(
db.ArchiveInfo.FileInfoPopIDs.Add(type); db.ArchiveInfo.FileInfoPopIDs.Add(type);
} }
else else
SkeepData(size); SkipData(size);
bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 ||
db.ArchiveInfo.Version.Minor > 2); db.ArchiveInfo.Version.Minor > 2);
if (checkRecordsSize && _inByteBack->_pos - ppp != size) if (checkRecordsSize && _inByteBack->_pos - ppp != size)

View File

@@ -110,8 +110,8 @@ public:
} }
Byte ReadByte(); Byte ReadByte();
void ReadBytes(Byte *data, size_t size); void ReadBytes(Byte *data, size_t size);
void SkeepData(UInt64 size); void SkipData(UInt64 size);
void SkeepData(); void SkipData();
UInt64 ReadNumber(); UInt64 ReadNumber();
CNum ReadNum(); CNum ReadNum();
UInt32 ReadUInt32(); UInt32 ReadUInt32();
@@ -162,8 +162,8 @@ private:
UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt64 ReadID() { return _inByteBack->ReadNumber(); }
UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); } void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
void SkeepData() { _inByteBack->SkeepData(); } void SkipData() { _inByteBack->SkipData(); }
void WaitAttribute(UInt64 attribute); void WaitAttribute(UInt64 attribute);
void ReadArchiveProperties(CInArchiveInfo &archiveInfo); void ReadArchiveProperties(CInArchiveInfo &archiveInfo);

View File

@@ -2,16 +2,14 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../../C/7zCrc.h"
#include "../../../Common/AutoPtr.h" #include "../../../Common/AutoPtr.h"
#include "../../Common/StreamObjects.h" #include "../../Common/StreamObjects.h"
#include "7zOut.h" #include "7zOut.h"
extern "C"
{
#include "../../../../C/7zCrc.h"
}
static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size)
{ {
while (size > 0) while (size > 0)
@@ -141,7 +139,7 @@ void COutArchive::Close()
Stream.Release(); Stream.Release();
} }
HRESULT COutArchive::SkeepPrefixArchiveHeader() HRESULT COutArchive::SkipPrefixArchiveHeader()
{ {
#ifdef _7Z_VOL #ifdef _7Z_VOL
if (_endMarker) if (_endMarker)

View File

@@ -1,12 +1,12 @@
// 7z/Out.h // 7zOut.h
#ifndef __7Z_OUT_H #ifndef __7Z_OUT_H
#define __7Z_OUT_H #define __7Z_OUT_H
#include "7zHeader.h"
#include "7zItem.h"
#include "7zCompressionMode.h" #include "7zCompressionMode.h"
#include "7zEncode.h" #include "7zEncode.h"
#include "7zHeader.h"
#include "7zItem.h"
#include "../../Common/OutBuffer.h" #include "../../Common/OutBuffer.h"
@@ -137,7 +137,7 @@ public:
CMyComPtr<ISequentialOutStream> SeqStream; CMyComPtr<ISequentialOutStream> SeqStream;
HRESULT Create(ISequentialOutStream *stream, bool endMarker); HRESULT Create(ISequentialOutStream *stream, bool endMarker);
void Close(); void Close();
HRESULT SkeepPrefixArchiveHeader(); HRESULT SkipPrefixArchiveHeader();
HRESULT WriteDatabase( HRESULT WriteDatabase(
DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS
const CArchiveDatabase &db, const CArchiveDatabase &db,

View File

File diff suppressed because it is too large Load Diff

View File

@@ -3,9 +3,9 @@
#ifndef __7Z_UPDATE_H #ifndef __7Z_UPDATE_H
#define __7Z_UPDATE_H #define __7Z_UPDATE_H
#include "7zCompressionMode.h"
#include "7zIn.h" #include "7zIn.h"
#include "7zOut.h" #include "7zOut.h"
#include "7zCompressionMode.h"
#include "../IArchive.h" #include "../IArchive.h"
@@ -27,7 +27,7 @@ struct CUpdateItem
UInt32 Attrib; UInt32 Attrib;
bool NewData; bool NewData;
bool NewProperties; bool NewProps;
bool IsAnti; bool IsAnti;
bool IsDir; bool IsDir;
@@ -78,7 +78,11 @@ HRESULT Update(
CArchiveDatabase &newDatabase, CArchiveDatabase &newDatabase,
ISequentialOutStream *seqOutStream, ISequentialOutStream *seqOutStream,
IArchiveUpdateCallback *updateCallback, IArchiveUpdateCallback *updateCallback,
const CUpdateOptions &options); const CUpdateOptions &options
#ifndef _NO_CRYPTO
, ICryptoGetTextPassword *getDecoderPassword
#endif
);
}} }}
#endif #endif

View File

@@ -104,7 +104,7 @@ $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
$(COMPL) $(COMPL)
$(AR_COMMON_OBJS): ../Common/$(*B).cpp $(AR_COMMON_OBJS): ../Common/$(*B).cpp
$(COMPL) $(COMPL)
$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp $O\CopyCoder.obj: ../../Compress/$(*B).cpp
$(COMPL) $(COMPL)
$(C_OBJS): ../../../../C/$(*B).c $(C_OBJS): ../../../../C/$(*B).c
$(COMPL_O2) $(COMPL_O2)

View File

@@ -3,15 +3,12 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../Common/ComTry.h" #include "../../Common/ComTry.h"
#include "../../Common/Types.h"
#include "../../Windows/PropVariant.h" #include "../../Windows/PropVariant.h"
#include "../Common/RegisterArc.h" #include "../Common/RegisterArc.h"
#include "IArchive.h" static const unsigned int kNumArcsMax = 48;
#include "../ICoder.h"
#include "../IPassword.h"
static const unsigned int kNumArcsMax = 32;
static unsigned int g_NumArcs = 0; static unsigned int g_NumArcs = 0;
static const CArcInfo *g_Arcs[kNumArcsMax]; static const CArcInfo *g_Arcs[kNumArcsMax];
void RegisterArc(const CArcInfo *arcInfo) void RegisterArc(const CArcInfo *arcInfo)

View File

@@ -2,14 +2,14 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../C/CpuArch.h"
#include "Common/ComTry.h" #include "Common/ComTry.h"
#include "Common/StringConvert.h" #include "Common/StringConvert.h"
#include "Windows/PropVariant.h" #include "Windows/PropVariant.h"
#include "Windows/Time.h" #include "Windows/Time.h"
#include "../../../C/CpuArch.h"
#include "../Common/LimitedStreams.h" #include "../Common/LimitedStreams.h"
#include "../Common/ProgressUtils.h" #include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h" #include "../Common/RegisterArc.h"
@@ -180,6 +180,7 @@ struct CItem
UInt32 PackSize; UInt32 PackSize;
UInt32 Size; UInt32 Size;
UInt32 FileCRC; UInt32 FileCRC;
UInt32 SplitPos;
Byte Version; Byte Version;
Byte ExtractVersion; Byte ExtractVersion;
@@ -197,6 +198,8 @@ struct CItem
bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kGarbled) != 0; } bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kGarbled) != 0; }
bool IsDir() const { return (FileType == NFileHeader::NFileType::kDirectory); } bool IsDir() const { return (FileType == NFileHeader::NFileType::kDirectory); }
bool IsSplitAfter() const { return (Flags & NFileHeader::NFlags::kVolume) != 0; }
bool IsSplitBefore() const { return (Flags & NFileHeader::NFlags::kExtFile) != 0; }
UInt32 GetWinAttributes() const UInt32 GetWinAttributes() const
{ {
UInt32 winAtrributes; UInt32 winAtrributes;
@@ -240,6 +243,10 @@ HRESULT CItem::Parse(const Byte *p, unsigned size)
// FirstChapter = p[28]; // FirstChapter = p[28];
// FirstChapter = p[29]; // FirstChapter = p[29];
SplitPos = 0;
if (IsSplitBefore() && firstHeaderSize >= 34)
SplitPos = Get32(p + 30);
unsigned pos = firstHeaderSize; unsigned pos = firstHeaderSize;
unsigned size1 = size - pos; unsigned size1 = size - pos;
RINOK(ReadString(p + pos, size1, Name)); RINOK(ReadString(p + pos, size1, Name));
@@ -270,7 +277,7 @@ class CInArchive
HRESULT ReadBlock(bool &filled); HRESULT ReadBlock(bool &filled);
HRESULT ReadSignatureAndBlock(bool &filled); HRESULT ReadSignatureAndBlock(bool &filled);
HRESULT SkeepExtendedHeaders(); HRESULT SkipExtendedHeaders();
HRESULT SafeReadBytes(void *data, UInt32 size); HRESULT SafeReadBytes(void *data, UInt32 size);
@@ -389,7 +396,7 @@ HRESULT CInArchive::ReadSignatureAndBlock(bool &filled)
return ReadBlock(filled); return ReadBlock(filled);
} }
HRESULT CInArchive::SkeepExtendedHeaders() HRESULT CInArchive::SkipExtendedHeaders()
{ {
for (UInt32 i = 0;; i++) for (UInt32 i = 0;; i++)
{ {
@@ -412,7 +419,7 @@ HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit)
if (!filled) if (!filled)
return S_FALSE; return S_FALSE;
RINOK(Header.Parse(_block, _blockSize)); RINOK(Header.Parse(_block, _blockSize));
return SkeepExtendedHeaders(); return SkipExtendedHeaders();
} }
HRESULT CInArchive::GetNextItem(bool &filled, CItem &item) HRESULT CInArchive::GetNextItem(bool &filled, CItem &item)
@@ -428,7 +435,7 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItem &item)
extraData = GetUi32(_block + pos); extraData = GetUi32(_block + pos);
*/ */
RINOK(SkeepExtendedHeaders()); RINOK(SkipExtendedHeaders());
filled = true; filled = true;
return S_OK; return S_OK;
} }
@@ -482,8 +489,9 @@ STATPROPSTG kProps[] =
{ {
{ NULL, kpidPath, VT_BSTR}, { NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL}, { NULL, kpidIsDir, VT_BOOL},
{ NULL, kpidSize, VT_UI8}, { NULL, kpidSize, VT_UI4},
{ NULL, kpidPackSize, VT_UI8}, { NULL, kpidPosition, VT_UI8},
{ NULL, kpidPackSize, VT_UI4},
{ NULL, kpidMTime, VT_FILETIME}, { NULL, kpidMTime, VT_FILETIME},
{ NULL, kpidAttrib, VT_UI4}, { NULL, kpidAttrib, VT_UI4},
{ NULL, kpidEncrypted, VT_BOOL}, { NULL, kpidEncrypted, VT_BOOL},
@@ -556,6 +564,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidIsDir: prop = item.IsDir(); break; case kpidIsDir: prop = item.IsDir(); break;
case kpidSize: prop = item.Size; break; case kpidSize: prop = item.Size; break;
case kpidPackSize: prop = item.PackSize; break; case kpidPackSize: prop = item.PackSize; break;
case kpidPosition: if (item.IsSplitBefore() || item.IsSplitAfter()) prop = (UInt64)item.SplitPos; break;
case kpidAttrib: prop = item.GetWinAttributes(); break; case kpidAttrib: prop = item.GetWinAttributes(); break;
case kpidEncrypted: prop = item.IsEncrypted(); break; case kpidEncrypted: prop = item.IsEncrypted(); break;
case kpidCRC: prop = item.FileCRC; break; case kpidCRC: prop = item.FileCRC; break;

View File

@@ -1,216 +0,0 @@
// BZip2Handler.cpp
#include "StdAfx.h"
#include "Common/ComTry.h"
#include "Windows/PropVariant.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamUtils.h"
#include "../Common/DummyOutStream.h"
#include "BZip2Handler.h"
using namespace NWindows;
namespace NArchive {
namespace NBZip2 {
static const CMethodId kMethodId_BZip2 = 0x040202;
STATPROPSTG kProps[] =
{
{ NULL, kpidPackSize, VT_UI8}
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = 1;
return S_OK;
}
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case kpidPackSize: prop = _item.PackSize; break;
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CHandler::Open(IInStream *stream,
const UInt64 * /* maxCheckStartPosition */,
IArchiveOpenCallback * /* openArchiveCallback */)
{
COM_TRY_BEGIN
try
{
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition));
const int kSignatureSize = 3;
Byte buffer[kSignatureSize];
RINOK(ReadStream_FALSE(stream, buffer, kSignatureSize));
if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h')
return S_FALSE;
UInt64 endPosition;
RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition));
_item.PackSize = endPosition - _streamStartPosition;
_stream = stream;
}
catch(...)
{
return S_FALSE;
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
_stream.Release();
return S_OK;
}
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
bool allFilesMode = (numItems == UInt32(-1));
if (!allFilesMode)
{
if (numItems == 0)
return S_OK;
if (numItems != 1)
return E_INVALIDARG;
if (indices[0] != 0)
return E_INVALIDARG;
}
bool testMode = (testModeSpec != 0);
extractCallback->SetTotal(_item.PackSize);
UInt64 currentTotalPacked = 0;
RINOK(extractCallback->SetCompleted(&currentTotalPacked));
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode;
askMode = testMode ? NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
if(!testMode && !realOutStream)
return S_OK;
extractCallback->PrepareOperation(askMode);
CMyComPtr<ICompressCoder> decoder;
HRESULT loadResult = CreateCoder(
EXTERNAL_CODECS_VARS
kMethodId_BZip2, decoder, false);
if (loadResult != S_OK || !decoder)
{
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
return S_OK;
}
#ifdef COMPRESS_MT
{
CMyComPtr<ICompressSetCoderMt> setCoderMt;
decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
if (setCoderMt)
{
RINOK(setCoderMt->SetNumberOfThreads(_numThreads));
}
}
#endif
CDummyOutStream *outStreamSpec = new CDummyOutStream;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->SetStream(realOutStream);
outStreamSpec->Init();
realOutStream.Release();
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, true);
RINOK(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL));
HRESULT result = S_OK;
bool firstItem = true;
for (;;)
{
lps->InSize = currentTotalPacked;
lps->OutSize = outStreamSpec->GetSize();
RINOK(lps->SetCur());
const int kSignatureSize = 3;
Byte buffer[kSignatureSize];
size_t processedSize = kSignatureSize;
RINOK(ReadStream(_stream, buffer, &processedSize));
if (processedSize != kSignatureSize)
{
if (firstItem)
return E_FAIL;
break;
}
if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h')
{
if (firstItem)
return E_FAIL;
break;
}
firstItem = false;
UInt64 dataStartPos;
RINOK(_stream->Seek((UInt64)(Int64)(-3), STREAM_SEEK_CUR, &dataStartPos));
result = decoder->Code(_stream, outStream, NULL, NULL, progress);
if (result != S_OK)
break;
CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;
decoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize);
if (!getInStreamProcessedSize)
break;
UInt64 packSize;
RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&packSize));
UInt64 pos;
RINOK(_stream->Seek(dataStartPos + packSize, STREAM_SEEK_SET, &pos));
currentTotalPacked = pos - _streamStartPosition;
}
outStream.Release();
Int32 retResult;
if (result == S_OK)
retResult = NExtract::NOperationResult::kOK;
else if (result == S_FALSE)
retResult = NExtract::NOperationResult::kDataError;
else
return result;
return extractCallback->SetOperationResult(retResult);
COM_TRY_END
}
IMPL_ISetCompressCodecsInfo
}}

View File

@@ -1,68 +0,0 @@
// BZip2/Handler.h
#ifndef __BZIP2_HANDLER_H
#define __BZIP2_HANDLER_H
#include "Common/MyCom.h"
#include "../IArchive.h"
#include "../../Common/CreateCoder.h"
#include "BZip2Item.h"
#ifdef COMPRESS_MT
#include "../../../Windows/System.h"
#endif
namespace NArchive {
namespace NBZip2 {
class CHandler:
public IInArchive,
public IOutArchive,
public ISetProperties,
PUBLIC_ISetCompressCodecsInfo
public CMyUnknownImp
{
CMyComPtr<IInStream> _stream;
NArchive::NBZip2::CItem _item;
UInt64 _streamStartPosition;
UInt32 _level;
UInt32 _dicSize;
UInt32 _numPasses;
#ifdef COMPRESS_MT
UInt32 _numThreads;
#endif
DECL_EXTERNAL_CODECS_VARS
void InitMethodProperties()
{
_level = 5;
_dicSize =
_numPasses = 0xFFFFFFFF;
#ifdef COMPRESS_MT
_numThreads = NWindows::NSystem::GetNumberOfProcessors();;
#endif
}
public:
MY_QUERYINTERFACE_BEGIN2(IInArchive)
MY_QUERYINTERFACE_ENTRY(IOutArchive)
MY_QUERYINTERFACE_ENTRY(ISetProperties)
QUERY_ENTRY_ISetCompressCodecsInfo
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);
DECL_ISetCompressCodecsInfo
CHandler() { InitMethodProperties(); }
};
}}
#endif

View File

@@ -1,156 +0,0 @@
// BZip2HandlerOut.cpp
#include "StdAfx.h"
#include "BZip2Handler.h"
#include "BZip2Update.h"
#include "Common/Defs.h"
#include "Windows/PropVariant.h"
#include "../../Compress/CopyCoder.h"
#include "../Common/ParseProperties.h"
using namespace NWindows;
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;
namespace NArchive {
namespace NBZip2 {
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
{
*type = NFileTimeType::kUnix;
return S_OK;
}
static HRESULT CopyStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream)
{
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
}
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
if (numItems != 1)
return E_INVALIDARG;
Int32 newData;
Int32 newProperties;
UInt32 indexInArchive;
if (!updateCallback)
return E_FAIL;
RINOK(updateCallback->GetUpdateItemInfo(0,&newData, &newProperties, &indexInArchive));
if (IntToBool(newProperties))
{
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
if (prop.vt == VT_BOOL)
{
if (prop.boolVal != VARIANT_FALSE)
return E_INVALIDARG;
}
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
}
}
if (IntToBool(newData))
{
UInt64 size;
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
if (prop.vt != VT_UI8)
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(
EXTERNAL_CODECS_VARS
size, outStream, 0, dicSize, numPasses,
#ifdef COMPRESS_MT
_numThreads,
#endif
updateCallback);
}
if (indexInArchive != 0)
return E_INVALIDARG;
RINOK(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL));
return CopyStreams(_stream, outStream);
}
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
{
InitMethodProperties();
#ifdef COMPRESS_MT
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
_numThreads = numProcessors;
#endif
for (int i = 0; i < numProperties; i++)
{
UString name = UString(names[i]);
name.MakeUpper();
if (name.IsEmpty())
return E_INVALIDARG;
const PROPVARIANT &prop = values[i];
if (name[0] == 'X')
{
UInt32 level = 9;
RINOK(ParsePropValue(name.Mid(1), prop, level));
_level = level;
continue;
}
if (name[0] == 'D')
{
UInt32 dicSize = kDicSizeX5;
RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));
_dicSize = dicSize;
continue;
}
if (name.Left(4) == L"PASS")
{
UInt32 num = kNumPassesX9;
RINOK(ParsePropValue(name.Mid(4), prop, num));
_numPasses = num;
continue;
}
if (name.Left(2) == L"MT")
{
#ifdef COMPRESS_MT
RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads));
#endif
continue;
}
return E_INVALIDARG;
}
return S_OK;
}
}}

View File

@@ -1,20 +0,0 @@
// Archive/BZip2Item.h
#ifndef __ARCHIVE_BZIP2_ITEM_H
#define __ARCHIVE_BZIP2_ITEM_H
namespace NArchive {
namespace NBZip2 {
struct CItem
{
UInt64 PackSize;
UInt64 UnPackSize;
};
}}
#endif

View File

@@ -1,74 +0,0 @@
// BZip2Update.cpp
#include "StdAfx.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/CreateCoder.h"
#include "Windows/PropVariant.h"
#include "BZip2Update.h"
namespace NArchive {
namespace NBZip2 {
static const CMethodId kMethodId_BZip2 = 0x040202;
HRESULT UpdateArchive(
DECL_EXTERNAL_CODECS_LOC_VARS
UInt64 unpackSize,
ISequentialOutStream *outStream,
int indexInClient,
UInt32 dictionary,
UInt32 numPasses,
#ifdef COMPRESS_MT
UInt32 numThreads,
#endif
IArchiveUpdateCallback *updateCallback)
{
RINOK(updateCallback->SetTotal(unpackSize));
UInt64 complexity = 0;
RINOK(updateCallback->SetCompleted(&complexity));
CMyComPtr<ISequentialInStream> fileInStream;
RINOK(updateCallback->GetStream(indexInClient, &fileInStream));
CLocalProgress *localProgressSpec = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
localProgressSpec->Init(updateCallback, true);
CMyComPtr<ICompressCoder> encoder;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
kMethodId_BZip2, encoder, true));
if (!encoder)
return E_NOTIMPL;
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);
if (setCoderProperties)
{
NWindows::NCOM::CPropVariant properties[] =
{
dictionary,
numPasses
#ifdef COMPRESS_MT
, numThreads
#endif
};
PROPID propIDs[] =
{
NCoderPropID::kDictionarySize,
NCoderPropID::kNumPasses
#ifdef COMPRESS_MT
, NCoderPropID::kNumThreads
#endif
};
RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0])));
}
RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
}
}}

View File

@@ -1,26 +0,0 @@
// BZip2Update.h
#ifndef __BZIP2_UPDATE_H
#define __BZIP2_UPDATE_H
#include "../IArchive.h"
#include "../../Common/CreateCoder.h"
namespace NArchive {
namespace NBZip2 {
HRESULT UpdateArchive(
DECL_EXTERNAL_CODECS_LOC_VARS
UInt64 unpackSize,
ISequentialOutStream *outStream,
int indexInClient,
UInt32 dictionary,
UInt32 numPasses,
#ifdef COMPRESS_MT
UInt32 numThreads,
#endif
IArchiveUpdateCallback *updateCallback);
}}
#endif

View File

@@ -1,8 +0,0 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#endif

View File

@@ -1,18 +0,0 @@
// BZip2Register.cpp
#include "StdAfx.h"
#include "../../Common/RegisterArc.h"
#include "BZip2Handler.h"
static IInArchive *CreateArc() { return new NArchive::NBZip2::CHandler; }
#ifndef EXTRACT_ONLY
static IOutArchive *CreateArcOut() { return new NArchive::NBZip2::CHandler; }
#else
#define CreateArcOut 0
#endif
static CArcInfo g_ArcInfo =
{ L"BZip2", L"bz2 bzip2 tbz2 tbz", L"* * .tar .tar", 2, { 'B', 'Z', 'h' }, 3, true, CreateArc, CreateArcOut };
REGISTER_ARC(BZip2)

428
CPP/7zip/Archive/Bz2Handler.cpp Executable file
View File

@@ -0,0 +1,428 @@
// Bz2Handler.cpp
#include "StdAfx.h"
#include "Common/ComTry.h"
#include "Windows/PropVariant.h"
#ifdef COMPRESS_MT
#include "../../Windows/System.h"
#endif
#include "../Common/CreateCoder.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
#include "../Compress/BZip2Decoder.h"
#include "../Compress/BZip2Encoder.h"
#include "../Compress/CopyCoder.h"
#include "Common/DummyOutStream.h"
#include "Common/ParseProperties.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,
public IOutArchive,
public ISetProperties,
public CMyUnknownImp
{
CMyComPtr<IInStream> _stream;
CMyComPtr<ISequentialInStream> _seqStream;
UInt64 _packSize;
UInt64 _startPosition;
bool _packSizeDefined;
UInt32 _level;
UInt32 _dicSize;
UInt32 _numPasses;
#ifdef COMPRESS_MT
UInt32 _numThreads;
#endif
void InitMethodProperties()
{
_level = 5;
_dicSize =
_numPasses = 0xFFFFFFFF;
#ifdef COMPRESS_MT
_numThreads = NWindows::NSystem::GetNumberOfProcessors();;
#endif
}
public:
MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
CHandler() { InitMethodProperties(); }
};
STATPROPSTG kProps[] =
{
{ NULL, kpidPackSize, VT_UI8}
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO_Table
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch(propID)
{
case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = 1;
return S_OK;
}
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
}
prop.Detach(value);
return S_OK;
}
STDMETHODIMP CHandler::Open(IInStream *stream,
const UInt64 * /* maxCheckStartPosition */,
IArchiveOpenCallback * /* openArchiveCallback */)
{
COM_TRY_BEGIN
try
{
Close();
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPosition));
const int kSignatureSize = 3;
Byte buf[kSignatureSize];
RINOK(ReadStream_FALSE(stream, buf, kSignatureSize));
if (buf[0] != 'B' || buf[1] != 'Z' || buf[2] != 'h')
return S_FALSE;
UInt64 endPosition;
RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition));
_packSize = endPosition - _startPosition;
_packSizeDefined = true;
_stream = stream;
_seqStream = stream;
}
catch(...) { return S_FALSE; }
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
{
Close();
_seqStream = stream;
return S_OK;
}
STDMETHODIMP CHandler::Close()
{
_packSizeDefined = false;
_seqStream.Release();
_stream.Release();
return S_OK;
}
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)-1);
if (!allFilesMode)
{
if (numItems == 0)
return S_OK;
if (numItems != 1 || indices[0] != 0)
return E_INVALIDARG;
}
bool testMode = (_aTestMode != 0);
if (_stream)
extractCallback->SetTotal(_packSize);
UInt64 currentTotalPacked = 0;
RINOK(extractCallback->SetCompleted(&currentTotalPacked));
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
if (!testMode && !realOutStream)
return S_OK;
extractCallback->PrepareOperation(askMode);
NCompress::NBZip2::CDecoder *decoderSpec = new NCompress::NBZip2::CDecoder;
CMyComPtr<ICompressCoder> decoder = decoderSpec;
if (_stream)
{
RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));
}
decoderSpec->SetInStream(_seqStream);
#if defined( COMPRESS_MT) && defined( COMPRESS_BZIP2_MT)
RINOK(decoderSpec->SetNumberOfThreads(_numThreads));
#endif
CDummyOutStream *outStreamSpec = new CDummyOutStream;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->SetStream(realOutStream);
outStreamSpec->Init();
realOutStream.Release();
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, true);
HRESULT result = S_OK;
bool firstItem = true;
for (;;)
{
lps->InSize = currentTotalPacked;
lps->OutSize = outStreamSpec->GetSize();
RINOK(lps->SetCur());
bool isBz2;
result = decoderSpec->CodeResume(outStream, isBz2, progress);
if (result != S_OK)
break;
if (!isBz2)
{
if (firstItem)
result = S_FALSE;
break;
}
firstItem = false;
_packSize = currentTotalPacked = decoderSpec->GetInputProcessedSize();
_packSizeDefined = true;
}
decoderSpec->ReleaseInStream();
outStream.Release();
Int32 retResult;
if (result == S_OK)
retResult = NExtract::NOperationResult::kOK;
else if (result == S_FALSE)
retResult = NExtract::NOperationResult::kDataError;
else
return result;
return extractCallback->SetOperationResult(retResult);
COM_TRY_END
}
static HRESULT UpdateArchive(
UInt64 unpackSize,
ISequentialOutStream *outStream,
int indexInClient,
UInt32 dictionary,
UInt32 numPasses,
#ifdef COMPRESS_MT
UInt32 numThreads,
#endif
IArchiveUpdateCallback *updateCallback)
{
RINOK(updateCallback->SetTotal(unpackSize));
UInt64 complexity = 0;
RINOK(updateCallback->SetCompleted(&complexity));
CMyComPtr<ISequentialInStream> fileInStream;
RINOK(updateCallback->GetStream(indexInClient, &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
#ifdef COMPRESS_MT
, numThreads
#endif
};
PROPID propIDs[] =
{
NCoderPropID::kDictionarySize,
NCoderPropID::kNumPasses
#ifdef COMPRESS_MT
, NCoderPropID::kNumThreads
#endif
};
RINOK(encoderSpec->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0])));
}
RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
}
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
{
*type = NFileTimeType::kUnix;
return S_OK;
}
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
if (numItems != 1)
return E_INVALIDARG;
Int32 newData, newProps;
UInt32 indexInArchive;
if (!updateCallback)
return E_FAIL;
RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));
if (IntToBool(newProps))
{
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
if (prop.vt == VT_BOOL)
{
if (prop.boolVal != VARIANT_FALSE)
return E_INVALIDARG;
}
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
}
}
if (IntToBool(newData))
{
UInt64 size;
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
if (prop.vt != VT_UI8)
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,
#ifdef COMPRESS_MT
_numThreads,
#endif
updateCallback);
}
if (indexInArchive != 0)
return E_INVALIDARG;
if (_stream)
RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));
return NCompress::CopyStream(_stream, outStream, NULL);
}
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
{
InitMethodProperties();
#ifdef COMPRESS_MT
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")
{
#ifdef COMPRESS_MT
RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads));
#endif
}
else
return E_INVALIDARG;
}
return S_OK;
}
static IInArchive *CreateArc() { return new CHandler; }
#ifndef EXTRACT_ONLY
static IOutArchive *CreateArcOut() { return new CHandler; }
#else
#define CreateArcOut 0
#endif
static CArcInfo g_ArcInfo =
{ L"BZip2", L"bz2 bzip2 tbz2 tbz", L"* * .tar .tar", 2, { 'B', 'Z', 'h' }, 3, true, CreateArc, CreateArcOut };
REGISTER_ARC(BZip2)
}}

View File

@@ -2,10 +2,7 @@
#include "StdAfx.h" #include "StdAfx.h"
extern "C"
{
#include "../../../../C/Alloc.h" #include "../../../../C/Alloc.h"
}
#include "Common/Defs.h" #include "Common/Defs.h"

View File

@@ -57,7 +57,7 @@ void CInArchive::ReadOtherArchive(COtherArchive &oa)
oa.DiskName = SafeReadName(); oa.DiskName = SafeReadName();
} }
void CInArchive::Skeep(size_t size) void CInArchive::Skip(size_t size)
{ {
while (size-- != 0) while (size-- != 0)
ReadByte(); ReadByte();
@@ -104,7 +104,7 @@ HRESULT CInArchive::Open2(IInStream *stream,
ai.PerFolderAreaSize = ReadByte(); ai.PerFolderAreaSize = ReadByte();
ai.PerDataBlockAreaSize = ReadByte(); ai.PerDataBlockAreaSize = ReadByte();
Skeep(ai.PerCabinetAreaSize); Skip(ai.PerCabinetAreaSize);
} }
{ {
@@ -124,7 +124,7 @@ HRESULT CInArchive::Open2(IInStream *stream,
folder.CompressionTypeMajor = ReadByte(); folder.CompressionTypeMajor = ReadByte();
folder.CompressionTypeMinor = ReadByte(); folder.CompressionTypeMinor = ReadByte();
Skeep(ai.PerFolderAreaSize); Skip(ai.PerFolderAreaSize);
database.Folders.Add(folder); database.Folders.Add(folder);
} }

View File

@@ -149,7 +149,7 @@ class CInArchive
UInt16 ReadUInt16(); UInt16 ReadUInt16();
UInt32 ReadUInt32(); UInt32 ReadUInt32();
AString SafeReadName(); AString SafeReadName();
void Skeep(size_t size); void Skip(size_t size);
void ReadOtherArchive(COtherArchive &oa); void ReadOtherArchive(COtherArchive &oa);
HRESULT Open2(IInStream *inStream, HRESULT Open2(IInStream *inStream,

View File

@@ -2,13 +2,11 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Common/StringConvert.h"
#include "Common/MyCom.h"
#include "Common/UTFConvert.h"
#include "Common/IntToString.h" #include "Common/IntToString.h"
#include "Windows/Defs.h" #include "Common/UTFConvert.h"
#include "../../Common/LimitedStreams.h" #include "../../Common/LimitedStreams.h"
#include "ChmIn.h" #include "ChmIn.h"
namespace NArchive{ namespace NArchive{
@@ -96,9 +94,8 @@ UString CMethodInfo::GetName() const
if (IsLzx()) if (IsLzx())
{ {
s = L"LZX:"; s = L"LZX:";
UInt32 numDictBits = LzxInfo.GetNumDictBits(); wchar_t temp[16];
wchar_t temp[32]; ConvertUInt32ToString(LzxInfo.GetNumDictBits(), temp);
ConvertUInt64ToString(numDictBits, temp);
s += temp; s += temp;
} }
else else
@@ -111,7 +108,7 @@ UString CMethodInfo::GetName() const
s2 = GetGuidString(); s2 = GetGuidString();
if (ControlData.GetCapacity() > 0) if (ControlData.GetCapacity() > 0)
{ {
s2 += ":"; s2 += ':';
for (size_t i = 0; i < ControlData.GetCapacity(); i++) for (size_t i = 0; i < ControlData.GetCapacity(); i++)
PrintByte(ControlData[i], s2); PrintByte(ControlData[i], s2);
} }
@@ -141,7 +138,7 @@ UString CSectionInfo::GetMethodName() const
for (int i = 0; i < Methods.Size(); i++) for (int i = 0; i < Methods.Size(); i++)
{ {
if (i != 0) if (i != 0)
s += L" "; s += L' ';
s += Methods[i].GetName(); s += Methods[i].GetName();
} }
return s; return s;
@@ -155,7 +152,7 @@ Byte CInArchive::ReadByte()
return b; return b;
} }
void CInArchive::Skeep(size_t size) void CInArchive::Skip(size_t size)
{ {
while (size-- != 0) while (size-- != 0)
ReadByte(); ReadByte();
@@ -221,7 +218,7 @@ void CInArchive::ReadString(int size, AString &s)
char c = (char)ReadByte(); char c = (char)ReadByte();
if (c == 0) if (c == 0)
{ {
Skeep(size); Skip(size);
return; return;
} }
s += c; s += c;
@@ -236,7 +233,7 @@ void CInArchive::ReadUString(int size, UString &s)
wchar_t c = ReadUInt16(); wchar_t c = ReadUInt16();
if (c == 0) if (c == 0)
{ {
Skeep(2 * size); Skip(2 * size);
return; return;
} }
s += c; s += c;
@@ -372,12 +369,12 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
RINOK(ReadDirEntry(database)); RINOK(ReadDirEntry(database));
numItems++; numItems++;
} }
Skeep(quickrefLength - 2); Skip(quickrefLength - 2);
if (ReadUInt16() != numItems) if (ReadUInt16() != numItems)
return S_FALSE; return S_FALSE;
} }
else else
Skeep(dirChunkSize - 4); Skip(dirChunkSize - 4);
} }
return S_OK; return S_OK;
} }
@@ -579,7 +576,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
} }
numItems++; numItems++;
} }
Skeep(quickrefLength - 2); Skip(quickrefLength - 2);
if (ReadUInt16() != numItems) if (ReadUInt16() != numItems)
return S_FALSE; return S_FALSE;
if (numItems > numDirEntries) if (numItems > numDirEntries)
@@ -587,7 +584,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
numDirEntries -= numItems; numDirEntries -= numItems;
} }
else else
Skeep(dirChunkSize - 4); Skip(dirChunkSize - 4);
} }
return numDirEntries == 0 ? S_OK : S_FALSE; return numDirEntries == 0 ? S_OK : S_FALSE;
} }

View File

@@ -3,10 +3,12 @@
#ifndef __ARCHIVE_CHM_IN_H #ifndef __ARCHIVE_CHM_IN_H
#define __ARCHIVE_CHM_IN_H #define __ARCHIVE_CHM_IN_H
#include "Common/MyString.h"
#include "Common/Buffer.h" #include "Common/Buffer.h"
#include "Common/MyString.h"
#include "../../IStream.h" #include "../../IStream.h"
#include "../../Common/InBuffer.h" #include "../../Common/InBuffer.h"
#include "ChmHeader.h" #include "ChmHeader.h"
namespace NArchive { namespace NArchive {
@@ -215,7 +217,7 @@ class CInArchive
Byte ReadByte(); Byte ReadByte();
void ReadBytes(Byte *data, UInt32 size); void ReadBytes(Byte *data, UInt32 size);
void Skeep(size_t size); void Skip(size_t size);
UInt16 ReadUInt16(); UInt16 ReadUInt16();
UInt32 ReadUInt32(); UInt32 ReadUInt32();
UInt64 ReadUInt64(); UInt64 ReadUInt64();

View File

@@ -3,8 +3,15 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Common/ComTry.h" #include "Common/ComTry.h"
#include "Windows/PropVariant.h" #include "Windows/PropVariant.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamUtils.h" #include "../../Common/StreamUtils.h"
#include "../../Compress/CopyCoder.h"
#include "ComHandler.h" #include "ComHandler.h"
namespace NArchive { namespace NArchive {
@@ -15,16 +22,15 @@ STATPROPSTG kProps[] =
{ NULL, kpidPath, VT_BSTR}, { NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL}, { NULL, kpidIsDir, VT_BOOL},
{ NULL, kpidSize, VT_UI8}, { NULL, kpidSize, VT_UI8},
// { NULL, kpidAttributes, VT_UI4},
{ NULL, kpidPackSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8},
{ NULL, kpidCTime, VT_FILETIME}, { NULL, kpidCTime, VT_FILETIME},
{ NULL, kpidMTime, VT_FILETIME} { NULL, kpidMTime, VT_FILETIME}
}; };
STATPROPSTG kArcProps[] = STATPROPSTG kArcProps[] =
{ {
{ NULL, kpidClusterSize, VT_UI4} { NULL, kpidClusterSize, VT_UI4},
{ NULL, kpidSectorSize, VT_UI4}
}; };
IMP_IInArchive_Props IMP_IInArchive_Props
@@ -37,6 +43,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
switch(propID) switch(propID)
{ {
case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break; case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break;
case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break;
} }
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;
@@ -52,33 +59,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
switch(propID) switch(propID)
{ {
case kpidPath: case kpidPath: prop = _db.GetItemPath(index); break;
{
UString name = _db.GetItemPath(index);
prop = name;
break;
}
case kpidIsDir: prop = item.IsDir(); break; case kpidIsDir: prop = item.IsDir(); break;
case kpidCTime: prop = item.CTime; break; case kpidCTime: prop = item.CTime; break;
case kpidMTime: prop = item.MTime; break; case kpidMTime: prop = item.MTime; break;
/* case kpidPackSize: if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break;
case kpidAttributes: case kpidSize: if (!item.IsDir()) prop = item.Size; break;
prop = item.Falgs;
break;
*/
case kpidPackSize:
if (!item.IsDir())
{
int numBits = _db.IsLargeStream(item.Size) ?
_db.SectorSizeBits :
_db.MiniSectorSizeBits;
prop = (item.Size + ((UInt64)1 << numBits) - 1) >> numBits << numBits;
break;
}
case kpidSize:
if (!item.IsDir())
prop = (UInt64)item.Size;
break;
} }
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;
@@ -93,7 +79,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
Close(); Close();
try try
{ {
if (OpenArchive(inStream, _db) != S_OK) if (_db.Open(inStream) != S_OK)
return S_FALSE; return S_FALSE;
_stream = inStream; _stream = inStream;
} }
@@ -129,25 +115,29 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
} }
RINOK(extractCallback->SetTotal(totalSize)); RINOK(extractCallback->SetTotal(totalSize));
UInt64 currentTotalSize = 0, currentItemSize = 0; UInt64 totalPackSize;
totalSize = totalPackSize = 0;
CByteBuffer sect; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
sect.SetCapacity((UInt32)1 << _db.SectorSizeBits); CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
for (i = 0; i < numItems; i++)
{ {
RINOK(extractCallback->SetCompleted(&currentTotalSize)); lps->InSize = totalPackSize;
lps->OutSize = totalSize;
RINOK(lps->SetCur());
Int32 index = allFilesMode ? i : indices[i]; Int32 index = allFilesMode ? i : indices[i];
const CItem &item = _db.Items[_db.Refs[index].Did]; const CItem &item = _db.Items[_db.Refs[index].Did];
currentItemSize = 0;
if (!item.IsDir())
currentItemSize = item.Size;
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> outStream;
Int32 askMode = testMode ? Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract; NArchive::NExtract::NAskMode::kExtract;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->GetStream(index, &outStream, askMode));
if (item.IsDir()) if (item.IsDir())
{ {
@@ -155,75 +145,31 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
continue; continue;
} }
if (!testMode && (!realOutStream))
totalPackSize += _db.GetItemPackSize(item.Size);
totalSize += item.Size;
if (!testMode && (!outStream))
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->PrepareOperation(askMode));
Int32 res = NArchive::NExtract::NOperationResult::kDataError; Int32 res = NArchive::NExtract::NOperationResult::kDataError;
CMyComPtr<ISequentialInStream> inStream;
HRESULT hres = GetStream(index, &inStream);
if (hres == S_FALSE)
res = NArchive::NExtract::NOperationResult::kDataError;
else if (hres == E_NOTIMPL)
res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
else
{ {
UInt32 sid = item.Sid; RINOK(hres);
UInt64 prev = 0; if (inStream)
for (UInt64 pos = 0;;)
{ {
if (sid == NFatID::kEndOfChain) RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
{ if (copyCoderSpec->TotalSize == item.Size)
if (pos != item.Size)
break;
res = NArchive::NExtract::NOperationResult::kOK; res = NArchive::NExtract::NOperationResult::kOK;
break;
}
if (pos >= item.Size)
break;
UInt64 offset;
UInt32 size;
if (_db.IsLargeStream(item.Size))
{
if (pos - prev > (1 << 20))
{
UInt64 processed = currentTotalSize + pos;
RINOK(extractCallback->SetCompleted(&processed));
prev = pos;
}
size = 1 << _db.SectorSizeBits;
offset = ((UInt64)sid + 1) << _db.SectorSizeBits;
if (sid >= _db.FatSize)
break;
sid = _db.Fat[sid];
}
else
{
int subBits = (_db.SectorSizeBits - _db.MiniSectorSizeBits);
UInt32 fid = sid >> subBits;
if (fid >= _db.NumSectorsInMiniStream)
break;
size = 1 << _db.MiniSectorSizeBits;
offset = (((UInt64)_db.MiniSids[fid] + 1) << _db.SectorSizeBits) +
((sid & ((1 << subBits) - 1)) << _db.MiniSectorSizeBits);
if (sid >= _db.MatSize)
break;
sid = _db.Mat[sid];
}
// last sector can be smaller than sector size (it can contain requied data only).
UInt64 rem = item.Size - pos;
if (size > rem)
size = (UInt32)rem;
RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
size_t realProcessedSize = size;
RINOK(ReadStream(_stream, sect, &realProcessedSize));
if (realProcessedSize != size)
break;
if (realOutStream)
{
RINOK(WriteStream(realOutStream, sect, size));
}
pos += size;
} }
} }
realOutStream.Release(); outStream.Release();
RINOK(extractCallback->SetOperationResult(res)); RINOK(extractCallback->SetOperationResult(res));
} }
return S_OK; return S_OK;
@@ -236,4 +182,58 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK; return S_OK;
} }
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
*stream = 0;
const CItem &item = _db.Items[_db.Refs[index].Did];
CClusterInStream *streamSpec = new CClusterInStream;
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
streamSpec->Stream = _stream;
streamSpec->StartOffset = 0;
bool isLargeStream = _db.IsLargeStream(item.Size);
int bsLog = isLargeStream ? _db.SectorSizeBits : _db.MiniSectorSizeBits;
streamSpec->BlockSizeLog = bsLog;
streamSpec->Size = item.Size;
UInt32 clusterSize = (UInt32)1 << bsLog;
UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog;
if (numClusters64 >= ((UInt32)1 << 31))
return E_NOTIMPL;
streamSpec->Vector.Reserve((int)numClusters64);
UInt32 sid = item.Sid;
UInt64 size = item.Size;
if (size != 0)
{
for (;; size -= clusterSize)
{
if (isLargeStream)
{
if (sid >= _db.FatSize)
return S_FALSE;
streamSpec->Vector.Add(sid + 1);
sid = _db.Fat[sid];
}
else
{
UInt64 val;
if (sid >= _db.MatSize || !_db.GetMiniCluster(sid, val) || val >= (UInt64)1 << 32)
return S_FALSE;
streamSpec->Vector.Add((UInt32)val);
sid = _db.Mat[sid];
}
if (size <= clusterSize)
break;
}
}
if (sid != NFatID::kEndOfChain)
return S_FALSE;
RINOK(streamSpec->InitAndSeek());
*stream = streamTemp.Detach();
return S_OK;
COM_TRY_END
}
}} }}

View File

@@ -12,15 +12,15 @@ namespace NCom {
class CHandler: class CHandler:
public IInArchive, public IInArchive,
public IInArchiveGetStream,
public CMyUnknownImp public CMyUnknownImp
{ {
public:
MY_UNKNOWN_IMP1(IInArchive)
INTERFACE_IInArchive(;)
private:
CMyComPtr<IInStream> _stream; CMyComPtr<IInStream> _stream;
CDatabase _db; CDatabase _db;
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
}; };
}} }}

View File

@@ -2,19 +2,19 @@
#include "StdAfx.h" #include "StdAfx.h"
extern "C"
{
#include "../../../../C/Alloc.h" #include "../../../../C/Alloc.h"
}
#include "../../../../C/CpuArch.h" #include "../../../../C/CpuArch.h"
#include "Common/MyCom.h"
#include "../../Common/StreamUtils.h"
#include "Common/IntToString.h" #include "Common/IntToString.h"
#include "Common/MyCom.h"
#include "../../Common/StreamUtils.h"
#include "ComIn.h" #include "ComIn.h"
#define Get16(p) GetUi16(p)
#define Get32(p) GetUi32(p)
namespace NArchive{ namespace NArchive{
namespace NCom{ namespace NCom{
@@ -50,31 +50,40 @@ static HRESULT ReadIDs(IInStream *inStream, Byte *buf, int sectorSizeBits, UInt3
RINOK(ReadSector(inStream, buf, sectorSizeBits, sid)); RINOK(ReadSector(inStream, buf, sectorSizeBits, sid));
UInt32 sectorSize = (UInt32)1 << sectorSizeBits; UInt32 sectorSize = (UInt32)1 << sectorSizeBits;
for (UInt32 t = 0; t < sectorSize; t += 4) for (UInt32 t = 0; t < sectorSize; t += 4)
*dest++ = GetUi32(buf + t); *dest++ = Get32(buf + t);
return S_OK; return S_OK;
} }
static void GetFileTimeFromMem(const Byte *p, FILETIME *ft) static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
{ {
ft->dwLowDateTime = GetUi32(p); ft->dwLowDateTime = Get32(p);
ft->dwHighDateTime = GetUi32(p + 4); ft->dwHighDateTime = Get32(p + 4);
} }
static void ReadItem(Byte *p, CItem &item, bool mode64bit) void CItem::Parse(const Byte *p, bool mode64bit)
{ {
memcpy(item.Name, p, 64); memcpy(Name, p, kNameSizeMax);
// item.NameSize = GetUi16(p + 64); // NameSize = Get16(p + 64);
item.Type = p[66]; Type = p[66];
item.LeftDid = GetUi32(p + 68); LeftDid = Get32(p + 68);
item.RightDid = GetUi32(p + 72); RightDid = Get32(p + 72);
item.SonDid = GetUi32(p + 76); SonDid = Get32(p + 76);
// item.Flags = GetUi32(p + 96); // Flags = Get32(p + 96);
GetFileTimeFromMem(p + 100, &item.CTime); GetFileTimeFromMem(p + 100, &CTime);
GetFileTimeFromMem(p + 108, &item.MTime); GetFileTimeFromMem(p + 108, &MTime);
item.Sid = GetUi32(p + 116); Sid = Get32(p + 116);
item.Size = GetUi32(p + 120); Size = Get32(p + 120);
if (mode64bit) if (mode64bit)
item.Size |= ((UInt64)GetUi32(p + 124) << 32); Size |= ((UInt64)Get32(p + 124) << 32);
}
void CDatabase::Clear()
{
Fat.Free();
MiniSids.Free();
Mat.Free();
Items.Clear();
Refs.Clear();
} }
static const UInt32 kNoDid = 0xFFFFFFFF; static const UInt32 kNoDid = 0xFFFFFFFF;
@@ -106,13 +115,6 @@ HRESULT CDatabase::AddNode(int parent, UInt32 did)
static const char kCharOpenBracket = '['; static const char kCharOpenBracket = '[';
static const char kCharCloseBracket = ']'; static const char kCharCloseBracket = ']';
UString DWORDToString(UInt32 val)
{
wchar_t buf[32];
ConvertUInt64ToString(val, buf);
return buf;
}
static UString CompoundNameToFileName(const UString &s) static UString CompoundNameToFileName(const UString &s)
{ {
UString res; UString res;
@@ -122,7 +124,9 @@ static UString CompoundNameToFileName(const UString &s)
if (c < 0x20) if (c < 0x20)
{ {
res += kCharOpenBracket; res += kCharOpenBracket;
res += DWORDToString(c); wchar_t buf[32];
ConvertUInt32ToString(c, buf);
res += buf;
res += kCharCloseBracket; res += kCharCloseBracket;
} }
else else
@@ -201,31 +205,30 @@ UString CDatabase::GetItemPath(UInt32 index) const
return s; return s;
} }
HRESULT OpenArchive(IInStream *inStream, CDatabase &db) HRESULT CDatabase::Open(IInStream *inStream)
{ {
static const UInt32 kHeaderSize = 512; static const UInt32 kHeaderSize = 512;
Byte p[kHeaderSize]; Byte p[kHeaderSize];
RINOK(ReadStream_FALSE(inStream, p, kHeaderSize)); RINOK(ReadStream_FALSE(inStream, p, kHeaderSize));
if (memcmp(p, kSignature, kSignatureSize) != 0) if (memcmp(p, kSignature, kSignatureSize) != 0)
return S_FALSE; return S_FALSE;
UInt16 majorVer = GetUi16(p + 0x1A); if (Get16(p + 0x1A) > 4) // majorVer
if (majorVer > 4)
return S_FALSE; return S_FALSE;
if (GetUi16(p + 0x1C) != 0xFFFE) if (Get16(p + 0x1C) != 0xFFFE)
return S_FALSE; return S_FALSE;
UInt16 sectorSizeBits = GetUi16(p + 0x1E); int sectorSizeBits = Get16(p + 0x1E);
bool mode64bit = (sectorSizeBits >= 12); bool mode64bit = (sectorSizeBits >= 12);
UInt16 miniSectorSizeBits = GetUi16(p + 0x20); int miniSectorSizeBits = Get16(p + 0x20);
db.SectorSizeBits = sectorSizeBits; SectorSizeBits = sectorSizeBits;
db.MiniSectorSizeBits = miniSectorSizeBits; MiniSectorSizeBits = miniSectorSizeBits;
if (sectorSizeBits > 28 || miniSectorSizeBits > 28 || if (sectorSizeBits > 28 || miniSectorSizeBits > 28 ||
sectorSizeBits < 7 || miniSectorSizeBits < 2 || miniSectorSizeBits > sectorSizeBits) sectorSizeBits < 7 || miniSectorSizeBits < 2 || miniSectorSizeBits > sectorSizeBits)
return S_FALSE; return S_FALSE;
UInt32 numSectorsForFAT = GetUi32(p + 0x2C); UInt32 numSectorsForFAT = Get32(p + 0x2C);
db.LongStreamMinSize = GetUi32(p + 0x38); LongStreamMinSize = Get32(p + 0x38);
UInt32 sectSize = (UInt32)1 << (int)(sectorSizeBits); UInt32 sectSize = (UInt32)1 << (int)sectorSizeBits;
CByteBuffer sect; CByteBuffer sect;
sect.SetCapacity(sectSize); sect.SetCapacity(sectSize);
@@ -235,11 +238,11 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
UInt32 numFatItems = numSectorsForFAT << ssb2; UInt32 numFatItems = numSectorsForFAT << ssb2;
if ((numFatItems >> ssb2) != numSectorsForFAT) if ((numFatItems >> ssb2) != numSectorsForFAT)
return S_FALSE; return S_FALSE;
db.FatSize = numFatItems; FatSize = numFatItems;
{ {
CUInt32Buf bat; CUInt32Buf bat;
UInt32 numSectorsForBat = GetUi32(p + 0x48); UInt32 numSectorsForBat = Get32(p + 0x48);
const UInt32 kNumHeaderBatItems = 109; const UInt32 kNumHeaderBatItems = 109;
UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2); UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2);
if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat) if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat)
@@ -248,8 +251,8 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
return S_FALSE; return S_FALSE;
UInt32 i; UInt32 i;
for (i = 0; i < kNumHeaderBatItems; i++) for (i = 0; i < kNumHeaderBatItems; i++)
bat[i] = GetUi32(p + 0x4c + i * 4); bat[i] = Get32(p + 0x4c + i * 4);
UInt32 sid = GetUi32(p + 0x44); UInt32 sid = Get32(p + 0x44);
for (UInt32 s = 0; s < numSectorsForBat; s++) for (UInt32 s = 0; s < numSectorsForBat; s++)
{ {
RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, bat + i)); RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, bat + i));
@@ -258,7 +261,7 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
} }
numBatItems = i; numBatItems = i;
if (!db.Fat.Allocate(numFatItems)) if (!Fat.Allocate(numFatItems))
return S_FALSE; return S_FALSE;
UInt32 j = 0; UInt32 j = 0;
@@ -266,33 +269,33 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
{ {
if (j >= numBatItems) if (j >= numBatItems)
return S_FALSE; return S_FALSE;
RINOK(ReadIDs(inStream, sect, sectorSizeBits, bat[j], db.Fat + i)); RINOK(ReadIDs(inStream, sect, sectorSizeBits, bat[j], Fat + i));
} }
} }
UInt32 numMatItems; UInt32 numMatItems;
{ {
UInt32 numSectorsForMat = GetUi32(p + 0x40); UInt32 numSectorsForMat = Get32(p + 0x40);
numMatItems = (UInt32)numSectorsForMat << ssb2; numMatItems = (UInt32)numSectorsForMat << ssb2;
if ((numMatItems >> ssb2) != numSectorsForMat) if ((numMatItems >> ssb2) != numSectorsForMat)
return S_FALSE; return S_FALSE;
if (!db.Mat.Allocate(numMatItems)) if (!Mat.Allocate(numMatItems))
return S_FALSE; return S_FALSE;
UInt32 i; UInt32 i;
UInt32 sid = GetUi32(p + 0x3C); UInt32 sid = Get32(p + 0x3C);
for (i = 0; i < numMatItems; i += numSidsInSec) for (i = 0; i < numMatItems; i += numSidsInSec)
{ {
RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, db.Mat + i)); RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, Mat + i));
if (sid >= numFatItems) if (sid >= numFatItems)
return S_FALSE; return S_FALSE;
sid = db.Fat[sid]; sid = Fat[sid];
} }
if (sid != NFatID::kEndOfChain) if (sid != NFatID::kEndOfChain)
return S_FALSE; return S_FALSE;
} }
{ {
UInt32 sid = GetUi32(p + 0x30); UInt32 sid = Get32(p + 0x30);
for (;;) for (;;)
{ {
if (sid >= numFatItems) if (sid >= numFatItems)
@@ -301,16 +304,16 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
for (UInt32 i = 0; i < sectSize; i += 128) for (UInt32 i = 0; i < sectSize; i += 128)
{ {
CItem item; CItem item;
ReadItem(sect + i, item, mode64bit); item.Parse(sect + i, mode64bit);
db.Items.Add(item); Items.Add(item);
} }
sid = db.Fat[sid]; sid = Fat[sid];
if (sid == NFatID::kEndOfChain) if (sid == NFatID::kEndOfChain)
break; break;
} }
} }
CItem root = db.Items[0]; CItem root = Items[0];
{ {
UInt32 numSectorsInMiniStream; UInt32 numSectorsInMiniStream;
@@ -320,19 +323,18 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
return S_FALSE; return S_FALSE;
numSectorsInMiniStream = (UInt32)numSatSects64; numSectorsInMiniStream = (UInt32)numSatSects64;
} }
db.NumSectorsInMiniStream = numSectorsInMiniStream; NumSectorsInMiniStream = numSectorsInMiniStream;
if (!db.MiniSids.Allocate(numSectorsInMiniStream)) if (!MiniSids.Allocate(numSectorsInMiniStream))
return S_FALSE; return S_FALSE;
{ {
UInt64 matSize64 = (root.Size + ((UInt64)1 << miniSectorSizeBits) - 1) >> miniSectorSizeBits; UInt64 matSize64 = (root.Size + ((UInt64)1 << miniSectorSizeBits) - 1) >> miniSectorSizeBits;
if (matSize64 > NFatID::kMaxValue) if (matSize64 > NFatID::kMaxValue)
return S_FALSE; return S_FALSE;
db.MatSize = (UInt32)matSize64; MatSize = (UInt32)matSize64;
if (numMatItems < db.MatSize) if (numMatItems < MatSize)
return S_FALSE; return S_FALSE;
} }
UInt32 sid = root.Sid; UInt32 sid = root.Sid;
for (UInt32 i = 0; ; i++) for (UInt32 i = 0; ; i++)
{ {
@@ -344,14 +346,14 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
} }
if (i >= numSectorsInMiniStream) if (i >= numSectorsInMiniStream)
return S_FALSE; return S_FALSE;
db.MiniSids[i] = sid; MiniSids[i] = sid;
if (sid >= numFatItems) if (sid >= numFatItems)
return S_FALSE; return S_FALSE;
sid = db.Fat[sid]; sid = Fat[sid];
} }
} }
return db.AddNode(-1, root.SonDid); return AddNode(-1, root.SonDid);
} }
}} }}

View File

@@ -57,6 +57,8 @@ struct CItem
bool IsEmpty() const { return Type == NItemType::kEmpty; } bool IsEmpty() const { return Type == NItemType::kEmpty; }
bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; } bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; }
void Parse(const Byte *p, bool mode64bit);
}; };
struct CRef struct CRef
@@ -67,15 +69,15 @@ struct CRef
class CDatabase class CDatabase
{ {
public: UInt32 NumSectorsInMiniStream;
CUInt32Buf MiniSids;
HRESULT AddNode(int parent, UInt32 did); HRESULT AddNode(int parent, UInt32 did);
public:
CUInt32Buf Fat; CUInt32Buf Fat;
UInt32 FatSize; UInt32 FatSize;
CUInt32Buf MiniSids;
UInt32 NumSectorsInMiniStream;
CUInt32Buf Mat; CUInt32Buf Mat;
UInt32 MatSize; UInt32 MatSize;
@@ -86,20 +88,29 @@ public:
int SectorSizeBits; int SectorSizeBits;
int MiniSectorSizeBits; int MiniSectorSizeBits;
void Clear() void Clear();
bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; }
UString GetItemPath(UInt32 index) const;
UInt64 GetItemPackSize(UInt64 size) const
{ {
Fat.Free(); UInt64 mask = ((UInt64)1 << (IsLargeStream(size) ? SectorSizeBits : MiniSectorSizeBits)) - 1;
MiniSids.Free(); return (size + mask) & ~mask;
Mat.Free();
Items.Clear();
Refs.Clear();
} }
bool IsLargeStream(UInt64 size) { return size >= LongStreamMinSize; } bool GetMiniCluster(UInt32 sid, UInt64 &res) const
UString GetItemPath(UInt32 index) const; {
int subBits = SectorSizeBits - MiniSectorSizeBits;
UInt32 fid = sid >> subBits;
if (fid >= NumSectorsInMiniStream)
return false;
res = (((UInt64)MiniSids[fid] + 1) << subBits) + (sid & ((1 << subBits) - 1));
return true;
}
HRESULT Open(IInStream *inStream);
}; };
HRESULT OpenArchive(IInStream *inStream, CDatabase &database);
}} }}

View File

@@ -82,11 +82,11 @@ static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5;
static bool AreEqual(const UString &methodName, const wchar_t *s) static bool AreEqual(const UString &methodName, const wchar_t *s)
{ return (methodName.CompareNoCase(s) == 0); } { return (methodName.CompareNoCase(s) == 0); }
static inline bool IsLZMAMethod(const UString &methodName) bool COneMethodInfo::IsLzma() const
{ {
return return
AreEqual(methodName, kLZMAMethodName) || AreEqual(MethodName, kLZMAMethodName) ||
AreEqual(methodName, kLZMA2MethodName); AreEqual(MethodName, kLZMA2MethodName);
} }
static inline bool IsBZip2Method(const UString &methodName) static inline bool IsBZip2Method(const UString &methodName)
@@ -109,8 +109,12 @@ struct CNameToPropID
const wchar_t *Name; const wchar_t *Name;
}; };
CNameToPropID g_NameToPropID[] = 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::kOrder, VT_UI4, L"O" },
{ NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, { NCoderPropID::kPosStateBits, VT_UI4, L"PB" },
{ NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, { NCoderPropID::kLitContextBits, VT_UI4, L"LC" },
@@ -122,7 +126,8 @@ CNameToPropID g_NameToPropID[] =
{ NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },
{ NCoderPropID::kAlgorithm, VT_UI4, L"a" }, { NCoderPropID::kAlgorithm, VT_UI4, L"a" },
{ NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },
{ NCoderPropID::kNumThreads, VT_UI4, L"mt" } { NCoderPropID::kNumThreads, VT_UI4, L"mt" },
{ NCoderPropID::kDefaultProp, VT_UI4, L"" }
}; };
static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
@@ -154,7 +159,7 @@ static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVar
return false; return false;
} }
static int FindPropIdFromStringName(const UString &name) static int FindPropIdExact(const UString &name)
{ {
for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
@@ -162,16 +167,26 @@ static int FindPropIdFromStringName(const UString &name)
return -1; return -1;
} }
static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, static int FindPropIdStart(const UString &name)
const NWindows::NCOM::CPropVariant &value)
{ {
for (int j = 0; j < oneMethodInfo.Props.Size(); j++) for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
if (oneMethodInfo.Props[j].Id == propID) {
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; return;
CProp prop; CProp prop;
prop.Id = propID; prop.Id = propID;
prop.Value = value; prop.Value = value;
oneMethodInfo.Props.Add(prop); m.Props.Add(prop);
} }
void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
@@ -184,7 +199,7 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
if (oneMethodInfo.MethodName.IsEmpty()) if (oneMethodInfo.MethodName.IsEmpty())
oneMethodInfo.MethodName = kDefaultMethodName; oneMethodInfo.MethodName = kDefaultMethodName;
if (IsLZMAMethod(oneMethodInfo.MethodName)) if (oneMethodInfo.IsLzma())
{ {
UInt32 dicSize = UInt32 dicSize =
(level >= 9 ? kLzmaDicSizeX9 : (level >= 9 ? kLzmaDicSizeX9 :
@@ -205,12 +220,12 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
(level >= 5 ? kLzmaMatchFinderX5 : (level >= 5 ? kLzmaMatchFinderX5 :
kLzmaMatchFinderX1); kLzmaMatchFinderX1);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);
#ifdef COMPRESS_MT #ifdef COMPRESS_MT
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
#endif #endif
} }
else if (IsDeflateMethod(oneMethodInfo.MethodName)) else if (IsDeflateMethod(oneMethodInfo.MethodName))
@@ -229,9 +244,9 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
(level >= 5 ? kDeflateAlgoX5 : (level >= 5 ? kDeflateAlgoX5 :
kDeflateAlgoX1); kDeflateAlgoX1);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
} }
else if (IsBZip2Method(oneMethodInfo.MethodName)) else if (IsBZip2Method(oneMethodInfo.MethodName))
{ {
@@ -245,10 +260,10 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
(level >= 3 ? kBZip2DicSizeX3 : (level >= 3 ? kBZip2DicSizeX3 :
kBZip2DicSizeX1)); kBZip2DicSizeX1));
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
#ifdef COMPRESS_MT #ifdef COMPRESS_MT
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
#endif #endif
} }
else if (IsPpmdMethod(oneMethodInfo.MethodName)) else if (IsPpmdMethod(oneMethodInfo.MethodName))
@@ -265,8 +280,8 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
(level >= 5 ? kPpmdOrderX5 : (level >= 5 ? kPpmdOrderX5 :
kPpmdOrderX1))); kPpmdOrderX1)));
SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);
SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);
} }
} }
@@ -316,25 +331,22 @@ static void SplitParam(const UString &param, UString &name, UString &value)
HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)
{ {
CProp prop; CProp prop;
if (name.CompareNoCase(L"D") == 0 || int index = FindPropIdExact(name);
name.CompareNoCase(L"MEM") == 0) 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; UInt32 dicSize;
RINOK(ParsePropDictionaryValue(value, dicSize)); RINOK(ParsePropDictionaryValue(value, dicSize));
prop.Id = (name.CompareNoCase(L"D") == 0) ?
NCoderPropID::kDictionarySize :
NCoderPropID::kUsedMemorySize;
prop.Value = dicSize; prop.Value = dicSize;
} }
else else
{ {
int index = FindPropIdFromStringName(name);
if (index < 0)
return E_INVALIDARG;
const CNameToPropID &nameToPropID = g_NameToPropID[index];
prop.Id = nameToPropID.PropID;
NCOM::CPropVariant propValue; NCOM::CPropVariant propValue;
if (nameToPropID.VarType == VT_BSTR) if (nameToPropID.VarType == VT_BSTR)
@@ -465,7 +477,7 @@ void COutHandler::Init()
WriteMTime = true; WriteMTime = true;
#ifdef COMPRESS_MT #ifdef COMPRESS_MT
_numThreads = NWindows::NSystem::GetNumberOfProcessors(); _numThreads = NSystem::GetNumberOfProcessors();
#endif #endif
_level = 5; _level = 5;
@@ -576,35 +588,26 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
} }
else else
{ {
int index = FindPropIdStart(realName);
if (index < 0)
return E_INVALIDARG;
const CNameToPropID &nameToPropID = g_NameToPropID[index];
CProp prop; CProp prop;
if (realName.Left(1).CompareNoCase(L"D") == 0) prop.Id = nameToPropID.PropID;
if (prop.Id == NCoderPropID::kBlockSize ||
prop.Id == NCoderPropID::kDictionarySize ||
prop.Id == NCoderPropID::kUsedMemorySize)
{ {
UInt32 dicSize; UInt32 dicSize;
RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize)); RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize));
prop.Id = NCoderPropID::kDictionarySize;
prop.Value = dicSize;
if (number <= mainDicMethodIndex)
mainDicSize = dicSize;
}
else if (realName.Left(1).CompareNoCase(L"C") == 0)
{
UInt32 blockSize;
RINOK(ParsePropDictionaryValue(realName.Mid(1), value, blockSize));
prop.Id = NCoderPropID::kBlockSize;
prop.Value = blockSize;
}
else if (realName.Left(3).CompareNoCase(L"MEM") == 0)
{
UInt32 dicSize;
RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize));
prop.Id = NCoderPropID::kUsedMemorySize;
prop.Value = dicSize; prop.Value = dicSize;
if (number <= mainDicMethodIndex) if (number <= mainDicMethodIndex)
mainDicSize = dicSize; mainDicSize = dicSize;
} }
else else
{ {
int index = FindPropIdFromStringName(realName); int index = FindPropIdExact(realName);
if (index < 0) if (index < 0)
return E_INVALIDARG; return E_INVALIDARG;
const CNameToPropID &nameToPropID = g_NameToPropID[index]; const CNameToPropID &nameToPropID = g_NameToPropID[index];

View File

@@ -12,6 +12,8 @@ struct COneMethodInfo
{ {
CObjectVector<CProp> Props; CObjectVector<CProp> Props;
UString MethodName; UString MethodName;
bool IsLzma() const;
}; };
class COutHandler class COutHandler

View File

@@ -1,15 +1,13 @@
// InStreamWithCRC.h // InStreamWithCRC.h
#ifndef __INSTREAMWITHCRC_H #ifndef __IN_STREAM_WITH_CRC_H
#define __INSTREAMWITHCRC_H #define __IN_STREAM_WITH_CRC_H
#include "../../../../C/7zCrc.h"
#include "../../../Common/MyCom.h" #include "../../../Common/MyCom.h"
#include "../../IStream.h"
extern "C" #include "../../IStream.h"
{
#include "../../../../C/7zCrc.h"
}
class CSequentialInStreamWithCRC: class CSequentialInStreamWithCRC:
public ISequentialInStream, public ISequentialInStream,

View File

@@ -6,19 +6,13 @@
STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
{ {
UInt32 realProcessedSize; HRESULT result = S_OK;
HRESULT result; if (_stream)
if(!_stream) result = _stream->Write(data, size, &size);
{
realProcessedSize = size;
result = S_OK;
}
else
result = _stream->Write(data, size, &realProcessedSize);
if (_calculate) if (_calculate)
_crc = CrcUpdate(_crc, data, realProcessedSize); _crc = CrcUpdate(_crc, data, size);
_size += realProcessedSize; _size += size;
if(processedSize != NULL) if (processedSize != NULL)
*processedSize = realProcessedSize; *processedSize = size;
return result; return result;
} }

View File

@@ -3,13 +3,11 @@
#ifndef __OUT_STREAM_WITH_CRC_H #ifndef __OUT_STREAM_WITH_CRC_H
#define __OUT_STREAM_WITH_CRC_H #define __OUT_STREAM_WITH_CRC_H
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
extern "C"
{
#include "../../../../C/7zCrc.h" #include "../../../../C/7zCrc.h"
}
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
class COutStreamWithCRC: class COutStreamWithCRC:
public ISequentialOutStream, public ISequentialOutStream,

View File

@@ -6,19 +6,13 @@
STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize)
{ {
UInt32 realProcessedSize; HRESULT result = S_OK;
HRESULT result; if (_stream)
if(!_stream) result = _stream->Write(data, size, &size);
{
realProcessedSize = size;
result = S_OK;
}
else
result = _stream->Write(data, size, &realProcessedSize);
if (_calculate) if (_calculate)
_sha.Update((const Byte *)data, realProcessedSize); _sha.Update((const Byte *)data, size);
_size += realProcessedSize; _size += size;
if(processedSize != NULL) if (processedSize != NULL)
*processedSize = realProcessedSize; *processedSize = size;
return result; return result;
} }

View File

@@ -3,13 +3,11 @@
#ifndef __OUT_STREAM_WITH_SHA1_H #ifndef __OUT_STREAM_WITH_SHA1_H
#define __OUT_STREAM_WITH_SHA1_H #define __OUT_STREAM_WITH_SHA1_H
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
#include "../../Crypto/Sha1.h" #include "../../Crypto/Sha1.h"
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
class COutStreamWithSha1: class COutStreamWithSha1:
public ISequentialOutStream, public ISequentialOutStream,

View File

@@ -1,240 +0,0 @@
// CpioHandler.cpp
#include "StdAfx.h"
#include "Common/ComTry.h"
#include "Common/Defs.h"
#include "Common/NewHandler.h"
#include "Common/StringConvert.h"
#include "Windows/PropVariant.h"
#include "Windows/Time.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/ProgressUtils.h"
#include "../../Compress/CopyCoder.h"
#include "../Common/ItemNameUtils.h"
#include "CpioHandler.h"
#include "CpioIn.h"
using namespace NWindows;
using namespace NTime;
namespace NArchive {
namespace NCpio {
/*
enum
{
kpidinode = kpidUserDefined,
kpidiChkSum
};
*/
STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidPackSize, VT_UI8},
{ NULL, kpidMTime, VT_FILETIME},
// { NULL, kpidUser, VT_BSTR},
// { NULL, kpidGroup, VT_BSTR},
// { L"inode", kpidinode, VT_UI4}
// { L"CheckSum", kpidiChkSum, VT_UI4}
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO
STDMETHODIMP CHandler::Open(IInStream *stream,
const UInt64 * /* maxCheckStartPosition */,
IArchiveOpenCallback *callback)
{
COM_TRY_BEGIN
// try
{
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));
_items.Clear();
for (;;)
{
CItemEx item;
bool filled;
HRESULT result = archive.GetNextItem(filled, item);
if (result == S_FALSE)
return S_FALSE;
if (result != S_OK)
return S_FALSE;
if (!filled)
break;
_items.Add(item);
archive.SkeepDataRecords(item.Size, item.Align);
if (callback != NULL)
{
if (needSetTotal)
{
RINOK(callback->SetTotal(NULL, &endPos));
needSetTotal = false;
}
if (_items.Size() % 100 == 0)
{
UInt64 numFiles = _items.Size();
UInt64 numBytes = item.HeaderPosition;
RINOK(callback->SetCompleted(&numFiles, &numBytes));
}
}
}
if (_items.Size() == 0)
return S_FALSE;
_inStream = stream;
}
/*
catch(...)
{
return S_FALSE;
}
*/
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
_items.Clear();
_inStream.Release();
return S_OK;
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = _items.Size();
return S_OK;
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
const CItemEx &item = _items[index];
switch(propID)
{
case kpidPath:
prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP));
break;
case kpidIsDir:
prop = item.IsDir();
break;
case kpidSize:
case kpidPackSize:
prop = (UInt64)item.Size;
break;
case kpidMTime:
{
FILETIME utcFileTime;
if (item.ModificationTime != 0)
NTime::UnixTimeToFileTime(item.ModificationTime, utcFileTime);
else
{
utcFileTime.dwLowDateTime = 0;
utcFileTime.dwHighDateTime = 0;
}
prop = utcFileTime;
break;
}
/*
case kpidinode: prop = item.inode; break;
case kpidiChkSum: prop = item.ChkSum; break;
*/
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
bool testMode = (_aTestMode != 0);
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]].Size;
extractCallback->SetTotal(totalSize);
UInt64 currentTotalSize = 0;
UInt64 currentItemSize;
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(_inStream);
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
{
lps->InSize = lps->OutSize = currentTotalSize;
RINOK(lps->SetCur());
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NArchive::NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i];
const CItemEx &item = _items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
currentItemSize = item.Size;
if (item.IsDir())
{
RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
continue;
}
if (!testMode && (!realOutStream))
continue;
RINOK(extractCallback->PrepareOperation(askMode));
if (testMode)
{
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
continue;
}
RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
streamSpec->Init(item.Size);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
realOutStream.Release();
RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
NArchive::NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kDataError));
}
return S_OK;
COM_TRY_END
}
}}

View File

@@ -1,30 +0,0 @@
// Archive/cpio/Handler.h
#ifndef __ARCHIVE_CPIO_HANDLER_H
#define __ARCHIVE_CPIO_HANDLER_H
#include "Common/MyCom.h"
#include "../IArchive.h"
#include "CpioItem.h"
namespace NArchive {
namespace NCpio {
class CHandler:
public IInArchive,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(IInArchive)
INTERFACE_IInArchive(;)
private:
CObjectVector<CItemEx> _items;
CMyComPtr<IInStream> _inStream;
};
}}
#endif

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